diff options
Diffstat (limited to 'core/java/android/content')
95 files changed, 0 insertions, 32302 deletions
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java deleted file mode 100644 index ce6501c..0000000 --- a/core/java/android/content/AbstractSyncableContentProvider.java +++ /dev/null @@ -1,601 +0,0 @@ -package android.content; - -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteDatabase; -import android.database.Cursor; -import android.net.Uri; -import android.accounts.AccountMonitor; -import android.accounts.AccountMonitorListener; -import android.provider.SyncConstValue; -import android.util.Config; -import android.util.Log; -import android.os.Bundle; -import android.text.TextUtils; - -import java.util.Collections; -import java.util.Map; -import java.util.HashMap; -import java.util.Vector; -import java.util.ArrayList; - -/** - * 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 AbstractSyncableContentProvider extends SyncableContentProvider { - private static final String TAG = "SyncableContentProvider"; - protected SQLiteOpenHelper mOpenHelper; - protected SQLiteDatabase mDb; - private final String mDatabaseName; - private final int mDatabaseVersion; - private final Uri mContentUri; - private AccountMonitor mAccountMonitor; - - /** the account set in the last call to onSyncStart() */ - private String mSyncingAccount; - - private SyncStateContentProviderHelper mSyncState = null; - - private static final String[] sAccountProjection = new String[] {SyncConstValue._SYNC_ACCOUNT}; - - private boolean mIsTemporary; - - private AbstractTableMerger mCurrentMerger = null; - private boolean mIsMergeCancelled = false; - - private static final String SYNC_ACCOUNT_WHERE_CLAUSE = SyncConstValue._SYNC_ACCOUNT + "=?"; - - protected boolean isTemporary() { - return mIsTemporary; - } - - /** - * Indicates whether or not this ContentProvider contains a full - * set of data or just diffs. This knowledge comes in handy when - * determining how to incorporate the contents of a temporary - * provider into a real provider. - */ - private boolean mContainsDiffs; - - /** - * Initializes the AbstractSyncableContentProvider - * @param dbName the filename of the database - * @param dbVersion the current version of the database schema - * @param contentUri The base Uri of the syncable content in this provider - */ - public AbstractSyncableContentProvider(String dbName, int dbVersion, Uri contentUri) { - super(); - - mDatabaseName = dbName; - mDatabaseVersion = dbVersion; - mContentUri = contentUri; - mIsTemporary = false; - setContainsDiffs(false); - if (Config.LOGV) { - Log.v(TAG, "created SyncableContentProvider " + this); - } - } - - /** - * Close resources that must be closed. You must call this to properly release - * the resources used by the AbstractSyncableContentProvider. - */ - public void close() { - if (mOpenHelper != null) { - mOpenHelper.close(); // OK to call .close() repeatedly. - } - } - - /** - * 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 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 void onDatabaseOpened(SQLiteDatabase db) {} - - private class DatabaseHelper extends SQLiteOpenHelper { - DatabaseHelper(Context context, String name) { - // Note: context and name may be null for temp providers - super(context, name, null, mDatabaseVersion); - } - - @Override - public void onCreate(SQLiteDatabase db) { - bootstrapDatabase(db); - mSyncState.createDatabase(db); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (!upgradeDatabase(db, oldVersion, newVersion)) { - mSyncState.discardSyncData(db, null /* all accounts */); - getContext().getContentResolver().startSync(mContentUri, new Bundle()); - } - } - - @Override - public void onOpen(SQLiteDatabase db) { - onDatabaseOpened(db); - mSyncState.onDatabaseOpened(db); - } - } - - @Override - public boolean onCreate() { - if (isTemporary()) throw new IllegalStateException("onCreate() called for temp provider"); - mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(), mDatabaseName); - mSyncState = new SyncStateContentProviderHelper(mOpenHelper); - - AccountMonitorListener listener = new AccountMonitorListener() { - public void onAccountsUpdated(String[] accounts) { - // Some providers override onAccountsChanged(); give them a database to work with. - mDb = mOpenHelper.getWritableDatabase(); - onAccountsChanged(accounts); - TempProviderSyncAdapter syncAdapter = (TempProviderSyncAdapter)getSyncAdapter(); - if (syncAdapter != null) { - syncAdapter.onAccountsChanged(accounts); - } - } - }; - mAccountMonitor = new AccountMonitor(getContext(), listener); - - return true; - } - - /** - * 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 AbstractSyncableContentProvider getTemporaryInstance() { - AbstractSyncableContentProvider temp; - try { - temp = getClass().newInstance(); - } catch (InstantiationException e) { - throw new RuntimeException("unable to instantiate class, " - + "this should never happen", e); - } catch (IllegalAccessException e) { - throw new RuntimeException( - "IllegalAccess while instantiating class, " - + "this should never happen", e); - } - - // Note: onCreate() isn't run for the temp provider, and it has no Context. - temp.mIsTemporary = true; - temp.setContainsDiffs(true); - temp.mOpenHelper = temp.new DatabaseHelper(null, null); - temp.mSyncState = new SyncStateContentProviderHelper(temp.mOpenHelper); - if (!isTemporary()) { - mSyncState.copySyncState( - mOpenHelper.getReadableDatabase(), - temp.mOpenHelper.getWritableDatabase(), - getSyncingAccount()); - } - return temp; - } - - public SQLiteDatabase getDatabase() { - if (mDb == null) mDb = mOpenHelper.getWritableDatabase(); - return mDb; - } - - public boolean getContainsDiffs() { - return mContainsDiffs; - } - - public void setContainsDiffs(boolean containsDiffs) { - if (containsDiffs && !isTemporary()) { - throw new IllegalStateException( - "only a temporary provider can contain diffs"); - } - mContainsDiffs = containsDiffs; - } - - /** - * Each subclass of this class should define a subclass of {@link - * android.content.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 - * android.content.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 - * android.content.AbstractTableMerger}, one for each table that should be merged. - */ - protected Iterable<? extends AbstractTableMerger> getMergers() { - return Collections.emptyList(); - } - - @Override - public final int update(final Uri url, final ContentValues values, - final String selection, final String[] selectionArgs) { - mDb = mOpenHelper.getWritableDatabase(); - mDb.beginTransaction(); - try { - if (isTemporary() && mSyncState.matches(url)) { - int numRows = mSyncState.asContentProvider().update( - url, values, selection, selectionArgs); - mDb.setTransactionSuccessful(); - return numRows; - } - - int result = updateInternal(url, values, selection, selectionArgs); - mDb.setTransactionSuccessful(); - - if (!isTemporary() && result > 0) { - getContext().getContentResolver().notifyChange(url, null /* observer */, - changeRequiresLocalSync(url)); - } - - return result; - } finally { - mDb.endTransaction(); - } - } - - @Override - public final int delete(final Uri url, final String selection, - final String[] selectionArgs) { - mDb = mOpenHelper.getWritableDatabase(); - mDb.beginTransaction(); - try { - if (isTemporary() && mSyncState.matches(url)) { - int numRows = mSyncState.asContentProvider().delete(url, selection, selectionArgs); - mDb.setTransactionSuccessful(); - return numRows; - } - int result = deleteInternal(url, selection, selectionArgs); - mDb.setTransactionSuccessful(); - if (!isTemporary() && result > 0) { - getContext().getContentResolver().notifyChange(url, null /* observer */, - changeRequiresLocalSync(url)); - } - return result; - } finally { - mDb.endTransaction(); - } - } - - @Override - public final Uri insert(final Uri url, final ContentValues values) { - mDb = mOpenHelper.getWritableDatabase(); - mDb.beginTransaction(); - try { - if (isTemporary() && mSyncState.matches(url)) { - Uri result = mSyncState.asContentProvider().insert(url, values); - mDb.setTransactionSuccessful(); - return result; - } - Uri result = insertInternal(url, values); - mDb.setTransactionSuccessful(); - if (!isTemporary() && result != null) { - getContext().getContentResolver().notifyChange(url, null /* observer */, - changeRequiresLocalSync(url)); - } - return result; - } finally { - mDb.endTransaction(); - } - } - - @Override - public final int bulkInsert(final Uri uri, final ContentValues[] values) { - int size = values.length; - int completed = 0; - final boolean isSyncStateUri = mSyncState.matches(uri); - mDb = mOpenHelper.getWritableDatabase(); - mDb.beginTransaction(); - try { - for (int i = 0; i < size; i++) { - Uri result; - if (isTemporary() && isSyncStateUri) { - result = mSyncState.asContentProvider().insert(uri, values[i]); - } else { - result = insertInternal(uri, values[i]); - mDb.yieldIfContended(); - } - if (result != null) { - completed++; - } - } - mDb.setTransactionSuccessful(); - } finally { - mDb.endTransaction(); - } - if (!isTemporary() && completed == size) { - getContext().getContentResolver().notifyChange(uri, null /* observer */, - changeRequiresLocalSync(uri)); - } - return completed; - } - - /** - * 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 boolean changeRequiresLocalSync(Uri uri) { - return true; - } - - @Override - public final Cursor query(final Uri url, final String[] projection, - final String selection, final String[] selectionArgs, - final String sortOrder) { - mDb = mOpenHelper.getReadableDatabase(); - if (isTemporary() && mSyncState.matches(url)) { - return mSyncState.asContentProvider().query( - url, projection, selection, selectionArgs, sortOrder); - } - return queryInternal(url, projection, selection, selectionArgs, sortOrder); - } - - /** - * Called right before a sync is started. - * - * @param context the sync context for the operation - * @param account - */ - public void onSyncStart(SyncContext context, String account) { - if (TextUtils.isEmpty(account)) { - throw new IllegalArgumentException("you passed in an empty account"); - } - mSyncingAccount = 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 void onSyncStop(SyncContext context, boolean success) { - } - - /** - * The account of the most recent call to onSyncStart() - * @return the account - */ - public String getSyncingAccount() { - return mSyncingAccount; - } - - /** - * 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 void merge(SyncContext context, SyncableContentProvider diffs, - TempProviderSyncResult result, SyncResult syncResult) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - synchronized(this) { - mIsMergeCancelled = false; - } - Iterable<? extends AbstractTableMerger> mergers = getMergers(); - try { - for (AbstractTableMerger merger : mergers) { - synchronized(this) { - if (mIsMergeCancelled) break; - mCurrentMerger = merger; - } - merger.merge(context, getSyncingAccount(), diffs, result, syncResult, this); - } - if (mIsMergeCancelled) return; - if (diffs != null) { - mSyncState.copySyncState( - ((AbstractSyncableContentProvider)diffs).mOpenHelper.getReadableDatabase(), - mOpenHelper.getWritableDatabase(), - getSyncingAccount()); - } - } finally { - synchronized (this) { - mCurrentMerger = null; - } - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - - /** - * Invoked when the active sync has been canceled. Sets the sync state of this provider and - * its merger to canceled. - */ - public void onSyncCanceled() { - synchronized (this) { - mIsMergeCancelled = true; - if (mCurrentMerger != null) { - mCurrentMerger.onMergeCancelled(); - } - } - } - - - public boolean isMergeCancelled() { - return mIsMergeCancelled; - } - - /** - * 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 void onAccountsChanged(String[] accountsArray) { - Map<String, Boolean> accounts = new HashMap<String, Boolean>(); - for (String account : accountsArray) { - accounts.put(account, false); - } - accounts.put(SyncConstValue.NON_SYNCABLE_ACCOUNT, false); - - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - Map<String, String> tableMap = db.getSyncedTables(); - Vector<String> tables = new Vector<String>(); - tables.addAll(tableMap.keySet()); - tables.addAll(tableMap.values()); - - db.beginTransaction(); - try { - mSyncState.onAccountsChanged(accountsArray); - for (String table : tables) { - deleteRowsForRemovedAccounts(accounts, table, - SyncConstValue._SYNC_ACCOUNT); - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - /** - * 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 - * @param accountColumnName the name of the column that is expected - * to hold the account. - */ - protected void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts, - String table, String accountColumnName) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - Cursor c = db.query(table, sAccountProjection, null, null, - accountColumnName, null, null); - try { - while (c.moveToNext()) { - String account = c.getString(0); - if (TextUtils.isEmpty(account)) { - continue; - } - if (!accounts.containsKey(account)) { - int numDeleted; - numDeleted = db.delete(table, accountColumnName + "=?", new String[]{account}); - if (Config.LOGV) { - Log.v(TAG, "deleted " + numDeleted - + " records from table " + table - + " for account " + account); - } - } - } - } finally { - c.close(); - } - } - - /** - * Called when the sync system determines that this provider should no longer - * contain records for the specified account. - */ - public void wipeAccount(String account) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - Map<String, String> tableMap = db.getSyncedTables(); - ArrayList<String> tables = new ArrayList<String>(); - tables.addAll(tableMap.keySet()); - tables.addAll(tableMap.values()); - - db.beginTransaction(); - - try { - // remove the SyncState data - mSyncState.discardSyncData(db, account); - - // remove the data in the synced tables - for (String table : tables) { - db.delete(table, SYNC_ACCOUNT_WHERE_CLAUSE, new String[]{account}); - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - /** - * Retrieves the SyncData bytes for the given account. The byte array returned may be null. - */ - public byte[] readSyncDataBytes(String account) { - return mSyncState.readSyncDataBytes(mOpenHelper.getReadableDatabase(), account); - } - - /** - * Sets the SyncData bytes for the given account. The byte array may be null. - */ - public void writeSyncDataBytes(String account, byte[] data) { - mSyncState.writeSyncDataBytes(mOpenHelper.getWritableDatabase(), account, data); - } -} diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java deleted file mode 100644 index 700f1d8..0000000 --- a/core/java/android/content/AbstractTableMerger.java +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright (C) 2006 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.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.Debug; -import android.provider.BaseColumns; -import static android.provider.SyncConstValue.*; -import android.text.TextUtils; -import android.util.Log; - -/** - * @hide - */ -public abstract class AbstractTableMerger -{ - private ContentValues mValues; - - protected SQLiteDatabase mDb; - protected String mTable; - protected Uri mTableURL; - protected String mDeletedTable; - protected Uri mDeletedTableURL; - static protected ContentValues mSyncMarkValues; - static private boolean TRACE; - - static { - mSyncMarkValues = new ContentValues(); - mSyncMarkValues.put(_SYNC_MARK, 1); - TRACE = false; - } - - private static final String TAG = "AbstractTableMerger"; - private static final String[] syncDirtyProjection = - new String[] {_SYNC_DIRTY, BaseColumns._ID, _SYNC_ID, _SYNC_VERSION}; - private static final String[] syncIdAndVersionProjection = - new String[] {_SYNC_ID, _SYNC_VERSION}; - - private volatile boolean mIsMergeCancelled; - - private static final String SELECT_MARKED = _SYNC_MARK + "> 0 and " + _SYNC_ACCOUNT + "=?"; - - private static final String SELECT_BY_SYNC_ID_AND_ACCOUNT = - _SYNC_ID +"=? and " + _SYNC_ACCOUNT + "=?"; - private static final String SELECT_BY_ID = BaseColumns._ID +"=?"; - - private static final String SELECT_UNSYNCED = "" - + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null)"; - - public AbstractTableMerger(SQLiteDatabase database, - String table, Uri tableURL, String deletedTable, - Uri deletedTableURL) - { - mDb = database; - mTable = table; - mTableURL = tableURL; - mDeletedTable = deletedTable; - mDeletedTableURL = deletedTableURL; - mValues = new ContentValues(); - } - - public abstract void insertRow(ContentProvider diffs, - Cursor diffsCursor); - public abstract void updateRow(long localPersonID, - ContentProvider diffs, Cursor diffsCursor); - public abstract void resolveRow(long localPersonID, - String syncID, ContentProvider diffs, Cursor diffsCursor); - - /** - * This is called when it is determined that a row should be deleted from the - * ContentProvider. The localCursor is on a table from the local ContentProvider - * and its current position is of the row that should be deleted. The localCursor - * is only guaranteed to contain the BaseColumns.ID column so the implementation - * of deleteRow() must query the database directly if other columns are needed. - * <p> - * It is the responsibility of the implementation of this method to ensure that the cursor - * points to the next row when this method returns, either by calling Cursor.deleteRow() or - * Cursor.next(). - * - * @param localCursor The Cursor into the local table, which points to the row that - * is to be deleted. - */ - public void deleteRow(Cursor localCursor) { - localCursor.deleteRow(); - } - - /** - * After {@link #merge} has completed, this method is called to send - * notifications to {@link android.database.ContentObserver}s of changes - * to the containing {@link ContentProvider}. These notifications likely - * do not want to request a sync back to the network. - */ - protected abstract void notifyChanges(); - - private static boolean findInCursor(Cursor cursor, int column, String id) { - while (!cursor.isAfterLast() && !cursor.isNull(column)) { - int comp = id.compareTo(cursor.getString(column)); - if (comp > 0) { - cursor.moveToNext(); - continue; - } - return comp == 0; - } - return false; - } - - public void onMergeCancelled() { - mIsMergeCancelled = true; - } - - /** - * Carry out a merge of the given diffs, and add the results to - * the given MergeResult. If we are the first merge to find - * client-side diffs, we'll use the given ContentProvider to - * construct a temporary instance to hold them. - */ - public void merge(final SyncContext context, - final String account, - final SyncableContentProvider serverDiffs, - TempProviderSyncResult result, - SyncResult syncResult, SyncableContentProvider temporaryInstanceFactory) { - mIsMergeCancelled = false; - if (serverDiffs != null) { - if (!mDb.isDbLockedByCurrentThread()) { - throw new IllegalStateException("this must be called from within a DB transaction"); - } - mergeServerDiffs(context, account, serverDiffs, syncResult); - notifyChanges(); - } - - if (result != null) { - findLocalChanges(result, temporaryInstanceFactory, account, syncResult); - } - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "merge complete"); - } - - /** - * @hide this is public for testing purposes only - */ - public void mergeServerDiffs(SyncContext context, - String account, SyncableContentProvider serverDiffs, SyncResult syncResult) { - boolean diffsArePartial = serverDiffs.getContainsDiffs(); - // mark the current rows so that we can distinguish these from new - // inserts that occur during the merge - mDb.update(mTable, mSyncMarkValues, null, null); - if (mDeletedTable != null) { - mDb.update(mDeletedTable, mSyncMarkValues, null, null); - } - - // load the local database entries, so we can merge them with the server - final String[] accountSelectionArgs = new String[]{account}; - Cursor localCursor = mDb.query(mTable, syncDirtyProjection, - SELECT_MARKED, accountSelectionArgs, null, null, - mTable + "." + _SYNC_ID); - Cursor deletedCursor; - if (mDeletedTable != null) { - deletedCursor = mDb.query(mDeletedTable, syncIdAndVersionProjection, - SELECT_MARKED, accountSelectionArgs, null, null, - mDeletedTable + "." + _SYNC_ID); - } else { - deletedCursor = - mDb.rawQuery("select 'a' as _sync_id, 'b' as _sync_version limit 0", null); - } - - // Apply updates and insertions from the server - Cursor diffsCursor = serverDiffs.query(mTableURL, - null, null, null, mTable + "." + _SYNC_ID); - int deletedSyncIDColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_ID); - int deletedSyncVersionColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_VERSION); - int serverSyncIDColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID); - int serverSyncVersionColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_VERSION); - int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID); - - String lastSyncId = null; - int diffsCount = 0; - int localCount = 0; - localCursor.moveToFirst(); - deletedCursor.moveToFirst(); - while (diffsCursor.moveToNext()) { - if (mIsMergeCancelled) { - localCursor.close(); - deletedCursor.close(); - diffsCursor.close(); - return; - } - mDb.yieldIfContended(); - String serverSyncId = diffsCursor.getString(serverSyncIDColumn); - String serverSyncVersion = diffsCursor.getString(serverSyncVersionColumn); - long localRowId = 0; - String localSyncVersion = null; - - diffsCount++; - context.setStatusText("Processing " + diffsCount + "/" - + diffsCursor.getCount()); - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "processing server entry " + - diffsCount + ", " + serverSyncId); - - if (TRACE) { - if (diffsCount == 10) { - Debug.startMethodTracing("atmtrace"); - } - if (diffsCount == 20) { - Debug.stopMethodTracing(); - } - } - - boolean conflict = false; - boolean update = false; - boolean insert = false; - - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "found event with serverSyncID " + serverSyncId); - } - if (TextUtils.isEmpty(serverSyncId)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.e(TAG, "server entry doesn't have a serverSyncID"); - } - continue; - } - - // It is possible that the sync adapter wrote the same record multiple times, - // e.g. if the same record came via multiple feeds. If this happens just ignore - // the duplicate records. - if (serverSyncId.equals(lastSyncId)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "skipping record with duplicate remote server id " + lastSyncId); - } - continue; - } - lastSyncId = serverSyncId; - - String localSyncID = null; - boolean localSyncDirty = false; - - while (!localCursor.isAfterLast()) { - if (mIsMergeCancelled) { - localCursor.deactivate(); - deletedCursor.deactivate(); - diffsCursor.deactivate(); - return; - } - localCount++; - localSyncID = localCursor.getString(2); - - // If the local record doesn't have a _sync_id then - // it is new. Ignore it for now, we will send an insert - // the the server later. - if (TextUtils.isEmpty(localSyncID)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "local record " + - localCursor.getLong(1) + - " has no _sync_id, ignoring"); - } - localCursor.moveToNext(); - localSyncID = null; - continue; - } - - int comp = serverSyncId.compareTo(localSyncID); - - // the local DB has a record that the server doesn't have - if (comp > 0) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "local record " + - localCursor.getLong(1) + - " has _sync_id " + localSyncID + - " that is < server _sync_id " + serverSyncId); - } - if (diffsArePartial) { - localCursor.moveToNext(); - } else { - deleteRow(localCursor); - if (mDeletedTable != null) { - mDb.delete(mDeletedTable, _SYNC_ID +"=?", new String[] {localSyncID}); - } - syncResult.stats.numDeletes++; - mDb.yieldIfContended(); - } - localSyncID = null; - continue; - } - - // the server has a record that the local DB doesn't have - if (comp < 0) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "local record " + - localCursor.getLong(1) + - " has _sync_id " + localSyncID + - " that is > server _sync_id " + serverSyncId); - } - localSyncID = null; - } - - // the server and the local DB both have this record - if (comp == 0) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "local record " + - localCursor.getLong(1) + - " has _sync_id " + localSyncID + - " that matches the server _sync_id"); - } - localSyncDirty = localCursor.getInt(0) != 0; - localRowId = localCursor.getLong(1); - localSyncVersion = localCursor.getString(3); - localCursor.moveToNext(); - } - - break; - } - - // If this record is in the deleted table then update the server version - // in the deleted table, if necessary, and then ignore it here. - // We will send a deletion indication to the server down a - // little further. - if (findInCursor(deletedCursor, deletedSyncIDColumn, serverSyncId)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "remote record " + serverSyncId + " is in the deleted table"); - } - final String deletedSyncVersion = deletedCursor.getString(deletedSyncVersionColumn); - if (!TextUtils.equals(deletedSyncVersion, serverSyncVersion)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "setting version of deleted record " + serverSyncId + " to " - + serverSyncVersion); - } - ContentValues values = new ContentValues(); - values.put(_SYNC_VERSION, serverSyncVersion); - mDb.update(mDeletedTable, values, "_sync_id=?", new String[]{serverSyncId}); - } - continue; - } - - // If the _sync_local_id is present in the diffsCursor - // then this record corresponds to a local record that was just - // inserted into the server and the _sync_local_id is the row id - // of the local record. Set these fields so that the next check - // treats this record as an update, which will allow the - // merger to update the record with the server's sync id - if (!diffsCursor.isNull(serverSyncLocalIdColumn)) { - localRowId = diffsCursor.getLong(serverSyncLocalIdColumn); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "the remote record with sync id " + serverSyncId - + " has a local sync id, " + localRowId); - } - localSyncID = serverSyncId; - localSyncDirty = false; - localSyncVersion = null; - } - - if (!TextUtils.isEmpty(localSyncID)) { - // An existing server item has changed - boolean recordChanged = (localSyncVersion == null) || - !serverSyncVersion.equals(localSyncVersion); - if (recordChanged) { - if (localSyncDirty) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "remote record " + serverSyncId - + " conflicts with local _sync_id " + localSyncID - + ", local _id " + localRowId); - } - conflict = true; - } else { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, - "remote record " + - serverSyncId + - " updates local _sync_id " + - localSyncID + ", local _id " + - localRowId); - } - update = true; - } - } - } else { - // the local db doesn't know about this record so add it - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "remote record " + serverSyncId + " is new, inserting"); - } - insert = true; - } - - if (update) { - updateRow(localRowId, serverDiffs, diffsCursor); - syncResult.stats.numUpdates++; - } else if (conflict) { - resolveRow(localRowId, serverSyncId, serverDiffs, diffsCursor); - syncResult.stats.numUpdates++; - } else if (insert) { - insertRow(serverDiffs, diffsCursor); - syncResult.stats.numInserts++; - } - } - - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "processed " + diffsCount + " server entries"); - } - - // If tombstones aren't in use delete any remaining local rows that - // don't have corresponding server rows. Keep the rows that don't - // have a sync id since those were created locally and haven't been - // synced to the server yet. - if (!diffsArePartial) { - while (!localCursor.isAfterLast() && !TextUtils.isEmpty(localCursor.getString(2))) { - if (mIsMergeCancelled) { - localCursor.deactivate(); - deletedCursor.deactivate(); - diffsCursor.deactivate(); - return; - } - localCount++; - final String localSyncId = localCursor.getString(2); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, - "deleting local record " + - localCursor.getLong(1) + - " _sync_id " + localSyncId); - } - deleteRow(localCursor); - if (mDeletedTable != null) { - mDb.delete(mDeletedTable, _SYNC_ID + "=?", new String[] {localSyncId}); - } - syncResult.stats.numDeletes++; - mDb.yieldIfContended(); - } - } - - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "checked " + localCount + - " local entries"); - diffsCursor.deactivate(); - localCursor.deactivate(); - deletedCursor.deactivate(); - - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "applying deletions from the server"); - - // Apply deletions from the server - if (mDeletedTableURL != null) { - diffsCursor = serverDiffs.query(mDeletedTableURL, null, null, null, null); - - while (diffsCursor.moveToNext()) { - if (mIsMergeCancelled) { - diffsCursor.deactivate(); - return; - } - // delete all rows that match each element in the diffsCursor - fullyDeleteMatchingRows(diffsCursor, account, syncResult); - mDb.yieldIfContended(); - } - diffsCursor.deactivate(); - } - } - - private void fullyDeleteMatchingRows(Cursor diffsCursor, String account, - SyncResult syncResult) { - int serverSyncIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID); - final boolean deleteBySyncId = !diffsCursor.isNull(serverSyncIdColumn); - - // delete the rows explicitly so that the delete operation can be overridden - final Cursor c; - final String[] selectionArgs; - if (deleteBySyncId) { - selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn), account}; - c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT, - selectionArgs, null, null, null); - } else { - int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID); - selectionArgs = new String[]{diffsCursor.getString(serverSyncLocalIdColumn)}; - c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_ID, selectionArgs, - null, null, null); - } - try { - c.moveToFirst(); - while (!c.isAfterLast()) { - deleteRow(c); // advances the cursor - syncResult.stats.numDeletes++; - } - } finally { - c.deactivate(); - } - if (deleteBySyncId && mDeletedTable != null) { - mDb.delete(mDeletedTable, SELECT_BY_SYNC_ID_AND_ACCOUNT, selectionArgs); - } - } - - /** - * Converts cursor into a Map, using the correct types for the values. - */ - protected void cursorRowToContentValues(Cursor cursor, ContentValues map) { - DatabaseUtils.cursorRowToContentValues(cursor, map); - } - - /** - * Finds local changes, placing the results in the given result object. - * @param temporaryInstanceFactory As an optimization for the case - * where there are no client-side diffs, mergeResult may initially - * have no {@link android.content.TempProviderSyncResult#tempContentProvider}. If this is - * the first in the sequence of AbstractTableMergers to find - * client-side diffs, it will use the given ContentProvider to - * create a temporary instance and store its {@link - * ContentProvider} in the mergeResult. - * @param account - * @param syncResult - */ - private void findLocalChanges(TempProviderSyncResult mergeResult, - SyncableContentProvider temporaryInstanceFactory, String account, - SyncResult syncResult) { - SyncableContentProvider clientDiffs = mergeResult.tempContentProvider; - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client updates"); - - final String[] accountSelectionArgs = new String[]{account}; - - // Generate the client updates and insertions - // Create a cursor for dirty records - Cursor localChangesCursor = mDb.query(mTable, null, SELECT_UNSYNCED, accountSelectionArgs, - null, null, null); - long numInsertsOrUpdates = localChangesCursor.getCount(); - while (localChangesCursor.moveToNext()) { - if (mIsMergeCancelled) { - localChangesCursor.close(); - return; - } - if (clientDiffs == null) { - clientDiffs = temporaryInstanceFactory.getTemporaryInstance(); - } - mValues.clear(); - cursorRowToContentValues(localChangesCursor, mValues); - mValues.remove("_id"); - DatabaseUtils.cursorLongToContentValues(localChangesCursor, "_id", mValues, - _SYNC_LOCAL_ID); - clientDiffs.insert(mTableURL, mValues); - } - localChangesCursor.close(); - - // Generate the client deletions - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client deletions"); - long numEntries = DatabaseUtils.queryNumEntries(mDb, mTable); - long numDeletedEntries = 0; - if (mDeletedTable != null) { - Cursor deletedCursor = mDb.query(mDeletedTable, - syncIdAndVersionProjection, - _SYNC_ACCOUNT + "=? AND " + _SYNC_ID + " IS NOT NULL", accountSelectionArgs, - null, null, mDeletedTable + "." + _SYNC_ID); - - numDeletedEntries = deletedCursor.getCount(); - while (deletedCursor.moveToNext()) { - if (mIsMergeCancelled) { - deletedCursor.close(); - return; - } - if (clientDiffs == null) { - clientDiffs = temporaryInstanceFactory.getTemporaryInstance(); - } - mValues.clear(); - DatabaseUtils.cursorRowToContentValues(deletedCursor, mValues); - clientDiffs.insert(mDeletedTableURL, mValues); - } - deletedCursor.close(); - } - - if (clientDiffs != null) { - mergeResult.tempContentProvider = clientDiffs; - } - syncResult.stats.numDeletes += numDeletedEntries; - syncResult.stats.numUpdates += numInsertsOrUpdates; - syncResult.stats.numEntries += numEntries; - } -} diff --git a/core/java/android/content/ActivityNotFoundException.java b/core/java/android/content/ActivityNotFoundException.java deleted file mode 100644 index 16149bb..0000000 --- a/core/java/android/content/ActivityNotFoundException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2006 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; - -/** - * This exception is thrown when a call to {@link Context#startActivity} or - * one of its variants fails because an Activity can not be found to execute - * the given Intent. - */ -public class ActivityNotFoundException extends RuntimeException -{ - public ActivityNotFoundException() - { - } - - public ActivityNotFoundException(String name) - { - super(name); - } -}; - diff --git a/core/java/android/content/AsyncQueryHandler.java b/core/java/android/content/AsyncQueryHandler.java deleted file mode 100644 index ac851cc..0000000 --- a/core/java/android/content/AsyncQueryHandler.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * 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.net.Uri; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import java.lang.ref.WeakReference; - -/** - * A helper class to help make handling asynchronous {@link ContentResolver} - * queries easier. - */ -public abstract class AsyncQueryHandler extends Handler { - private static final String TAG = "AsyncQuery"; - private static final boolean localLOGV = false; - - private static final int EVENT_ARG_QUERY = 1; - private static final int EVENT_ARG_INSERT = 2; - private static final int EVENT_ARG_UPDATE = 3; - private static final int EVENT_ARG_DELETE = 4; - - /* package */ final WeakReference<ContentResolver> mResolver; - - private static Looper sLooper = null; - - private Handler mWorkerThreadHandler; - - protected static final class WorkerArgs { - public Uri uri; - public Handler handler; - public String[] projection; - public String selection; - public String[] selectionArgs; - public String orderBy; - public Object result; - public Object cookie; - public ContentValues values; - } - - protected class WorkerHandler extends Handler { - public WorkerHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - final ContentResolver resolver = mResolver.get(); - if (resolver == null) return; - - WorkerArgs args = (WorkerArgs) msg.obj; - - int token = msg.what; - int event = msg.arg1; - - switch (event) { - case EVENT_ARG_QUERY: - Cursor cursor; - try { - cursor = resolver.query(args.uri, args.projection, - args.selection, args.selectionArgs, - args.orderBy); - // Calling getCount() causes the cursor window to be filled, - // which will make the first access on the main thread a lot faster. - if (cursor != null) { - cursor.getCount(); - } - } catch (Exception e) { - cursor = null; - } - - args.result = cursor; - break; - - case EVENT_ARG_INSERT: - args.result = resolver.insert(args.uri, args.values); - break; - - case EVENT_ARG_UPDATE: - args.result = resolver.update(args.uri, args.values, args.selection, - args.selectionArgs); - break; - - case EVENT_ARG_DELETE: - args.result = resolver.delete(args.uri, args.selection, args.selectionArgs); - break; - - } - - // passing the original token value back to the caller - // on top of the event values in arg1. - Message reply = args.handler.obtainMessage(token); - reply.obj = args; - reply.arg1 = msg.arg1; - - if (localLOGV) { - Log.d(TAG, "WorkerHandler.handleMsg: msg.arg1=" + msg.arg1 - + ", reply.what=" + reply.what); - } - - reply.sendToTarget(); - } - } - - public AsyncQueryHandler(ContentResolver cr) { - super(); - mResolver = new WeakReference<ContentResolver>(cr); - synchronized (AsyncQueryHandler.class) { - if (sLooper == null) { - HandlerThread thread = new HandlerThread("AsyncQueryWorker"); - thread.start(); - - sLooper = thread.getLooper(); - } - } - mWorkerThreadHandler = createHandler(sLooper); - } - - protected Handler createHandler(Looper looper) { - return new WorkerHandler(looper); - } - - /** - * This method begins an asynchronous query. When the query is done - * {@link #onQueryComplete} is called. - * - * @param token A token passed into {@link #onQueryComplete} to identify - * the query. - * @param cookie An object that gets passed into {@link #onQueryComplete} - * @param uri The URI, using the content:// scheme, for the content to - * retrieve. - * @param projection A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading data - * from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null will - * return all rows for the given URI. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in the order that they - * appear in the selection. The values will be bound as Strings. - * @param orderBy How to order the rows, formatted as an SQL ORDER BY - * clause (excluding the ORDER BY itself). Passing null will use the - * default sort order, which may be unordered. - */ - public void startQuery(int token, Object cookie, Uri uri, - String[] projection, String selection, String[] selectionArgs, - String orderBy) { - // Use the token as what so cancelOperations works properly - Message msg = mWorkerThreadHandler.obtainMessage(token); - msg.arg1 = EVENT_ARG_QUERY; - - WorkerArgs args = new WorkerArgs(); - args.handler = this; - args.uri = uri; - args.projection = projection; - args.selection = selection; - args.selectionArgs = selectionArgs; - args.orderBy = orderBy; - args.cookie = cookie; - msg.obj = args; - - mWorkerThreadHandler.sendMessage(msg); - } - - /** - * Attempts to cancel operation that has not already started. Note that - * there is no guarantee that the operation will be canceled. They still may - * result in a call to on[Query/Insert/Update/Delete]Complete after this - * call has completed. - * - * @param token The token representing the operation to be canceled. - * If multiple operations have the same token they will all be canceled. - */ - public final void cancelOperation(int token) { - mWorkerThreadHandler.removeMessages(token); - } - - /** - * This method begins an asynchronous insert. When the insert operation is - * done {@link #onInsertComplete} is called. - * - * @param token A token passed into {@link #onInsertComplete} to identify - * the insert operation. - * @param cookie An object that gets passed into {@link #onInsertComplete} - * @param uri the Uri passed to the insert operation. - * @param initialValues the ContentValues parameter passed to the insert operation. - */ - public final void startInsert(int token, Object cookie, Uri uri, - ContentValues initialValues) { - // Use the token as what so cancelOperations works properly - Message msg = mWorkerThreadHandler.obtainMessage(token); - msg.arg1 = EVENT_ARG_INSERT; - - WorkerArgs args = new WorkerArgs(); - args.handler = this; - args.uri = uri; - args.cookie = cookie; - args.values = initialValues; - msg.obj = args; - - mWorkerThreadHandler.sendMessage(msg); - } - - /** - * This method begins an asynchronous update. When the update operation is - * done {@link #onUpdateComplete} is called. - * - * @param token A token passed into {@link #onUpdateComplete} to identify - * the update operation. - * @param cookie An object that gets passed into {@link #onUpdateComplete} - * @param uri the Uri passed to the update operation. - * @param values the ContentValues parameter passed to the update operation. - */ - public final void startUpdate(int token, Object cookie, Uri uri, - ContentValues values, String selection, String[] selectionArgs) { - // Use the token as what so cancelOperations works properly - Message msg = mWorkerThreadHandler.obtainMessage(token); - msg.arg1 = EVENT_ARG_UPDATE; - - WorkerArgs args = new WorkerArgs(); - args.handler = this; - args.uri = uri; - args.cookie = cookie; - args.values = values; - args.selection = selection; - args.selectionArgs = selectionArgs; - msg.obj = args; - - mWorkerThreadHandler.sendMessage(msg); - } - - /** - * This method begins an asynchronous delete. When the delete operation is - * done {@link #onDeleteComplete} is called. - * - * @param token A token passed into {@link #onDeleteComplete} to identify - * the delete operation. - * @param cookie An object that gets passed into {@link #onDeleteComplete} - * @param uri the Uri passed to the delete operation. - * @param selection the where clause. - */ - public final void startDelete(int token, Object cookie, Uri uri, - String selection, String[] selectionArgs) { - // Use the token as what so cancelOperations works properly - Message msg = mWorkerThreadHandler.obtainMessage(token); - msg.arg1 = EVENT_ARG_DELETE; - - WorkerArgs args = new WorkerArgs(); - args.handler = this; - args.uri = uri; - args.cookie = cookie; - args.selection = selection; - args.selectionArgs = selectionArgs; - msg.obj = args; - - mWorkerThreadHandler.sendMessage(msg); - } - - /** - * Called when an asynchronous query is completed. - * - * @param token the token to identify the query, passed in from - * {@link #startQuery}. - * @param cookie the cookie object that's passed in from {@link #startQuery}. - * @param cursor The cursor holding the results from the query. - */ - protected void onQueryComplete(int token, Object cookie, Cursor cursor) { - // Empty - } - - /** - * Called when an asynchronous insert is completed. - * - * @param token the token to identify the query, passed in from - * {@link #startInsert}. - * @param cookie the cookie object that's passed in from - * {@link #startInsert}. - * @param uri the uri returned from the insert operation. - */ - protected void onInsertComplete(int token, Object cookie, Uri uri) { - // Empty - } - - /** - * Called when an asynchronous update is completed. - * - * @param token the token to identify the query, passed in from - * {@link #startUpdate}. - * @param cookie the cookie object that's passed in from - * {@link #startUpdate}. - * @param result the result returned from the update operation - */ - protected void onUpdateComplete(int token, Object cookie, int result) { - // Empty - } - - /** - * Called when an asynchronous delete is completed. - * - * @param token the token to identify the query, passed in from - * {@link #startDelete}. - * @param cookie the cookie object that's passed in from - * {@link #startDelete}. - * @param result the result returned from the delete operation - */ - protected void onDeleteComplete(int token, Object cookie, int result) { - // Empty - } - - @Override - public void handleMessage(Message msg) { - WorkerArgs args = (WorkerArgs) msg.obj; - - if (localLOGV) { - Log.d(TAG, "AsyncQueryHandler.handleMessage: msg.what=" + msg.what - + ", msg.arg1=" + msg.arg1); - } - - int token = msg.what; - int event = msg.arg1; - - // pass token back to caller on each callback. - switch (event) { - case EVENT_ARG_QUERY: - onQueryComplete(token, args.cookie, (Cursor) args.result); - break; - - case EVENT_ARG_INSERT: - onInsertComplete(token, args.cookie, (Uri) args.result); - break; - - case EVENT_ARG_UPDATE: - onUpdateComplete(token, args.cookie, (Integer) args.result); - break; - - case EVENT_ARG_DELETE: - onDeleteComplete(token, args.cookie, (Integer) args.result); - break; - } - } -} diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java deleted file mode 100644 index 08f6191..0000000 --- a/core/java/android/content/BroadcastReceiver.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2006 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.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -/** - * Base class for code that will receive intents sent by sendBroadcast(). - * You can either dynamically register an instance of this class with - * {@link Context#registerReceiver Context.registerReceiver()} - * or statically publish an implementation through the - * {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag in your <code>AndroidManifest.xml</code>. <em><strong>Note:</strong></em> - * If registering a receiver in your - * {@link android.app.Activity#onResume() Activity.onResume()} - * implementation, you should unregister it in - * {@link android.app.Activity#onPause() Activity.onPause()}. - * (You won't receive intents when paused, - * and this will cut down on unnecessary system overhead). Do not unregister in - * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()}, - * because this won't be called if the user moves back in the history - * stack. - * - * <p>There are two major classes of broadcasts that can be received:</p> - * <ul> - * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}) are completely asynchronous. All receivers of the - * broadcast are run, in an undefined order, often at the same time. This is - * more efficient, but means that receivers can not use the result or abort - * APIs included here. - * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}) are delivered to one receiver at a time. - * As each receiver executes in turn, it can propagate a result to the next - * receiver, or it can completely abort the broadcast so that it won't be passed - * to other receivers. The order receivers runs in can be controlled with the - * {@link android.R.styleable#AndroidManifestIntentFilter_priority - * android:priority} attribute of the matching intent-filter; receivers with - * the same priority will be run in an arbitrary order. - * </ul> - * - * <p>Even in the case of normal broadcasts, the system may in some - * situations revert to delivering the broadcast one receiver at a time. In - * particular, for receivers that may require the creation of a process, only - * one will be run at a time to avoid overloading the system with new processes. - * In this situation, however, the non-ordered semantics hold: these receivers - * can not return results or abort their broadcast.</p> - * - * <p>Note that, although the Intent class is used for sending and receiving - * these broadcasts, the Intent broadcast mechanism here is completely separate - * from Intents that are used to start Activities with - * {@link Context#startActivity Context.startActivity()}. - * There is no way for an BroadcastReceiver - * to see or capture Intents used with startActivity(); likewise, when - * you broadcast an Intent, you will never find or start an Activity. - * These two operations are semantically very different: starting an - * Activity with an Intent is a foreground operation that modifies what the - * user is currently interacting with; broadcasting an Intent is a background - * operation that the user is not normally aware of. - * - * <p>The BroadcastReceiver class (when launched as a component through - * a manifest's {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag) is an important part of an - * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p> - * - * <p>Topics covered here: - * <ol> - * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a> - * <li><a href="#Permissions">Permissions</a> - * <li><a href="#ProcessLifecycle">Process Lifecycle</a> - * </ol> - * - * <a name="ReceiverLifecycle"></a> - * <h3>Receiver Lifecycle</h3> - * - * <p>A BroadcastReceiver object is only valid for the duration of the call - * to {@link #onReceive}. Once your code returns from this function, - * the system considers the object to be finished and no longer active. - * - * <p>This has important repercussions to what you can do in an - * {@link #onReceive} implementation: anything that requires asynchronous - * operation is not available, because you will need to return from the - * function to handle the asynchronous operation, but at that point the - * BroadcastReceiver is no longer active and thus the system is free to kill - * its process before the asynchronous operation completes. - * - * <p>In particular, you may <i>not</i> show a dialog or bind to a service from - * within an BroadcastReceiver. For the former, you should instead use the - * {@link android.app.NotificationManager} API. For the latter, you can - * use {@link android.content.Context#startService Context.startService()} to - * send a command to the service. - * - * <a name="Permissions"></a> - * <h3>Permissions</h3> - * - * <p>Access permissions can be enforced by either the sender or receiver - * of an Intent. - * - * <p>To enforce a permission when sending, you supply a non-null - * <var>permission</var> argument to - * {@link Context#sendBroadcast(Intent, String)} or - * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}. - * Only receivers who have been granted this permission - * (by requesting it with the - * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * tag in their <code>AndroidManifest.xml</code>) will be able to receive - * the broadcast. - * - * <p>To enforce a permission when receiving, you supply a non-null - * <var>permission</var> when registering your receiver -- either when calling - * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)} - * or in the static - * {@link android.R.styleable#AndroidManifestReceiver <receiver>} - * tag in your <code>AndroidManifest.xml</code>. Only broadcasters who have - * been granted this permission (by requesting it with the - * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * tag in their <code>AndroidManifest.xml</code>) will be able to send an - * Intent to the receiver. - * - * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> - * document for more information on permissions and security in general. - * - * <a name="ProcessLifecycle"></a> - * <h3>Process Lifecycle</h3> - * - * <p>A process that is currently executing an BroadcastReceiver (that is, - * currently running the code in its {@link #onReceive} method) is - * considered to be a foreground process and will be kept running by the - * system except under cases of extreme memory pressure. - * - * <p>Once you return from onReceive(), the BroadcastReceiver is no longer - * active, and its hosting process is only as important as any other application - * components that are running in it. This is especially important because if - * that process was only hosting the BroadcastReceiver (a common case for - * applications that the user has never or not recently interacted with), then - * upon returning from onReceive() the system will consider its process - * to be empty and aggressively kill it so that resources are available for other - * more important processes. - * - * <p>This means that for longer-running operations you will often use - * a {@link android.app.Service} in conjunction with an BroadcastReceiver to keep - * the containing process active for the entire time of your operation. - */ -public abstract class BroadcastReceiver { - public BroadcastReceiver() { - } - - /** - * This method is called when the BroadcastReceiver is receiving an Intent - * broadcast. During this time you can use the other methods on - * BroadcastReceiver to view/modify the current result values. The function - * is normally called from the main thread of its process, so you should - * never perform long-running operations in it (there is a timeout of - * 10 seconds that the system allows before considering the receiver to - * be blocked and a candidate to be killed). You cannot launch a popup dialog - * in your implementation of onReceive(). - * - * <p><b>If this BroadcastReceiver was launched through a <receiver> tag, - * then the object is no longer alive after returning from this - * function.</b> This means you should not perform any operations that - * return a result to you asynchronously -- in particular, for interacting - * with services, you should use - * {@link Context#startService(Intent)} instead of - * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish - * to interact with a service that is already running, you can use - * {@link #peekService}. - * - * @param context The Context in which the receiver is running. - * @param intent The Intent being received. - */ - public abstract void onReceive(Context context, Intent intent); - - /** - * Provide a binder to an already-running service. This method is synchronous - * and will not start the target service if it is not present, so it is safe - * to call from {@link #onReceive}. - * - * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)} - * @param service The Intent indicating the service you wish to use. See {@link - * Context#startService(Intent)} for more information. - */ - public IBinder peekService(Context myContext, Intent service) { - IActivityManager am = ActivityManagerNative.getDefault(); - IBinder binder = null; - try { - binder = am.peekService(service, service.resolveTypeIfNeeded( - myContext.getContentResolver())); - } catch (RemoteException e) { - } - return binder; - } - - /** - * Change the current result code of this broadcast; only works with - * broadcasts sent through - * {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}. Often uses the - * Activity {@link android.app.Activity#RESULT_CANCELED} and - * {@link android.app.Activity#RESULT_OK} constants, though the - * actual meaning of this value is ultimately up to the broadcaster. - * - * <p><strong>This method does not work with non-ordered broadcasts such - * as those sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}</strong></p> - * - * @param code The new result code. - * - * @see #setResult(int, String, Bundle) - */ - public final void setResultCode(int code) { - checkSynchronousHint(); - mResultCode = code; - } - - /** - * Retrieve the current result code, as set by the previous receiver. - * - * @return int The current result code. - */ - public final int getResultCode() { - return mResultCode; - } - - /** - * Change the current result data of this broadcast; only works with - * broadcasts sent through - * {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}. This is an arbitrary - * string whose interpretation is up to the broadcaster. - * - * <p><strong>This method does not work with non-ordered broadcasts such - * as those sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}</strong></p> - * - * @param data The new result data; may be null. - * - * @see #setResult(int, String, Bundle) - */ - public final void setResultData(String data) { - checkSynchronousHint(); - mResultData = data; - } - - /** - * Retrieve the current result data, as set by the previous receiver. - * Often this is null. - * - * @return String The current result data; may be null. - */ - public final String getResultData() { - return mResultData; - } - - /** - * Change the current result extras of this broadcast; only works with - * broadcasts sent through - * {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}. This is a Bundle - * holding arbitrary data, whose interpretation is up to the - * broadcaster. Can be set to null. Calling this method completely - * replaces the current map (if any). - * - * <p><strong>This method does not work with non-ordered broadcasts such - * as those sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}</strong></p> - * - * @param extras The new extra data map; may be null. - * - * @see #setResult(int, String, Bundle) - */ - public final void setResultExtras(Bundle extras) { - checkSynchronousHint(); - mResultExtras = extras; - } - - /** - * Retrieve the current result extra data, as set by the previous receiver. - * Any changes you make to the returned Map will be propagated to the next - * receiver. - * - * @param makeMap If true then a new empty Map will be made for you if the - * current Map is null; if false you should be prepared to - * receive a null Map. - * - * @return Map The current extras map. - */ - public final Bundle getResultExtras(boolean makeMap) { - Bundle e = mResultExtras; - if (!makeMap) return e; - if (e == null) mResultExtras = e = new Bundle(); - return e; - } - - /** - * Change all of the result data returned from this broadcasts; only works - * with broadcasts sent through - * {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}. All current result data is replaced - * by the value given to this method. - * - * <p><strong>This method does not work with non-ordered broadcasts such - * as those sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}</strong></p> - * - * @param code The new result code. Often uses the - * Activity {@link android.app.Activity#RESULT_CANCELED} and - * {@link android.app.Activity#RESULT_OK} constants, though the - * actual meaning of this value is ultimately up to the broadcaster. - * @param data The new result data. This is an arbitrary - * string whose interpretation is up to the broadcaster; may be null. - * @param extras The new extra data map. This is a Bundle - * holding arbitrary data, whose interpretation is up to the - * broadcaster. Can be set to null. This completely - * replaces the current map (if any). - */ - public final void setResult(int code, String data, Bundle extras) { - checkSynchronousHint(); - mResultCode = code; - mResultData = data; - mResultExtras = extras; - } - - /** - * Returns the flag indicating whether or not this receiver should - * abort the current broadcast. - * - * @return True if the broadcast should be aborted. - */ - public final boolean getAbortBroadcast() { - return mAbortBroadcast; - } - - /** - * Sets the flag indicating that this receiver should abort the - * current broadcast; only works with broadcasts sent through - * {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast}. This will prevent - * any other broadcast receivers from receiving the broadcast. It will still - * call {@link #onReceive} of the BroadcastReceiver that the caller of - * {@link Context#sendOrderedBroadcast(Intent, String) - * Context.sendOrderedBroadcast} passed in. - * - * <p><strong>This method does not work with non-ordered broadcasts such - * as those sent with {@link Context#sendBroadcast(Intent) - * Context.sendBroadcast}</strong></p> - */ - public final void abortBroadcast() { - checkSynchronousHint(); - mAbortBroadcast = true; - } - - /** - * Clears the flag indicating that this receiver should abort the current - * broadcast. - */ - public final void clearAbortBroadcast() { - mAbortBroadcast = false; - } - - /** - * For internal use, sets the hint about whether this BroadcastReceiver is - * running in ordered mode. - */ - public final void setOrderedHint(boolean isOrdered) { - mOrderedHint = isOrdered; - } - - /** - * Control inclusion of debugging help for mismatched - * calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter) - * Context.registerReceiver()}. - * If called with true, before given to registerReceiver(), then the - * callstack of the following {@link Context#unregisterReceiver(BroadcastReceiver) - * Context.unregisterReceiver()} call is retained, to be printed if a later - * incorrect unregister call is made. Note that doing this requires retaining - * information about the BroadcastReceiver for the lifetime of the app, - * resulting in a leak -- this should only be used for debugging. - */ - public final void setDebugUnregister(boolean debug) { - mDebugUnregister = debug; - } - - /** - * Return the last value given to {@link #setDebugUnregister}. - */ - public final boolean getDebugUnregister() { - return mDebugUnregister; - } - - void checkSynchronousHint() { - if (mOrderedHint) { - return; - } - RuntimeException e = new RuntimeException( - "BroadcastReceiver trying to return result during a non-ordered broadcast"); - e.fillInStackTrace(); - Log.e("BroadcastReceiver", e.getMessage(), e); - } - - private int mResultCode; - private String mResultData; - private Bundle mResultExtras; - private boolean mAbortBroadcast; - private boolean mDebugUnregister; - private boolean mOrderedHint; -} - diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java deleted file mode 100644 index dad60b0..0000000 --- a/core/java/android/content/ComponentCallbacks.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2006 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.content.res.Configuration; - -/** - * The set of callback APIs that are common to all application components - * ({@link android.app.Activity}, {@link android.app.Service}, - * {@link ContentProvider}, and {@link android.app.Application}). - */ -public interface ComponentCallbacks { - /** - * Called by the system when the device configuration changes while your - * component is running. Note that, unlike activities, other components - * are never restarted when a configuration changes: they must always deal - * with the results of the change, such as by re-retrieving resources. - * - * <p>At the time that this function has been called, your Resources - * object will have been updated to return resource values matching the - * new configuration. - * - * @param newConfig The new device configuration. - */ - void onConfigurationChanged(Configuration newConfig); - - /** - * This is called when the overall system is running low on memory, and - * would like actively running process to try to tighten their belt. While - * the exact point at which this will be called is not defined, generally - * it will happen around the time all background process have been killed, - * that is before reaching the point of killing processes hosting - * service and foreground UI that we would like to avoid killing. - * - * <p>Applications that want to be nice can implement this method to release - * any caches or other unnecessary resources they may be holding on to. - * The system will perform a gc for you after returning from this method. - */ - void onLowMemory(); -} diff --git a/core/java/android/content/ComponentName.aidl b/core/java/android/content/ComponentName.aidl deleted file mode 100644 index 40dc8de..0000000 --- a/core/java/android/content/ComponentName.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 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; - -parcelable ComponentName; diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java deleted file mode 100644 index 32c6864..0000000 --- a/core/java/android/content/ComponentName.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2006 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.os.Parcel; -import android.os.Parcelable; - -/** - * Identifier for a specific application component - * ({@link android.app.Activity}, {@link android.app.Service}, - * {@link android.content.BroadcastReceiver}, or - * {@link android.content.ContentProvider}) that is available. Two - * pieces of information, encapsulated here, are required to identify - * a component: the package (a String) it exists in, and the class (a String) - * name inside of that package. - * - */ -public final class ComponentName implements Parcelable { - private final String mPackage; - private final String mClass; - - /** - * Create a new component identifier. - * - * @param pkg The name of the package that the component exists in. Can - * not be null. - * @param cls The name of the class inside of <var>pkg</var> that - * implements the component. Can not be null. - */ - public ComponentName(String pkg, String cls) { - if (pkg == null) throw new NullPointerException("package name is null"); - if (cls == null) throw new NullPointerException("class name is null"); - mPackage = pkg; - mClass = cls; - } - - /** - * Create a new component identifier from a Context and class name. - * - * @param pkg A Context for the package implementing the component, - * from which the actual package name will be retrieved. - * @param cls The name of the class inside of <var>pkg</var> that - * implements the component. - */ - public ComponentName(Context pkg, String cls) { - if (cls == null) throw new NullPointerException("class name is null"); - mPackage = pkg.getPackageName(); - mClass = cls; - } - - /** - * Create a new component identifier from a Context and Class object. - * - * @param pkg A Context for the package implementing the component, from - * which the actual package name will be retrieved. - * @param cls The Class object of the desired component, from which the - * actual class name will be retrieved. - */ - public ComponentName(Context pkg, Class<?> cls) { - mPackage = pkg.getPackageName(); - mClass = cls.getName(); - } - - /** - * Return the package name of this component. - */ - public String getPackageName() { - return mPackage; - } - - /** - * Return the class name of this component. - */ - public String getClassName() { - return mClass; - } - - /** - * Return the class name, either fully qualified or in a shortened form - * (with a leading '.') if it is a suffix of the package. - */ - public String getShortClassName() { - if (mClass.startsWith(mPackage)) { - int PN = mPackage.length(); - int CN = mClass.length(); - if (CN > PN && mClass.charAt(PN) == '.') { - return mClass.substring(PN, CN); - } - } - return mClass; - } - - /** - * Return a String that unambiguously describes both the package and - * class names contained in the ComponentName. You can later recover - * the ComponentName from this string through - * {@link #unflattenFromString(String)}. - * - * @return Returns a new String holding the package and class names. This - * is represented as the package name, concatenated with a '/' and then the - * class name. - * - * @see #unflattenFromString(String) - */ - public String flattenToString() { - return mPackage + "/" + mClass; - } - - /** - * The samee as {@link #flattenToString()}, but abbreviates the class - * name if it is a suffix of the package. The result can still be used - * with {@link #unflattenFromString(String)}. - * - * @return Returns a new String holding the package and class names. This - * is represented as the package name, concatenated with a '/' and then the - * class name. - * - * @see #unflattenFromString(String) - */ - public String flattenToShortString() { - return mPackage + "/" + getShortClassName(); - } - - /** - * Recover a ComponentName from a String that was previously created with - * {@link #flattenToString()}. It splits the string at the first '/', - * taking the part before as the package name and the part after as the - * class name. As a special convenience (to use, for example, when - * parsing component names on the command line), if the '/' is immediately - * followed by a '.' then the final class name will be the concatenation - * of the package name with the string following the '/'. Thus - * "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah". - * - * @param str The String that was returned by flattenToString(). - * @return Returns a new ComponentName containing the package and class - * names that were encoded in <var>str</var> - * - * @see #flattenToString() - */ - public static ComponentName unflattenFromString(String str) { - int sep = str.indexOf('/'); - if (sep < 0 || (sep+1) >= str.length()) { - return null; - } - String pkg = str.substring(0, sep); - String cls = str.substring(sep+1); - if (cls.length() > 0 && cls.charAt(0) == '.') { - cls = pkg + cls; - } - return new ComponentName(pkg, cls); - } - - /** - * Return string representation of this class without the class's name - * as a prefix. - */ - public String toShortString() { - return "{" + mPackage + "/" + mClass + "}"; - } - - @Override - public String toString() { - return "ComponentInfo{" + mPackage + "/" + mClass + "}"; - } - - @Override - public boolean equals(Object obj) { - try { - if (obj != null) { - ComponentName other = (ComponentName)obj; - // Note: no null checks, because mPackage and mClass can - // never be null. - return mPackage.equals(other.mPackage) - && mClass.equals(other.mClass); - } - } catch (ClassCastException e) { - } - return false; - } - - @Override - public int hashCode() { - return mPackage.hashCode() + mClass.hashCode(); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(mPackage); - out.writeString(mClass); - } - - /** - * Write a ComponentName to a Parcel, handling null pointers. Must be - * read with {@link #readFromParcel(Parcel)}. - * - * @param c The ComponentName to be written. - * @param out The Parcel in which the ComponentName will be placed. - * - * @see #readFromParcel(Parcel) - */ - public static void writeToParcel(ComponentName c, Parcel out) { - if (c != null) { - c.writeToParcel(out, 0); - } else { - out.writeString(null); - } - } - - /** - * Read a ComponentName from a Parcel that was previously written - * with {@link #writeToParcel(ComponentName, Parcel)}, returning either - * a null or new object as appropriate. - * - * @param in The Parcel from which to read the ComponentName - * @return Returns a new ComponentName matching the previously written - * object, or null if a null had been written. - * - * @see #writeToParcel(ComponentName, Parcel) - */ - public static ComponentName readFromParcel(Parcel in) { - String pkg = in.readString(); - return pkg != null ? new ComponentName(pkg, in) : null; - } - - public static final Parcelable.Creator<ComponentName> CREATOR - = new Parcelable.Creator<ComponentName>() { - public ComponentName createFromParcel(Parcel in) { - return new ComponentName(in); - } - - public ComponentName[] newArray(int size) { - return new ComponentName[size]; - } - }; - - /** - * Instantiate a new ComponentName from the data in a Parcel that was - * previously written with {@link #writeToParcel(Parcel, int)}. Note that you - * must not use this with data written by - * {@link #writeToParcel(ComponentName, Parcel)} since it is not possible - * to handle a null ComponentObject here. - * - * @param in The Parcel containing the previously written ComponentName, - * positioned at the location in the buffer where it was written. - */ - public ComponentName(Parcel in) { - mPackage = in.readString(); - if (mPackage == null) throw new NullPointerException( - "package name is null"); - mClass = in.readString(); - if (mClass == null) throw new NullPointerException( - "class name is null"); - } - - private ComponentName(String pkg, Parcel in) { - mPackage = pkg; - mClass = in.readString(); - } -} diff --git a/core/java/android/content/ContentInsertHandler.java b/core/java/android/content/ContentInsertHandler.java deleted file mode 100644 index fbf726e..0000000 --- a/core/java/android/content/ContentInsertHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008 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 org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Interface to insert data to ContentResolver - * @hide - */ -public interface ContentInsertHandler extends ContentHandler { - /** - * insert data from InputStream to ContentResolver - * @param contentResolver - * @param in InputStream - * @throws IOException - * @throws SAXException - */ - public void insert(ContentResolver contentResolver, InputStream in) - throws IOException, SAXException; - - /** - * insert data from String to ContentResolver - * @param contentResolver - * @param in input string - * @throws SAXException - */ - public void insert(ContentResolver contentResolver, String in) - throws SAXException; - -} diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java deleted file mode 100644 index 3a64cee..0000000 --- a/core/java/android/content/ContentProvider.java +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2006 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.content.pm.PackageManager; -import android.content.pm.ProviderInfo; -import android.content.res.Configuration; -import android.database.Cursor; -import android.database.CursorToBulkCursorAdaptor; -import android.database.CursorWindow; -import android.database.IBulkCursor; -import android.database.IContentObserver; -import android.database.SQLException; -import android.net.Uri; -import android.os.Binder; -import android.os.ParcelFileDescriptor; - -import java.io.File; -import java.io.FileNotFoundException; - -/** - * Content providers are one of the primary building blocks of Android applications, providing - * content to applications. They encapsulate data and provide it to applications through the single - * {@link ContentResolver} interface. A content provider is only required if you need to share - * data between multiple applications. For example, the contacts data is used by multiple - * applications and must be stored in a content provider. If you don't need to share data amongst - * multiple applications you can use a database directly via - * {@link android.database.sqlite.SQLiteDatabase}. - * - * <p>For more information, read <a href="{@docRoot}guide/topics/providers/content-providers.html">Content - * Providers</a>.</p> - * - * <p>When a request is made via - * a {@link ContentResolver} the system inspects the authority of the given URI and passes the - * request to the content provider registered with the authority. The content provider can interpret - * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing - * URIs.</p> - * - * <p>The primary methods that need to be implemented are: - * <ul> - * <li>{@link #query} which returns data to the caller</li> - * <li>{@link #insert} which inserts new data into the content provider</li> - * <li>{@link #update} which updates existing data in the content provider</li> - * <li>{@link #delete} which deletes data from the content provider</li> - * <li>{@link #getType} which returns the MIME type of data in the content provider</li> - * </ul></p> - * - * <p>This class takes care of cross process calls so subclasses don't have to worry about which - * process a request is coming from.</p> - */ -public abstract class ContentProvider implements ComponentCallbacks { - private Context mContext = null; - private String mReadPermission; - private String mWritePermission; - - private Transport mTransport = new Transport(); - - /** - * Given an IContentProvider, try to coerce it back to the real - * ContentProvider object if it is running in the local process. This can - * be used if you know you are running in the same process as a provider, - * and want to get direct access to its implementation details. Most - * clients should not nor have a reason to use it. - * - * @param abstractInterface The ContentProvider interface that is to be - * coerced. - * @return If the IContentProvider is non-null and local, returns its actual - * ContentProvider instance. Otherwise returns null. - * @hide - */ - public static ContentProvider coerceToLocalContentProvider( - IContentProvider abstractInterface) { - if (abstractInterface instanceof Transport) { - return ((Transport)abstractInterface).getContentProvider(); - } - return null; - } - - /** - * Binder object that deals with remoting. - * - * @hide - */ - class Transport extends ContentProviderNative { - ContentProvider getContentProvider() { - return ContentProvider.this; - } - - /** - * Remote version of a query, which returns an IBulkCursor. The bulk - * cursor should be wrapped with BulkCursorToCursorAdaptor before use. - */ - public IBulkCursor bulkQuery(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder, - IContentObserver observer, CursorWindow window) { - checkReadPermission(uri); - Cursor cursor = ContentProvider.this.query(uri, projection, - selection, selectionArgs, sortOrder); - if (cursor == null) { - return null; - } - String wperm = getWritePermission(); - return new CursorToBulkCursorAdaptor(cursor, observer, - ContentProvider.this.getClass().getName(), - wperm == null || - getContext().checkCallingOrSelfPermission(getWritePermission()) - == PackageManager.PERMISSION_GRANTED, - window); - } - - public Cursor query(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder) { - checkReadPermission(uri); - return ContentProvider.this.query(uri, projection, selection, - selectionArgs, sortOrder); - } - - public String getType(Uri uri) { - return ContentProvider.this.getType(uri); - } - - - public Uri insert(Uri uri, ContentValues initialValues) { - checkWritePermission(uri); - return ContentProvider.this.insert(uri, initialValues); - } - - public int bulkInsert(Uri uri, ContentValues[] initialValues) { - checkWritePermission(uri); - return ContentProvider.this.bulkInsert(uri, initialValues); - } - - public int delete(Uri uri, String selection, String[] selectionArgs) { - checkWritePermission(uri); - return ContentProvider.this.delete(uri, selection, selectionArgs); - } - - public int update(Uri uri, ContentValues values, String selection, - String[] selectionArgs) { - checkWritePermission(uri); - return ContentProvider.this.update(uri, values, selection, selectionArgs); - } - - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) checkWritePermission(uri); - else checkReadPermission(uri); - return ContentProvider.this.openFile(uri, mode); - } - - public ISyncAdapter getSyncAdapter() { - checkWritePermission(null); - return ContentProvider.this.getSyncAdapter().getISyncAdapter(); - } - - private void checkReadPermission(Uri uri) { - final String rperm = getReadPermission(); - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - if (getContext().checkUriPermission(uri, rperm, null, pid, uid, - Intent.FLAG_GRANT_READ_URI_PERMISSION) - == PackageManager.PERMISSION_GRANTED) { - return; - } - String msg = "Permission Denial: reading " - + ContentProvider.this.getClass().getName() - + " uri " + uri + " from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid() - + " requires " + rperm; - throw new SecurityException(msg); - } - - private void checkWritePermission(Uri uri) { - final String wperm = getWritePermission(); - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - if (getContext().checkUriPermission(uri, null, wperm, pid, uid, - Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - == PackageManager.PERMISSION_GRANTED) { - return; - } - String msg = "Permission Denial: writing " - + ContentProvider.this.getClass().getName() - + " uri " + uri + " from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid() - + " requires " + wperm; - throw new SecurityException(msg); - } - } - - - /** - * Retrieve the Context this provider is running in. Only available once - * onCreate(Map icicle) has been called -- this will be null in the - * constructor. - */ - public final Context getContext() { - return mContext; - } - - /** - * Change the permission required to read data from the content - * provider. This is normally set for you from its manifest information - * when the provider is first created. - * - * @param permission Name of the permission required for read-only access. - */ - protected final void setReadPermission(String permission) { - mReadPermission = permission; - } - - /** - * Return the name of the permission required for read-only access to - * this content provider. This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - */ - public final String getReadPermission() { - return mReadPermission; - } - - /** - * Change the permission required to read and write data in the content - * provider. This is normally set for you from its manifest information - * when the provider is first created. - * - * @param permission Name of the permission required for read/write access. - */ - protected final void setWritePermission(String permission) { - mWritePermission = permission; - } - - /** - * Return the name of the permission required for read/write access to - * this content provider. This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - */ - public final String getWritePermission() { - return mWritePermission; - } - - /** - * Called when the provider is being started. - * - * @return true if the provider was successfully loaded, false otherwise - */ - public abstract boolean onCreate(); - - public void onConfigurationChanged(Configuration newConfig) { - } - - public void onLowMemory() { - } - - /** - * Receives a query request from a client in a local process, and - * returns a Cursor. This is called internally by the {@link ContentResolver}. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * <p> - * Example client call:<p> - * <pre>// Request a specific record. - * Cursor managedCursor = managedQuery( - Contacts.People.CONTENT_URI.addId(2), - projection, // Which columns to return. - null, // WHERE clause. - People.NAME + " ASC"); // Sort order.</pre> - * Example implementation:<p> - * <pre>// SQLiteQueryBuilder is a helper class that creates the - // proper SQL syntax for us. - SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); - - // Set the table we're querying. - qBuilder.setTables(DATABASE_TABLE_NAME); - - // If the query ends in a specific record number, we're - // being asked for a specific record, so set the - // WHERE clause in our query. - if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ - qBuilder.appendWhere("_id=" + uri.getPathLeafId()); - } - - // Make the query. - Cursor c = qBuilder.query(mDb, - projection, - selection, - selectionArgs, - groupBy, - having, - sortOrder); - c.setNotificationUri(getContext().getContentResolver(), uri); - return c;</pre> - * - * @param uri The URI to query. This will be the full URI sent by the client; - * if the client is requesting a specific record, the URI will end in a record number - * that the implementation should parse and add to a WHERE or HAVING clause, specifying - * that _id value. - * @param projection The list of columns to put into the cursor. If - * null all columns are included. - * @param selection A selection criteria to apply when filtering rows. - * If null then all rows are included. - * @param sortOrder How the rows in the cursor should be sorted. - * If null then the provider is free to define the sort order. - * @return a Cursor or null. - */ - public abstract Cursor query(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder); - - /** - * Return the MIME type of the data at the given URI. This should start with - * <code>vnd.android.cursor.item</code> for a single record, - * or <code>vnd.android.cursor.dir/</code> for multiple items. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * - * @param uri the URI to query. - * @return a MIME type string, or null if there is no type. - */ - public abstract String getType(Uri uri); - - /** - * Implement this to insert a new row. - * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} - * after inserting. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * @param uri The content:// URI of the insertion request. - * @param values A set of column_name/value pairs to add to the database. - * @return The URI for the newly inserted item. - */ - public abstract Uri insert(Uri uri, ContentValues values); - - /** - * Implement this to insert a set of new rows, or the default implementation will - * iterate over the values and call {@link #insert} on each of them. - * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} - * after inserting. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * - * @param uri The content:// URI of the insertion request. - * @param values An array of sets of column_name/value pairs to add to the database. - * @return The number of values that were inserted. - */ - public int bulkInsert(Uri uri, ContentValues[] values) { - int numValues = values.length; - for (int i = 0; i < numValues; i++) { - insert(uri, values[i]); - } - return numValues; - } - - /** - * A request to delete one or more rows. The selection clause is applied when performing - * the deletion, allowing the operation to affect multiple rows in a - * directory. - * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()} - * after deleting. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * - * <p>The implementation is responsible for parsing out a row ID at the end - * of the URI, if a specific row is being deleted. That is, the client would - * pass in <code>content://contacts/people/22</code> and the implementation is - * responsible for parsing the record number (22) when creating a SQL statement. - * - * @param uri The full URI to query, including a row ID (if a specific record is requested). - * @param selection An optional restriction to apply to rows when deleting. - * @return The number of rows affected. - * @throws SQLException - */ - public abstract int delete(Uri uri, String selection, String[] selectionArgs); - - /** - * Update a content URI. All rows matching the optionally provided selection - * will have their columns listed as the keys in the values map with the - * values of those keys. - * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} - * after updating. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * - * @param uri The URI to query. This can potentially have a record ID if this - * is an update request for a specific record. - * @param values A Bundle mapping from column names to new column values (NULL is a - * valid value). - * @param selection An optional filter to match rows to update. - * @return the number of rows affected. - */ - public abstract int update(Uri uri, ContentValues values, String selection, - String[] selectionArgs); - - /** - * Open a file blob associated with a content URI. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * - * <p>Returns a - * ParcelFileDescriptor, from which you can obtain a - * {@link java.io.FileDescriptor} for use with - * {@link java.io.FileInputStream}, {@link java.io.FileOutputStream}, etc. - * This can be used to store large data (such as an image) associated with - * a particular piece of content. - * - * <p>The returned ParcelFileDescriptor is owned by the caller, so it is - * their responsibility to close it when done. That is, the implementation - * of this method should create a new ParcelFileDescriptor for each call. - * - * @param uri The URI whose file is to be opened. - * @param mode Access mode for the file. May be "r" for read-only access - * or "rw" for read and write access. - * - * @return Returns a new ParcelFileDescriptor which you can use to access - * the file. - * - * @throws FileNotFoundException Throws FileNotFoundException if there is - * no file associated with the given URI or the mode is invalid. - * @throws SecurityException Throws SecurityException if the caller does - * not have permission to access the file. - */ - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - throw new FileNotFoundException("No files supported by provider at " - + uri); - } - - /** - * Convenience for subclasses that wish to implement {@link #openFile} - * by looking up a column named "_data" at the given URI. - * - * @param uri The URI to be opened. - * @param mode The file mode. - * - * @return Returns a new ParcelFileDescriptor that can be used by the - * client to access the file. - */ - protected final ParcelFileDescriptor openFileHelper(Uri uri, - String mode) throws FileNotFoundException { - Cursor c = query(uri, new String[]{"_data"}, null, null, null); - int count = (c != null) ? c.getCount() : 0; - if (count != 1) { - // If there is not exactly one result, throw an appropriate - // exception. - if (c != null) { - c.close(); - } - if (count == 0) { - throw new FileNotFoundException("No entry for " + uri); - } - throw new FileNotFoundException("Multiple items at " + uri); - } - - c.moveToFirst(); - int i = c.getColumnIndex("_data"); - String path = (i >= 0 ? c.getString(i) : null); - c.close(); - if (path == null) { - throw new FileNotFoundException("Column _data not found."); - } - - int modeBits; - if ("r".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_ONLY; - } else if ("rw".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_WRITE - | ParcelFileDescriptor.MODE_CREATE; - } else { - throw new FileNotFoundException("Bad mode for " + uri + ": " - + mode); - } - return ParcelFileDescriptor.open(new File(path), modeBits); - } - - /** - * Get the sync adapter that is to be used by this content provider. - * This is intended for use by the sync system. If null then this - * content provider is considered not syncable. - * This method can be called from multiple - * threads, as described in - * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: - * Processes and Threads</a>. - * - * @return the SyncAdapter that is to be used by this ContentProvider, or null - * if this ContentProvider is not syncable - * @hide - */ - public SyncAdapter getSyncAdapter() { - return null; - } - - /** - * Returns true if this instance is a temporary content provider. - * @return true if this instance is a temporary content provider - */ - protected boolean isTemporary() { - return false; - } - - /** - * Returns the Binder object for this provider. - * - * @return the Binder object for this provider - * @hide - */ - public IContentProvider getIContentProvider() { - return mTransport; - } - - /** - * After being instantiated, this is called to tell the content provider - * about itself. - * - * @param context The context this provider is running in - * @param info Registered information about this content provider - */ - public void attachInfo(Context context, ProviderInfo info) { - - /* - * Only allow it to be set once, so after the content service gives - * this to us clients can't change it. - */ - if (mContext == null) { - mContext = context; - if (info != null) { - setReadPermission(info.readPermission); - setWritePermission(info.writePermission); - } - ContentProvider.this.onCreate(); - } - } -} diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java deleted file mode 100644 index ede2c9b..0000000 --- a/core/java/android/content/ContentProviderNative.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2006 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.BulkCursorNative; -import android.database.BulkCursorToCursorAdaptor; -import android.database.Cursor; -import android.database.CursorWindow; -import android.database.DatabaseUtils; -import android.database.IBulkCursor; -import android.database.IContentObserver; -import android.net.Uri; -import android.os.Binder; -import android.os.RemoteException; -import android.os.IBinder; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; - -import java.io.FileNotFoundException; - -/** - * {@hide} - */ -abstract public class ContentProviderNative extends Binder implements IContentProvider { - private static final String TAG = "ContentProvider"; - - public ContentProviderNative() - { - attachInterface(this, descriptor); - } - - /** - * Cast a Binder object into a content resolver interface, generating - * a proxy if needed. - */ - static public IContentProvider asInterface(IBinder obj) - { - if (obj == null) { - return null; - } - IContentProvider in = - (IContentProvider)obj.queryLocalInterface(descriptor); - if (in != null) { - return in; - } - - return new ContentProviderProxy(obj); - } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - try { - switch (code) { - case QUERY_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - int num = data.readInt(); - String[] projection = null; - if (num > 0) { - projection = new String[num]; - for (int i = 0; i < num; i++) { - projection[i] = data.readString(); - } - } - String selection = data.readString(); - num = data.readInt(); - String[] selectionArgs = null; - if (num > 0) { - selectionArgs = new String[num]; - for (int i = 0; i < num; i++) { - selectionArgs[i] = data.readString(); - } - } - String sortOrder = data.readString(); - IContentObserver observer = IContentObserver.Stub. - asInterface(data.readStrongBinder()); - CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); - - IBulkCursor bulkCursor = bulkQuery(url, projection, selection, - selectionArgs, sortOrder, observer, window); - reply.writeNoException(); - if (bulkCursor != null) { - reply.writeStrongBinder(bulkCursor.asBinder()); - } else { - reply.writeStrongBinder(null); - } - return true; - } - - case GET_TYPE_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - String type = getType(url); - reply.writeNoException(); - reply.writeString(type); - - return true; - } - - case INSERT_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - ContentValues values = ContentValues.CREATOR.createFromParcel(data); - - Uri out = insert(url, values); - reply.writeNoException(); - Uri.writeToParcel(reply, out); - return true; - } - - case BULK_INSERT_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - ContentValues[] values = data.createTypedArray(ContentValues.CREATOR); - - int count = bulkInsert(url, values); - reply.writeNoException(); - reply.writeInt(count); - return true; - } - - case DELETE_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - String selection = data.readString(); - String[] selectionArgs = data.readStringArray(); - - int count = delete(url, selection, selectionArgs); - - reply.writeNoException(); - reply.writeInt(count); - return true; - } - - case UPDATE_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - ContentValues values = ContentValues.CREATOR.createFromParcel(data); - String selection = data.readString(); - String[] selectionArgs = data.readStringArray(); - - int count = update(url, values, selection, selectionArgs); - - reply.writeNoException(); - reply.writeInt(count); - return true; - } - - case OPEN_FILE_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - Uri url = Uri.CREATOR.createFromParcel(data); - String mode = data.readString(); - - ParcelFileDescriptor fd; - fd = openFile(url, mode); - reply.writeNoException(); - if (fd != null) { - reply.writeInt(1); - fd.writeToParcel(reply, - Parcelable.PARCELABLE_WRITE_RETURN_VALUE); - } else { - reply.writeInt(0); - } - return true; - } - - case GET_SYNC_ADAPTER_TRANSACTION: - { - data.enforceInterface(IContentProvider.descriptor); - ISyncAdapter sa = getSyncAdapter(); - reply.writeNoException(); - reply.writeStrongBinder(sa != null ? sa.asBinder() : null); - return true; - } - } - } catch (Exception e) { - DatabaseUtils.writeExceptionToParcel(reply, e); - return true; - } - - return super.onTransact(code, data, reply, flags); - } - - public IBinder asBinder() - { - return this; - } -} - - -final class ContentProviderProxy implements IContentProvider -{ - public ContentProviderProxy(IBinder remote) - { - mRemote = remote; - } - - public IBinder asBinder() - { - return mRemote; - } - - public IBulkCursor bulkQuery(Uri url, String[] projection, - String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, - CursorWindow window) throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - int length = 0; - if (projection != null) { - length = projection.length; - } - data.writeInt(length); - for (int i = 0; i < length; i++) { - data.writeString(projection[i]); - } - data.writeString(selection); - if (selectionArgs != null) { - length = selectionArgs.length; - } else { - length = 0; - } - data.writeInt(length); - for (int i = 0; i < length; i++) { - data.writeString(selectionArgs[i]); - } - data.writeString(sortOrder); - data.writeStrongBinder(observer.asBinder()); - window.writeToParcel(data, 0); - - mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - - IBulkCursor bulkCursor = null; - IBinder bulkCursorBinder = reply.readStrongBinder(); - if (bulkCursorBinder != null) { - bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder); - } - - data.recycle(); - reply.recycle(); - - return bulkCursor; - } - - public Cursor query(Uri url, String[] projection, String selection, - String[] selectionArgs, String sortOrder) throws RemoteException { - //TODO make a pool of windows so we can reuse memory dealers - CursorWindow window = new CursorWindow(false /* window will be used remotely */); - BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); - IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder, - adaptor.getObserver(), window); - - if (bulkCursor == null) { - return null; - } - adaptor.set(bulkCursor); - return adaptor; - } - - public String getType(Uri url) throws RemoteException - { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - - mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - String out = reply.readString(); - - data.recycle(); - reply.recycle(); - - return out; - } - - public Uri insert(Uri url, ContentValues values) throws RemoteException - { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - values.writeToParcel(data, 0); - - mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - Uri out = Uri.CREATOR.createFromParcel(reply); - - data.recycle(); - reply.recycle(); - - return out; - } - - public int bulkInsert(Uri url, ContentValues[] values) throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - data.writeTypedArray(values, 0); - - mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - int count = reply.readInt(); - - data.recycle(); - reply.recycle(); - - return count; - } - - public int delete(Uri url, String selection, String[] selectionArgs) - throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - data.writeString(selection); - data.writeStringArray(selectionArgs); - - mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - int count = reply.readInt(); - - data.recycle(); - reply.recycle(); - - return count; - } - - public int update(Uri url, ContentValues values, String selection, - String[] selectionArgs) throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - values.writeToParcel(data, 0); - data.writeString(selection); - data.writeStringArray(selectionArgs); - - mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - int count = reply.readInt(); - - data.recycle(); - reply.recycle(); - - return count; - } - - public ParcelFileDescriptor openFile(Uri url, String mode) - throws RemoteException, FileNotFoundException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - url.writeToParcel(data, 0); - data.writeString(mode); - - mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply); - int has = reply.readInt(); - ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null; - - data.recycle(); - reply.recycle(); - - return fd; - } - - public ISyncAdapter getSyncAdapter() throws RemoteException { - Parcel data = Parcel.obtain(); - Parcel reply = Parcel.obtain(); - - data.writeInterfaceToken(IContentProvider.descriptor); - - mRemote.transact(IContentProvider.GET_SYNC_ADAPTER_TRANSACTION, data, reply, 0); - - DatabaseUtils.readExceptionFromParcel(reply); - ISyncAdapter syncAdapter = ISyncAdapter.Stub.asInterface(reply.readStrongBinder()); - - data.recycle(); - reply.recycle(); - - return syncAdapter; - } - - private IBinder mRemote; -} - diff --git a/core/java/android/content/ContentQueryMap.java b/core/java/android/content/ContentQueryMap.java deleted file mode 100644 index dbcb4a7..0000000 --- a/core/java/android/content/ContentQueryMap.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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.ContentObserver; -import android.database.Cursor; -import android.os.Handler; - -import java.util.HashMap; -import java.util.Map; -import java.util.Observable; - -/** - * Caches the contents of a cursor into a Map of String->ContentValues and optionally - * keeps the cache fresh by registering for updates on the content backing the cursor. The column of - * the database that is to be used as the key of the map is user-configurable, and the - * ContentValues contains all columns other than the one that is designated the key. - * <p> - * The cursor data is accessed by row key and column name via getValue(). - */ -public class ContentQueryMap extends Observable { - private Cursor mCursor; - private String[] mColumnNames; - private int mKeyColumn; - - private Handler mHandlerForUpdateNotifications = null; - private boolean mKeepUpdated = false; - - private Map<String, ContentValues> mValues = null; - - private ContentObserver mContentObserver; - - /** Set when a cursor change notification is received and is cleared on a call to requery(). */ - private boolean mDirty = false; - - /** - * Creates a ContentQueryMap that caches the content backing the cursor - * - * @param cursor the cursor whose contents should be cached - * @param columnNameOfKey the column that is to be used as the key of the values map - * @param keepUpdated true if the cursor's ContentProvider should be monitored for changes and - * the map updated when changes do occur - * @param handlerForUpdateNotifications the Handler that should be used to receive - * notifications of changes (if requested). Normally you pass null here, but if - * you know that the thread that is creating this isn't a thread that can receive - * messages then you can create your own handler and use that here. - */ - public ContentQueryMap(Cursor cursor, String columnNameOfKey, boolean keepUpdated, - Handler handlerForUpdateNotifications) { - mCursor = cursor; - mColumnNames = mCursor.getColumnNames(); - mKeyColumn = mCursor.getColumnIndexOrThrow(columnNameOfKey); - mHandlerForUpdateNotifications = handlerForUpdateNotifications; - setKeepUpdated(keepUpdated); - - // If we aren't keeping the cache updated with the current state of the cursor's - // ContentProvider then read it once into the cache. Otherwise the cache will be filled - // automatically. - if (!keepUpdated) { - readCursorIntoCache(); - } - } - - /** - * Change whether or not the ContentQueryMap will register with the cursor's ContentProvider - * for change notifications. If you use a ContentQueryMap in an activity you should call this - * with false in onPause(), which means you need to call it with true in onResume() - * if want it to be kept updated. - * @param keepUpdated if true the ContentQueryMap should be registered with the cursor's - * ContentProvider, false otherwise - */ - public void setKeepUpdated(boolean keepUpdated) { - if (keepUpdated == mKeepUpdated) return; - mKeepUpdated = keepUpdated; - - if (!mKeepUpdated) { - mCursor.unregisterContentObserver(mContentObserver); - mContentObserver = null; - } else { - if (mHandlerForUpdateNotifications == null) { - mHandlerForUpdateNotifications = new Handler(); - } - if (mContentObserver == null) { - mContentObserver = new ContentObserver(mHandlerForUpdateNotifications) { - @Override - public void onChange(boolean selfChange) { - // If anyone is listening, we need to do this now to broadcast - // to the observers. Otherwise, we'll just set mDirty and - // let it query lazily when they ask for the values. - if (countObservers() != 0) { - requery(); - } else { - mDirty = true; - } - } - }; - } - mCursor.registerContentObserver(mContentObserver); - // mark dirty, since it is possible the cursor's backing data had changed before we - // registered for changes - mDirty = true; - } - } - - /** - * Access the ContentValues for the row specified by rowName - * @param rowName which row to read - * @return the ContentValues for the row, or null if the row wasn't present in the cursor - */ - public synchronized ContentValues getValues(String rowName) { - if (mDirty) requery(); - return mValues.get(rowName); - } - - /** Requeries the cursor and reads the contents into the cache */ - public void requery() { - mDirty = false; - mCursor.requery(); - readCursorIntoCache(); - setChanged(); - notifyObservers(); - } - - private synchronized void readCursorIntoCache() { - // Make a new map so old values returned by getRows() are undisturbed. - int capacity = mValues != null ? mValues.size() : 0; - mValues = new HashMap<String, ContentValues>(capacity); - while (mCursor.moveToNext()) { - ContentValues values = new ContentValues(); - for (int i = 0; i < mColumnNames.length; i++) { - if (i != mKeyColumn) { - values.put(mColumnNames[i], mCursor.getString(i)); - } - } - mValues.put(mCursor.getString(mKeyColumn), values); - } - } - - public synchronized Map<String, ContentValues> getRows() { - if (mDirty) requery(); - return mValues; - } - - public synchronized void close() { - if (mContentObserver != null) { - mCursor.unregisterContentObserver(mContentObserver); - mContentObserver = null; - } - mCursor.close(); - mCursor = null; - } - - @Override - protected void finalize() throws Throwable { - if (mCursor != null) close(); - super.finalize(); - } -} diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java deleted file mode 100644 index 52f55b6..0000000 --- a/core/java/android/content/ContentResolver.java +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright (C) 2006 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.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.database.Cursor; -import android.database.CursorWrapper; -import android.database.IContentObserver; -import android.net.Uri; -import android.os.Bundle; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.text.TextUtils; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.List; - - -/** - * This class provides applications access to the content model. - */ -public abstract class ContentResolver { - public final static String SYNC_EXTRAS_ACCOUNT = "account"; - public static final String SYNC_EXTRAS_EXPEDITED = "expedited"; - public static final String SYNC_EXTRAS_FORCE = "force"; - public static final String SYNC_EXTRAS_UPLOAD = "upload"; - public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override"; - public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions"; - - public static final String SCHEME_CONTENT = "content"; - public static final String SCHEME_ANDROID_RESOURCE = "android.resource"; - public static final String SCHEME_FILE = "file"; - - /** - * This is the Android platform's base MIME type for a content: URI - * containing a Cursor of a single item. Applications should use this - * as the base type along with their own sub-type of their content: URIs - * that represent a particular item. For example, hypothetical IMAP email - * client may have a URI - * <code>content://com.company.provider.imap/inbox/1</code> for a particular - * message in the inbox, whose MIME type would be reported as - * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code> - * - * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}. - */ - public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; - - /** - * This is the Android platform's base MIME type for a content: URI - * containing a Cursor of zero or more items. Applications should use this - * as the base type along with their own sub-type of their content: URIs - * that represent a directory of items. For example, hypothetical IMAP email - * client may have a URI - * <code>content://com.company.provider.imap/inbox</code> for all of the - * messages in its inbox, whose MIME type would be reported as - * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code> - * - * <p>Note how the base MIME type varies between this and - * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is - * one single item or multiple items in the data set, while the sub-type - * remains the same because in either case the data structure contained - * in the cursor is the same. - */ - public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir"; - - public ContentResolver(Context context) - { - mContext = context; - } - - /** @hide */ - protected abstract IContentProvider acquireProvider(Context c, String name); - /** @hide */ - public abstract boolean releaseProvider(IContentProvider icp); - - /** - * Return the MIME type of the given content URL. - * - * @param url A Uri identifying content (either a list or specific type), - * using the content:// scheme. - * @return A MIME type for the content, or null if the URL is invalid or the type is unknown - */ - public final String getType(Uri url) - { - IContentProvider provider = acquireProvider(url); - if (provider == null) { - return null; - } - try { - return provider.getType(url); - } catch (RemoteException e) { - return null; - } catch (java.lang.Exception e) { - return null; - } finally { - releaseProvider(provider); - } - } - - /** - * Query the given URI, returning a {@link Cursor} over the result set. - * - * @param uri The URI, using the content:// scheme, for the content to - * retrieve. - * @param projection A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading data - * from storage that isn't going to be used. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null will - * return all rows for the given URI. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in the order that they - * appear in the selection. The values will be bound as Strings. - * @param sortOrder How to order the rows, formatted as an SQL ORDER BY - * clause (excluding the ORDER BY itself). Passing null will use the - * default sort order, which may be unordered. - * @return A Cursor object, which is positioned before the first entry, or null - * @see Cursor - */ - public final Cursor query(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder) { - IContentProvider provider = acquireProvider(uri); - if (provider == null) { - return null; - } - try { - Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder); - if(qCursor == null) { - releaseProvider(provider); - return null; - } - //Wrap the cursor object into CursorWrapperInner object - return new CursorWrapperInner(qCursor, provider); - } catch (RemoteException e) { - releaseProvider(provider); - return null; - } catch(RuntimeException e) { - releaseProvider(provider); - throw e; - } - } - - /** - * Open a stream on to the content associated with a content URI. If there - * is no data associated with the URI, FileNotFoundException is thrown. - * - * <h5>Accepts the following URI schemes:</h5> - * <ul> - * <li>content ({@link #SCHEME_CONTENT})</li> - * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> - * <li>file ({@link #SCHEME_FILE})</li> - * </ul> - * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5> - * <p> - * A Uri object can be used to reference a resource in an APK file. The - * Uri should be one of the following formats: - * <ul> - * <li><code>android.resource://package_name/id_number</code><br/> - * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. - * For example <code>com.example.myapp</code><br/> - * <code>id_number</code> is the int form of the ID.<br/> - * The easiest way to construct this form is - * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre> - * </li> - * <li><code>android.resource://package_name/type/name</code><br/> - * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. - * For example <code>com.example.myapp</code><br/> - * <code>type</code> is the string form of the resource type. For example, <code>raw</code> - * or <code>drawable</code>. - * <code>name</code> is the string form of the resource name. That is, whatever the file - * name was in your res directory, without the type extension. - * The easiest way to construct this form is - * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre> - * </li> - * </ul> - * @param uri The desired "content:" URI. - * @return InputStream - * @throws FileNotFoundException if the provided URI could not be opened. - */ - public final InputStream openInputStream(Uri uri) - throws FileNotFoundException { - String scheme = uri.getScheme(); - if (SCHEME_CONTENT.equals(scheme)) { - ParcelFileDescriptor fd = openFileDescriptor(uri, "r"); - return fd != null ? new ParcelFileDescriptor.AutoCloseInputStream(fd) : null; - } else if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { - String authority = uri.getAuthority(); - Resources r; - if (TextUtils.isEmpty(authority)) { - throw new FileNotFoundException("No authority: " + uri); - } else { - try { - r = mContext.getPackageManager().getResourcesForApplication(authority); - } catch (NameNotFoundException ex) { - throw new FileNotFoundException("No package found for authority: " + uri); - } - } - List<String> path = uri.getPathSegments(); - if (path == null) { - throw new FileNotFoundException("No path: " + uri); - } - int len = path.size(); - int id; - if (len == 1) { - try { - id = Integer.parseInt(path.get(0)); - } catch (NumberFormatException e) { - throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); - } - } else if (len == 2) { - id = r.getIdentifier(path.get(1), path.get(0), authority); - } else { - throw new FileNotFoundException("More than two path segments: " + uri); - } - if (id == 0) { - throw new FileNotFoundException("No resource found for: " + uri); - } - try { - InputStream stream = r.openRawResource(id); - return stream; - } catch (Resources.NotFoundException ex) { - throw new FileNotFoundException("Resource ID does not exist: " + uri); - } - } else if (SCHEME_FILE.equals(scheme)) { - return new FileInputStream(uri.getPath()); - } else { - throw new FileNotFoundException("Unknown scheme: " + uri); - } - } - - /** - * Open a stream on to the content associated with a content URI. If there - * is no data associated with the URI, FileNotFoundException is thrown. - * - * <h5>Accepts the following URI schemes:</h5> - * <ul> - * <li>content ({@link #SCHEME_CONTENT})</li> - * </ul> - * - * @param uri The desired "content:" URI. - * @return OutputStream - */ - public final OutputStream openOutputStream(Uri uri) - throws FileNotFoundException { - String scheme = uri.getScheme(); - if (SCHEME_CONTENT.equals(scheme)) { - ParcelFileDescriptor fd = openFileDescriptor(uri, "rw"); - return fd != null - ? new ParcelFileDescriptor.AutoCloseOutputStream(fd) : null; - } else { - throw new FileNotFoundException("Unknown scheme: " + uri); - } - } - - /** - * Open a raw file descriptor to access data under a "content:" URI. This - * interacts with the underlying {@link ContentProvider#openFile} - * ContentProvider.openFile()} method of the provider associated with the - * given URI, to retrieve any file stored there. - * - * <h5>Accepts the following URI schemes:</h5> - * <ul> - * <li>content ({@link #SCHEME_CONTENT})</li> - * </ul> - * - * @param uri The desired URI to open. - * @param mode The file mode to use, as per {@link ContentProvider#openFile - * ContentProvider.openFile}. - * @return Returns a new ParcelFileDescriptor pointing to the file. You - * own this descriptor and are responsible for closing it when done. - * @throws FileNotFoundException Throws FileNotFoundException of no - * file exists under the URI or the mode is invalid. - */ - public final ParcelFileDescriptor openFileDescriptor(Uri uri, - String mode) throws FileNotFoundException { - IContentProvider provider = acquireProvider(uri); - if (provider == null) { - throw new FileNotFoundException("No content provider: " + uri); - } - try { - ParcelFileDescriptor fd = provider.openFile(uri, mode); - if(fd == null) { - releaseProvider(provider); - return null; - } - return new ParcelFileDescriptorInner(fd, provider); - } catch (RemoteException e) { - releaseProvider(provider); - throw new FileNotFoundException("Dead content provider: " + uri); - } catch (FileNotFoundException e) { - releaseProvider(provider); - throw e; - } catch (RuntimeException e) { - releaseProvider(provider); - throw e; - } - } - - /** - * Inserts a row into a table at the given URL. - * - * If the content provider supports transactions the insertion will be atomic. - * - * @param url The URL of the table to insert into. - * @param values The initial values for the newly inserted row. The key is the column name for - * the field. Passing an empty ContentValues will create an empty row. - * @return the URL of the newly created row. - */ - public final Uri insert(Uri url, ContentValues values) - { - IContentProvider provider = acquireProvider(url); - if (provider == null) { - throw new IllegalArgumentException("Unknown URL " + url); - } - try { - return provider.insert(url, values); - } catch (RemoteException e) { - return null; - } finally { - releaseProvider(provider); - } - } - - /** - * Inserts multiple rows into a table at the given URL. - * - * This function make no guarantees about the atomicity of the insertions. - * - * @param url The URL of the table to insert into. - * @param values The initial values for the newly inserted rows. The key is the column name for - * the field. Passing null will create an empty row. - * @return the number of newly created rows. - */ - public final int bulkInsert(Uri url, ContentValues[] values) - { - IContentProvider provider = acquireProvider(url); - if (provider == null) { - throw new IllegalArgumentException("Unknown URL " + url); - } - try { - return provider.bulkInsert(url, values); - } catch (RemoteException e) { - return 0; - } finally { - releaseProvider(provider); - } - } - - /** - * Deletes row(s) specified by a content URI. - * - * If the content provider supports transactions, the deletion will be atomic. - * - * @param url The URL of the row to delete. - * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause - (excluding the WHERE itself). - * @return The number of rows deleted. - */ - public final int delete(Uri url, String where, String[] selectionArgs) - { - IContentProvider provider = acquireProvider(url); - if (provider == null) { - throw new IllegalArgumentException("Unknown URL " + url); - } - try { - return provider.delete(url, where, selectionArgs); - } catch (RemoteException e) { - return -1; - } finally { - releaseProvider(provider); - } - } - - /** - * Update row(s) in a content URI. - * - * If the content provider supports transactions the update will be atomic. - * - * @param uri The URI to modify. - * @param values The new field values. The key is the column name for the field. - A null value will remove an existing field value. - * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause - (excluding the WHERE itself). - * @return the URL of the newly created row - * @throws NullPointerException if uri or values are null - */ - public final int update(Uri uri, ContentValues values, String where, - String[] selectionArgs) { - IContentProvider provider = acquireProvider(uri); - if (provider == null) { - throw new IllegalArgumentException("Unknown URI " + uri); - } - try { - return provider.update(uri, values, where, selectionArgs); - } catch (RemoteException e) { - return -1; - } finally { - releaseProvider(provider); - } - } - - /** - * Returns the content provider for the given content URI.. - * - * @param uri The URI to a content provider - * @return The ContentProvider for the given URI, or null if no content provider is found. - * @hide - */ - public final IContentProvider acquireProvider(Uri uri) - { - if (!SCHEME_CONTENT.equals(uri.getScheme())) { - return null; - } - String auth = uri.getAuthority(); - if (auth != null) { - return acquireProvider(mContext, uri.getAuthority()); - } - return null; - } - - /** - * @hide - */ - public final IContentProvider acquireProvider(String name) { - if(name == null) { - return null; - } - return acquireProvider(mContext, name); - } - - /** - * Register an observer class that gets callbacks when data identified by a - * given content URI changes. - * - * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI - * for a whole class of content. - * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code> - * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI - * specified by <em>uri</em> will cause notifications to be sent. If true, than any URI values - * at or below the specified URI will also trigger a match. - * @param observer The object that receives callbacks when changes occur. - * @see #unregisterContentObserver - */ - public final void registerContentObserver(Uri uri, boolean notifyForDescendents, - ContentObserver observer) - { - try { - ContentServiceNative.getDefault().registerContentObserver(uri, notifyForDescendents, - observer.getContentObserver()); - } catch (RemoteException e) { - } - } - - /** - * Unregisters a change observer. - * - * @param observer The previously registered observer that is no longer needed. - * @see #registerContentObserver - */ - public final void unregisterContentObserver(ContentObserver observer) { - try { - IContentObserver contentObserver = observer.releaseContentObserver(); - if (contentObserver != null) { - ContentServiceNative.getDefault().unregisterContentObserver( - contentObserver); - } - } catch (RemoteException e) { - } - } - - /** - * Notify registered observers that a row was updated. - * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}. - * By default, CursorAdapter objects will get this notification. - * - * @param uri - * @param observer The observer that originated the change, may be <code>null</null> - */ - public void notifyChange(Uri uri, ContentObserver observer) { - notifyChange(uri, observer, true /* sync to network */); - } - - /** - * Notify registered observers that a row was updated. - * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}. - * By default, CursorAdapter objects will get this notification. - * - * @param uri - * @param observer The observer that originated the change, may be <code>null</null> - * @param syncToNetwork If true, attempt to sync the change to the network. - */ - public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { - try { - ContentServiceNative.getDefault().notifyChange( - uri, observer == null ? null : observer.getContentObserver(), - observer != null && observer.deliverSelfNotifications(), syncToNetwork); - } catch (RemoteException e) { - } - } - - /** - * Start an asynchronous sync operation. If you want to monitor the progress - * of the sync you may register a SyncObserver. Only values of the following - * types may be used in the extras bundle: - * <ul> - * <li>Integer</li> - * <li>Long</li> - * <li>Boolean</li> - * <li>Float</li> - * <li>Double</li> - * <li>String</li> - * </ul> - * - * @param uri the uri of the provider to sync or null to sync all providers. - * @param extras any extras to pass to the SyncAdapter. - */ - public void startSync(Uri uri, Bundle extras) { - validateSyncExtrasBundle(extras); - try { - ContentServiceNative.getDefault().startSync(uri, extras); - } catch (RemoteException e) { - } - } - - /** - * Check that only values of the following types are in the Bundle: - * <ul> - * <li>Integer</li> - * <li>Long</li> - * <li>Boolean</li> - * <li>Float</li> - * <li>Double</li> - * <li>String</li> - * <li>null</li> - * </ul> - * @param extras the Bundle to check - */ - public static void validateSyncExtrasBundle(Bundle extras) { - try { - for (String key : extras.keySet()) { - Object value = extras.get(key); - if (value == null) continue; - if (value instanceof Long) continue; - if (value instanceof Integer) continue; - if (value instanceof Boolean) continue; - if (value instanceof Float) continue; - if (value instanceof Double) continue; - if (value instanceof String) continue; - throw new IllegalArgumentException("unexpected value type: " - + value.getClass().getName()); - } - } catch (IllegalArgumentException e) { - throw e; - } catch (RuntimeException exc) { - throw new IllegalArgumentException("error unparceling Bundle", exc); - } - } - - public void cancelSync(Uri uri) { - try { - ContentServiceNative.getDefault().cancelSync(uri); - } catch (RemoteException e) { - } - } - - private final class CursorWrapperInner extends CursorWrapper { - private IContentProvider mContentProvider; - public static final String TAG="CursorWrapperInner"; - private boolean mCloseFlag = false; - - CursorWrapperInner(Cursor cursor, IContentProvider icp) { - super(cursor); - mContentProvider = icp; - } - - @Override - public void close() { - super.close(); - ContentResolver.this.releaseProvider(mContentProvider); - mCloseFlag = true; - } - - @Override - protected void finalize() throws Throwable { - try { - if(!mCloseFlag) { - ContentResolver.this.releaseProvider(mContentProvider); - } - } finally { - super.finalize(); - } - } - } - - private final class ParcelFileDescriptorInner extends ParcelFileDescriptor { - private IContentProvider mContentProvider; - public static final String TAG="ParcelFileDescriptorInner"; - private boolean mReleaseProviderFlag = false; - - ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) { - super(pfd); - mContentProvider = icp; - } - - @Override - public void close() throws IOException { - if(!mReleaseProviderFlag) { - super.close(); - ContentResolver.this.releaseProvider(mContentProvider); - mReleaseProviderFlag = true; - } - } - - @Override - protected void finalize() throws Throwable { - if (!mReleaseProviderFlag) { - close(); - } - } - } - - private final Context mContext; - private static final String TAG = "ContentResolver"; -} diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java deleted file mode 100644 index b028868..0000000 --- a/core/java/android/content/ContentService.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2006 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.IContentObserver; -import android.database.sqlite.SQLiteException; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Config; -import android.util.Log; -import android.Manifest; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; - -/** - * {@hide} - */ -public final class ContentService extends ContentServiceNative { - private static final String TAG = "ContentService"; - private Context mContext; - private boolean mFactoryTest; - private final ObserverNode mRootNode = new ObserverNode(""); - private SyncManager mSyncManager = null; - private final Object mSyncManagerLock = new Object(); - - private SyncManager getSyncManager() { - synchronized(mSyncManagerLock) { - try { - // Try to create the SyncManager, return null if it fails (e.g. the disk is full). - if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest); - } catch (SQLiteException e) { - Log.e(TAG, "Can't create SyncManager", e); - } - return mSyncManager; - } - } - - @Override - protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP, - "caller doesn't have the DUMP permission"); - - // This makes it so that future permission checks will be in the context of this - // process rather than the caller's process. We will restore this before returning. - long identityToken = clearCallingIdentity(); - try { - if (mSyncManager == null) { - pw.println("No SyncManager created! (Disk full?)"); - } else { - mSyncManager.dump(fd, pw); - } - } finally { - restoreCallingIdentity(identityToken); - } - } - - /*package*/ ContentService(Context context, boolean factoryTest) { - mContext = context; - mFactoryTest = factoryTest; - getSyncManager(); - } - - public void registerContentObserver(Uri uri, boolean notifyForDescendents, - IContentObserver observer) { - if (observer == null || uri == null) { - throw new IllegalArgumentException("You must pass a valid uri and observer"); - } - synchronized (mRootNode) { - mRootNode.addObserver(uri, observer, notifyForDescendents); - if (Config.LOGV) Log.v(TAG, "Registered observer " + observer + " at " + uri + - " with notifyForDescendents " + notifyForDescendents); - } - } - - public void unregisterContentObserver(IContentObserver observer) { - if (observer == null) { - throw new IllegalArgumentException("You must pass a valid observer"); - } - synchronized (mRootNode) { - mRootNode.removeObserver(observer); - if (Config.LOGV) Log.v(TAG, "Unregistered observer " + observer); - } - } - - public void notifyChange(Uri uri, IContentObserver observer, - boolean observerWantsSelfNotifications, boolean syncToNetwork) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Notifying update of " + uri + " from observer " + observer - + ", syncToNetwork " + syncToNetwork); - } - // This makes it so that future permission checks will be in the context of this - // process rather than the caller's process. We will restore this before returning. - long identityToken = clearCallingIdentity(); - try { - ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); - synchronized (mRootNode) { - mRootNode.collectObservers(uri, 0, observer, observerWantsSelfNotifications, - calls); - } - final int numCalls = calls.size(); - for (int i=0; i<numCalls; i++) { - ObserverCall oc = calls.get(i); - try { - oc.mObserver.onChange(oc.mSelfNotify); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); - } - } catch (RemoteException ex) { - synchronized (mRootNode) { - Log.w(TAG, "Found dead observer, removing"); - IBinder binder = oc.mObserver.asBinder(); - final ArrayList<ObserverNode.ObserverEntry> list - = oc.mNode.mObservers; - int numList = list.size(); - for (int j=0; j<numList; j++) { - ObserverNode.ObserverEntry oe = list.get(j); - if (oe.observer.asBinder() == binder) { - list.remove(j); - j--; - numList--; - } - } - } - } - } - if (syncToNetwork) { - SyncManager syncManager = getSyncManager(); - if (syncManager != null) syncManager.scheduleLocalSync(uri); - } - } finally { - restoreCallingIdentity(identityToken); - } - } - - /** - * Hide this class since it is not part of api, - * but current unittest framework requires it to be public - * @hide - * - */ - public static final class ObserverCall { - final ObserverNode mNode; - final IContentObserver mObserver; - final boolean mSelfNotify; - - ObserverCall(ObserverNode node, IContentObserver observer, - boolean selfNotify) { - mNode = node; - mObserver = observer; - mSelfNotify = selfNotify; - } - } - - public void startSync(Uri url, Bundle extras) { - ContentResolver.validateSyncExtrasBundle(extras); - // This makes it so that future permission checks will be in the context of this - // process rather than the caller's process. We will restore this before returning. - long identityToken = clearCallingIdentity(); - try { - SyncManager syncManager = getSyncManager(); - if (syncManager != null) syncManager.startSync(url, extras); - } finally { - restoreCallingIdentity(identityToken); - } - } - - /** - * Clear all scheduled sync operations that match the uri and cancel the active sync - * if it matches the uri. If the uri is null, clear all scheduled syncs and cancel - * the active one, if there is one. - * @param uri Filter on the sync operations to cancel, or all if null. - */ - public void cancelSync(Uri uri) { - // This makes it so that future permission checks will be in the context of this - // process rather than the caller's process. We will restore this before returning. - long identityToken = clearCallingIdentity(); - try { - SyncManager syncManager = getSyncManager(); - if (syncManager != null) { - syncManager.clearScheduledSyncOperations(uri); - syncManager.cancelActiveSync(uri); - } - } finally { - restoreCallingIdentity(identityToken); - } - } - - public static IContentService main(Context context, boolean factoryTest) { - ContentService service = new ContentService(context, factoryTest); - ServiceManager.addService("content", service); - return service; - } - - /** - * Hide this class since it is not part of api, - * but current unittest framework requires it to be public - * @hide - */ - public static final class ObserverNode { - private class ObserverEntry implements IBinder.DeathRecipient { - public IContentObserver observer; - public boolean notifyForDescendents; - - public ObserverEntry(IContentObserver o, boolean n) { - observer = o; - notifyForDescendents = n; - try { - observer.asBinder().linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } - } - - public void binderDied() { - removeObserver(observer); - } - } - - public static final int INSERT_TYPE = 0; - public static final int UPDATE_TYPE = 1; - public static final int DELETE_TYPE = 2; - - private String mName; - private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>(); - private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>(); - - public ObserverNode(String name) { - mName = name; - } - - private String getUriSegment(Uri uri, int index) { - if (uri != null) { - if (index == 0) { - return uri.getAuthority(); - } else { - return uri.getPathSegments().get(index - 1); - } - } else { - return null; - } - } - - private int countUriSegments(Uri uri) { - if (uri == null) { - return 0; - } - return uri.getPathSegments().size() + 1; - } - - public void addObserver(Uri uri, IContentObserver observer, boolean notifyForDescendents) { - addObserver(uri, 0, observer, notifyForDescendents); - } - - private void addObserver(Uri uri, int index, IContentObserver observer, - boolean notifyForDescendents) { - - // If this is the leaf node add the observer - if (index == countUriSegments(uri)) { - mObservers.add(new ObserverEntry(observer, notifyForDescendents)); - return; - } - - // Look to see if the proper child already exists - String segment = getUriSegment(uri, index); - int N = mChildren.size(); - for (int i = 0; i < N; i++) { - ObserverNode node = mChildren.get(i); - if (node.mName.equals(segment)) { - node.addObserver(uri, index + 1, observer, notifyForDescendents); - return; - } - } - - // No child found, create one - ObserverNode node = new ObserverNode(segment); - mChildren.add(node); - node.addObserver(uri, index + 1, observer, notifyForDescendents); - } - - public boolean removeObserver(IContentObserver observer) { - int size = mChildren.size(); - for (int i = 0; i < size; i++) { - boolean empty = mChildren.get(i).removeObserver(observer); - if (empty) { - mChildren.remove(i); - i--; - size--; - } - } - - IBinder observerBinder = observer.asBinder(); - size = mObservers.size(); - for (int i = 0; i < size; i++) { - ObserverEntry entry = mObservers.get(i); - if (entry.observer.asBinder() == observerBinder) { - mObservers.remove(i); - // We no longer need to listen for death notifications. Remove it. - observerBinder.unlinkToDeath(entry, 0); - break; - } - } - - if (mChildren.size() == 0 && mObservers.size() == 0) { - return true; - } - return false; - } - - private void collectMyObservers(Uri uri, - boolean leaf, IContentObserver observer, boolean selfNotify, - ArrayList<ObserverCall> calls) - { - int N = mObservers.size(); - IBinder observerBinder = observer == null ? null : observer.asBinder(); - for (int i = 0; i < N; i++) { - ObserverEntry entry = mObservers.get(i); - - // Don't notify the observer if it sent the notification and isn't interesed - // in self notifications - if (entry.observer.asBinder() == observerBinder && !selfNotify) { - continue; - } - - // Make sure the observer is interested in the notification - if (leaf || (!leaf && entry.notifyForDescendents)) { - calls.add(new ObserverCall(this, entry.observer, selfNotify)); - } - } - } - - public void collectObservers(Uri uri, int index, IContentObserver observer, - boolean selfNotify, ArrayList<ObserverCall> calls) { - String segment = null; - int segmentCount = countUriSegments(uri); - if (index >= segmentCount) { - // This is the leaf node, notify all observers - collectMyObservers(uri, true, observer, selfNotify, calls); - } else if (index < segmentCount){ - segment = getUriSegment(uri, index); - // Notify any observers at this level who are interested in descendents - collectMyObservers(uri, false, observer, selfNotify, calls); - } - - int N = mChildren.size(); - for (int i = 0; i < N; i++) { - ObserverNode node = mChildren.get(i); - if (segment == null || node.mName.equals(segment)) { - // We found the child, - node.collectObservers(uri, index + 1, observer, selfNotify, calls); - if (segment != null) { - break; - } - } - } - } - } -} diff --git a/core/java/android/content/ContentServiceNative.java b/core/java/android/content/ContentServiceNative.java deleted file mode 100644 index f050501..0000000 --- a/core/java/android/content/ContentServiceNative.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2006 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.IContentObserver; -import android.net.Uri; -import android.os.Binder; -import android.os.RemoteException; -import android.os.IBinder; -import android.os.Parcel; -import android.os.ServiceManager; -import android.os.Bundle; -import android.util.Config; -import android.util.Log; - -/** - * {@hide} - */ -abstract class ContentServiceNative extends Binder implements IContentService -{ - public ContentServiceNative() - { - attachInterface(this, descriptor); - } - - /** - * Cast a Binder object into a content resolver interface, generating - * a proxy if needed. - */ - static public IContentService asInterface(IBinder obj) - { - if (obj == null) { - return null; - } - IContentService in = - (IContentService)obj.queryLocalInterface(descriptor); - if (in != null) { - return in; - } - - return new ContentServiceProxy(obj); - } - - /** - * Retrieve the system's default/global content service. - */ - static public IContentService getDefault() - { - if (gDefault != null) { - return gDefault; - } - IBinder b = ServiceManager.getService("content"); - if (Config.LOGV) Log.v("ContentService", "default service binder = " + b); - gDefault = asInterface(b); - if (Config.LOGV) Log.v("ContentService", "default service = " + gDefault); - return gDefault; - } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) - { - try { - switch (code) { - case REGISTER_CONTENT_OBSERVER_TRANSACTION: { - Uri uri = Uri.CREATOR.createFromParcel(data); - boolean notifyForDescendents = data.readInt() != 0; - IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder()); - registerContentObserver(uri, notifyForDescendents, observer); - return true; - } - - case UNREGISTER_CHANGE_OBSERVER_TRANSACTION: { - IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder()); - unregisterContentObserver(observer); - return true; - } - - case NOTIFY_CHANGE_TRANSACTION: { - Uri uri = Uri.CREATOR.createFromParcel(data); - IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder()); - boolean observerWantsSelfNotifications = data.readInt() != 0; - boolean syncToNetwork = data.readInt() != 0; - notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork); - return true; - } - - case START_SYNC_TRANSACTION: { - Uri url = null; - int hasUrl = data.readInt(); - if (hasUrl != 0) { - url = Uri.CREATOR.createFromParcel(data); - } - startSync(url, data.readBundle()); - return true; - } - - case CANCEL_SYNC_TRANSACTION: { - Uri url = null; - int hasUrl = data.readInt(); - if (hasUrl != 0) { - url = Uri.CREATOR.createFromParcel(data); - } - cancelSync(url); - return true; - } - - default: - return super.onTransact(code, data, reply, flags); - } - } catch (Exception e) { - Log.e("ContentServiceNative", "Caught exception in transact", e); - } - - return false; - } - - public IBinder asBinder() - { - return this; - } - - private static IContentService gDefault; -} - - -final class ContentServiceProxy implements IContentService -{ - public ContentServiceProxy(IBinder remote) - { - mRemote = remote; - } - - public IBinder asBinder() - { - return mRemote; - } - - public void registerContentObserver(Uri uri, boolean notifyForDescendents, - IContentObserver observer) throws RemoteException - { - Parcel data = Parcel.obtain(); - uri.writeToParcel(data, 0); - data.writeInt(notifyForDescendents ? 1 : 0); - data.writeStrongInterface(observer); - mRemote.transact(REGISTER_CONTENT_OBSERVER_TRANSACTION, data, null, 0); - data.recycle(); - } - - public void unregisterContentObserver(IContentObserver observer) throws RemoteException { - Parcel data = Parcel.obtain(); - data.writeStrongInterface(observer); - mRemote.transact(UNREGISTER_CHANGE_OBSERVER_TRANSACTION, data, null, 0); - data.recycle(); - } - - public void notifyChange(Uri uri, IContentObserver observer, - boolean observerWantsSelfNotifications, boolean syncToNetwork) - throws RemoteException { - Parcel data = Parcel.obtain(); - uri.writeToParcel(data, 0); - data.writeStrongInterface(observer); - data.writeInt(observerWantsSelfNotifications ? 1 : 0); - data.writeInt(syncToNetwork ? 1 : 0); - mRemote.transact(NOTIFY_CHANGE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); - data.recycle(); - } - - public void startSync(Uri url, Bundle extras) throws RemoteException { - Parcel data = Parcel.obtain(); - if (url == null) { - data.writeInt(0); - } else { - data.writeInt(1); - url.writeToParcel(data, 0); - } - extras.writeToParcel(data, 0); - mRemote.transact(START_SYNC_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); - data.recycle(); - } - - public void cancelSync(Uri url) throws RemoteException { - Parcel data = Parcel.obtain(); - if (url == null) { - data.writeInt(0); - } else { - data.writeInt(1); - url.writeToParcel(data, 0); - } - mRemote.transact(CANCEL_SYNC_TRANSACTION, data, null /* reply */, IBinder.FLAG_ONEWAY); - data.recycle(); - } - - private IBinder mRemote; -} - diff --git a/core/java/android/content/ContentUris.java b/core/java/android/content/ContentUris.java deleted file mode 100644 index aa76034..0000000 --- a/core/java/android/content/ContentUris.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.net.Uri; - -/** - * Utility methods useful for working with content {@link android.net.Uri}s, - * those with a "content" scheme. - */ -public class ContentUris { - - /** - * Converts the last path segment to a long. - * - * <p>This supports a common convention for content URIs where an ID is - * stored in the last segment. - * - * @throws UnsupportedOperationException if this isn't a hierarchical URI - * @throws NumberFormatException if the last segment isn't a number - * - * @return the long conversion of the last segment or -1 if the path is - * empty - */ - public static long parseId(Uri contentUri) { - String last = contentUri.getLastPathSegment(); - return last == null ? -1 : Long.parseLong(last); - } - - /** - * Appends the given ID to the end of the path. - * - * @param builder to append the ID to - * @param id to append - * - * @return the given builder - */ - public static Uri.Builder appendId(Uri.Builder builder, long id) { - return builder.appendEncodedPath(String.valueOf(id)); - } - - /** - * Appends the given ID to the end of the path. - * - * @param contentUri to start with - * @param id to append - * - * @return a new URI with the given ID appended to the end of the path - */ - public static Uri withAppendedId(Uri contentUri, long id) { - return appendId(contentUri.buildUpon(), id).build(); - } -} diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java deleted file mode 100644 index 532cc03..0000000 --- a/core/java/android/content/ContentValues.java +++ /dev/null @@ -1,501 +0,0 @@ -/* - * 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.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * This class is used to store a set of values that the {@link ContentResolver} - * can process. - */ -public final class ContentValues implements Parcelable { - public static final String TAG = "ContentValues"; - - /** Holds the actual values */ - private HashMap<String, Object> mValues; - - /** - * Creates an empty set of values using the default initial size - */ - public ContentValues() { - // Choosing a default size of 8 based on analysis of typical - // consumption by applications. - mValues = new HashMap<String, Object>(8); - } - - /** - * Creates an empty set of values using the given initial size - * - * @param size the initial size of the set of values - */ - public ContentValues(int size) { - mValues = new HashMap<String, Object>(size, 1.0f); - } - - /** - * Creates a set of values copied from the given set - * - * @param from the values to copy - */ - public ContentValues(ContentValues from) { - mValues = new HashMap<String, Object>(from.mValues); - } - - /** - * Creates a set of values copied from the given HashMap. This is used - * by the Parcel unmarshalling code. - * - * @param from the values to start with - * {@hide} - */ - private ContentValues(HashMap<String, Object> values) { - mValues = values; - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof ContentValues)) { - return false; - } - return mValues.equals(((ContentValues) object).mValues); - } - - @Override - public int hashCode() { - return mValues.hashCode(); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, String value) { - mValues.put(key, value); - } - - /** - * Adds all values from the passed in ContentValues. - * - * @param other the ContentValues from which to copy - */ - public void putAll(ContentValues other) { - mValues.putAll(other.mValues); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Byte value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Short value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Integer value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Long value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Float value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Double value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, Boolean value) { - mValues.put(key, value); - } - - /** - * Adds a value to the set. - * - * @param key the name of the value to put - * @param value the data for the value to put - */ - public void put(String key, byte[] value) { - mValues.put(key, value); - } - - /** - * Adds a null value to the set. - * - * @param key the name of the value to make null - */ - public void putNull(String key) { - mValues.put(key, null); - } - - /** - * Returns the number of values. - * - * @return the number of values - */ - public int size() { - return mValues.size(); - } - - /** - * Remove a single value. - * - * @param key the name of the value to remove - */ - public void remove(String key) { - mValues.remove(key); - } - - /** - * Removes all values. - */ - public void clear() { - mValues.clear(); - } - - /** - * Returns true if this object has the named value. - * - * @param key the value to check for - * @return {@code true} if the value is present, {@code false} otherwise - */ - public boolean containsKey(String key) { - return mValues.containsKey(key); - } - - /** - * Gets a value. Valid value types are {@link String}, {@link Boolean}, and - * {@link Number} implementations. - * - * @param key the value to get - * @return the data for the value - */ - public Object get(String key) { - return mValues.get(key); - } - - /** - * Gets a value and converts it to a String. - * - * @param key the value to get - * @return the String for the value - */ - public String getAsString(String key) { - Object value = mValues.get(key); - return value != null ? mValues.get(key).toString() : null; - } - - /** - * Gets a value and converts it to a Long. - * - * @param key the value to get - * @return the Long value, or null if the value is missing or cannot be converted - */ - public Long getAsLong(String key) { - Object value = mValues.get(key); - try { - return value != null ? ((Number) value).longValue() : null; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - try { - return Long.valueOf(value.toString()); - } catch (NumberFormatException e2) { - Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key); - return null; - } - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Long"); - return null; - } - } - } - - /** - * Gets a value and converts it to an Integer. - * - * @param key the value to get - * @return the Integer value, or null if the value is missing or cannot be converted - */ - public Integer getAsInteger(String key) { - Object value = mValues.get(key); - try { - return value != null ? ((Number) value).intValue() : null; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - try { - return Integer.valueOf(value.toString()); - } catch (NumberFormatException e2) { - Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key); - return null; - } - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Integer"); - return null; - } - } - } - - /** - * Gets a value and converts it to a Short. - * - * @param key the value to get - * @return the Short value, or null if the value is missing or cannot be converted - */ - public Short getAsShort(String key) { - Object value = mValues.get(key); - try { - return value != null ? ((Number) value).shortValue() : null; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - try { - return Short.valueOf(value.toString()); - } catch (NumberFormatException e2) { - Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key); - return null; - } - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Short"); - return null; - } - } - } - - /** - * Gets a value and converts it to a Byte. - * - * @param key the value to get - * @return the Byte value, or null if the value is missing or cannot be converted - */ - public Byte getAsByte(String key) { - Object value = mValues.get(key); - try { - return value != null ? ((Number) value).byteValue() : null; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - try { - return Byte.valueOf(value.toString()); - } catch (NumberFormatException e2) { - Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key); - return null; - } - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Byte"); - return null; - } - } - } - - /** - * Gets a value and converts it to a Double. - * - * @param key the value to get - * @return the Double value, or null if the value is missing or cannot be converted - */ - public Double getAsDouble(String key) { - Object value = mValues.get(key); - try { - return value != null ? ((Number) value).doubleValue() : null; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - try { - return Double.valueOf(value.toString()); - } catch (NumberFormatException e2) { - Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key); - return null; - } - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Double"); - return null; - } - } - } - - /** - * Gets a value and converts it to a Float. - * - * @param key the value to get - * @return the Float value, or null if the value is missing or cannot be converted - */ - public Float getAsFloat(String key) { - Object value = mValues.get(key); - try { - return value != null ? ((Number) value).floatValue() : null; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - try { - return Float.valueOf(value.toString()); - } catch (NumberFormatException e2) { - Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key); - return null; - } - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Float"); - return null; - } - } - } - - /** - * Gets a value and converts it to a Boolean. - * - * @param key the value to get - * @return the Boolean value, or null if the value is missing or cannot be converted - */ - public Boolean getAsBoolean(String key) { - Object value = mValues.get(key); - try { - return (Boolean) value; - } catch (ClassCastException e) { - if (value instanceof CharSequence) { - return Boolean.valueOf(value.toString()); - } else { - Log.e(TAG, "Cannot cast value for " + key + " to a Boolean"); - return null; - } - } - } - - /** - * Gets a value that is a byte array. Note that this method will not convert - * any other types to byte arrays. - * - * @param key the value to get - * @return the byte[] value, or null is the value is missing or not a byte[] - */ - public byte[] getAsByteArray(String key) { - Object value = mValues.get(key); - if (value instanceof byte[]) { - return (byte[]) value; - } else { - return null; - } - } - - /** - * Returns a set of all of the keys and values - * - * @return a set of all of the keys and values - */ - public Set<Map.Entry<String, Object>> valueSet() { - return mValues.entrySet(); - } - - public static final Parcelable.Creator<ContentValues> CREATOR = - new Parcelable.Creator<ContentValues>() { - @SuppressWarnings({"deprecation", "unchecked"}) - public ContentValues createFromParcel(Parcel in) { - // TODO - what ClassLoader should be passed to readHashMap? - HashMap<String, Object> values = in.readHashMap(null); - return new ContentValues(values); - } - - public ContentValues[] newArray(int size) { - return new ContentValues[size]; - } - }; - - public int describeContents() { - return 0; - } - - @SuppressWarnings("deprecation") - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeMap(mValues); - } - - /** - * Unsupported, here until we get proper bulk insert APIs. - * {@hide} - */ - @Deprecated - public void putStringArrayList(String key, ArrayList<String> value) { - mValues.put(key, value); - } - - /** - * Unsupported, here until we get proper bulk insert APIs. - * {@hide} - */ - @SuppressWarnings("unchecked") - @Deprecated - public ArrayList<String> getStringArrayList(String key) { - return (ArrayList<String>) mValues.get(key); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (String name : mValues.keySet()) { - String value = getAsString(name); - if (sb.length() > 0) sb.append(" "); - sb.append(name + "=" + value); - } - return sb.toString(); - } -} diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java deleted file mode 100644 index e0fe533..0000000 --- a/core/java/android/content/Context.java +++ /dev/null @@ -1,1654 +0,0 @@ -/* - * Copyright (C) 2006 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.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.AttributeSet; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Interface to global information about an application environment. This is - * an abstract class whose implementation is provided by - * the Android system. It - * allows access to application-specific resources and classes, as well as - * up-calls for application-level operations such as launching activities, - * broadcasting and receiving intents, etc. - */ -public abstract class Context { - /** - * File creation mode: the default mode, where the created file can only - * be accessed by the calling application (or all applications sharing the - * same user ID). - * @see #MODE_WORLD_READABLE - * @see #MODE_WORLD_WRITEABLE - */ - public static final int MODE_PRIVATE = 0x0000; - /** - * File creation mode: allow all other applications to have read access - * to the created file. - * @see #MODE_PRIVATE - * @see #MODE_WORLD_WRITEABLE - */ - public static final int MODE_WORLD_READABLE = 0x0001; - /** - * File creation mode: allow all other applications to have write access - * to the created file. - * @see #MODE_PRIVATE - * @see #MODE_WORLD_READABLE - */ - public static final int MODE_WORLD_WRITEABLE = 0x0002; - /** - * File creation mode: for use with {@link #openFileOutput}, if the file - * already exists then write data to the end of the existing file - * instead of erasing it. - * @see #openFileOutput - */ - public static final int MODE_APPEND = 0x8000; - - /** - * Flag for {@link #bindService}: automatically create the service as long - * as the binding exists. Note that while this will create the service, - * its {@link android.app.Service#onStart} method will still only be called due to an - * explicit call to {@link #startService}. Even without that, though, - * this still provides you with access to the service object while the - * service is created. - * - * <p>Specifying this flag also tells the system to treat the service - * as being as important as your own process -- that is, when deciding - * which process should be killed to free memory, the service will only - * be considered a candidate as long as the processes of any such bindings - * is also a candidate to be killed. This is to avoid situations where - * the service is being continually created and killed due to low memory. - */ - public static final int BIND_AUTO_CREATE = 0x0001; - - /** - * Flag for {@link #bindService}: include debugging help for mismatched - * calls to unbind. When this flag is set, the callstack of the following - * {@link #unbindService} call is retained, to be printed if a later - * incorrect unbind call is made. Note that doing this requires retaining - * information about the binding that was made for the lifetime of the app, - * resulting in a leak -- this should only be used for debugging. - */ - public static final int BIND_DEBUG_UNBIND = 0x0002; - - /** Return an AssetManager instance for your application's package. */ - public abstract AssetManager getAssets(); - - /** Return a Resources instance for your application's package. */ - public abstract Resources getResources(); - - /** Return PackageManager instance to find global package information. */ - public abstract PackageManager getPackageManager(); - - /** Return a ContentResolver instance for your application's package. */ - public abstract ContentResolver getContentResolver(); - - /** - * Return the Looper for the main thread of the current process. This is - * the thread used to dispatch calls to application components (activities, - * services, etc). - */ - public abstract Looper getMainLooper(); - - /** - * Return the context of the single, global Application object of the - * current process. - */ - public abstract Context getApplicationContext(); - - /** - * Return a localized, styled CharSequence from the application's package's - * default string table. - * - * @param resId Resource id for the CharSequence text - */ - public final CharSequence getText(int resId) { - return getResources().getText(resId); - } - - /** - * Return a localized string from the application's package's - * default string table. - * - * @param resId Resource id for the string - */ - public final String getString(int resId) { - return getResources().getString(resId); - } - - /** - * Return a localized formatted string from the application's package's - * default string table, substituting the format arguments as defined in - * {@link java.util.Formatter} and {@link java.lang.String#format}. - * - * @param resId Resource id for the format string - * @param formatArgs The format arguments that will be used for substitution. - */ - - public final String getString(int resId, Object... formatArgs) { - return getResources().getString(resId, formatArgs); - } - - /** - * Set the base theme for this context. Note that this should be called - * before any views are instantiated in the Context (for example before - * calling {@link android.app.Activity#setContentView} or - * {@link android.view.LayoutInflater#inflate}). - * - * @param resid The style resource describing the theme. - */ - public abstract void setTheme(int resid); - - /** - * Return the Theme object associated with this Context. - */ - public abstract Resources.Theme getTheme(); - - /** - * Retrieve styled attribute information in this Context's theme. See - * {@link Resources.Theme#obtainStyledAttributes(int[])} - * for more information. - * - * @see Resources.Theme#obtainStyledAttributes(int[]) - */ - public final TypedArray obtainStyledAttributes( - int[] attrs) { - return getTheme().obtainStyledAttributes(attrs); - } - - /** - * Retrieve styled attribute information in this Context's theme. See - * {@link Resources.Theme#obtainStyledAttributes(int, int[])} - * for more information. - * - * @see Resources.Theme#obtainStyledAttributes(int, int[]) - */ - public final TypedArray obtainStyledAttributes( - int resid, int[] attrs) throws Resources.NotFoundException { - return getTheme().obtainStyledAttributes(resid, attrs); - } - - /** - * Retrieve styled attribute information in this Context's theme. See - * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)} - * for more information. - * - * @see Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int) - */ - public final TypedArray obtainStyledAttributes( - AttributeSet set, int[] attrs) { - return getTheme().obtainStyledAttributes(set, attrs, 0, 0); - } - - /** - * Retrieve styled attribute information in this Context's theme. See - * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)} - * for more information. - * - * @see Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int) - */ - public final TypedArray obtainStyledAttributes( - AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { - return getTheme().obtainStyledAttributes( - set, attrs, defStyleAttr, defStyleRes); - } - - /** - * Return a class loader you can use to retrieve classes in this package. - */ - public abstract ClassLoader getClassLoader(); - - /** Return the name of this application's package. */ - public abstract String getPackageName(); - - /** - * {@hide} - * Return the full path to this context's resource files. This is the ZIP files - * containing the application's resources. - * - * <p>Note: this is not generally useful for applications, since they should - * not be directly accessing the file system. - * - * - * @return String Path to the resources. - */ - public abstract String getPackageResourcePath(); - - /** - * {@hide} - * Return the full path to this context's code and asset files. This is the ZIP files - * containing the application's code and assets. - * - * <p>Note: this is not generally useful for applications, since they should - * not be directly accessing the file system. - * - * - * @return String Path to the code and assets. - */ - public abstract String getPackageCodePath(); - - /** - * Retrieve and hold the contents of the preferences file 'name', returning - * a SharedPreferences through which you can retrieve and modify its - * values. Only one instance of the SharedPreferences object is returned - * to any callers for the same name, meaning they will see each other's - * edits as soon as they are made. - * - * @param name Desired preferences file. If a preferences file by this name - * does not exist, it will be created when you retrieve an - * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_WORLD_READABLE} - * and {@link #MODE_WORLD_WRITEABLE} to control permissions. - * - * @return Returns the single SharedPreferences instance that can be used - * to retrieve and modify the preference values. - * - * @see #MODE_PRIVATE - * @see #MODE_WORLD_READABLE - * @see #MODE_WORLD_WRITEABLE - */ - public abstract SharedPreferences getSharedPreferences(String name, - int mode); - - /** - * Open a private file associated with this Context's application package - * for reading. - * - * @param name The name of the file to open; can not contain path - * separators. - * - * @return FileInputStream Resulting input stream. - * - * @see #openFileOutput - * @see #fileList - * @see #deleteFile - * @see java.io.FileInputStream#FileInputStream(String) - */ - public abstract FileInputStream openFileInput(String name) - throws FileNotFoundException; - - /** - * Open a private file associated with this Context's application package - * for writing. Creates the file if it doesn't already exist. - * - * @param name The name of the file to open; can not contain path - * separators. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_APPEND} to append to an existing file, - * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control - * permissions. - * - * @return FileOutputStream Resulting output stream. - * - * @see #MODE_APPEND - * @see #MODE_PRIVATE - * @see #MODE_WORLD_READABLE - * @see #MODE_WORLD_WRITEABLE - * @see #openFileInput - * @see #fileList - * @see #deleteFile - * @see java.io.FileOutputStream#FileOutputStream(String) - */ - public abstract FileOutputStream openFileOutput(String name, int mode) - throws FileNotFoundException; - - /** - * Delete the given private file associated with this Context's - * application package. - * - * @param name The name of the file to delete; can not contain path - * separators. - * - * @return True if the file was successfully deleted; else - * false. - * - * @see #openFileInput - * @see #openFileOutput - * @see #fileList - * @see java.io.File#delete() - */ - public abstract boolean deleteFile(String name); - - /** - * Returns the absolute path on the filesystem where a file created with - * {@link #openFileOutput} is stored. - * - * @param name The name of the file for which you would like to get - * its path. - * - * @return Returns an absolute path to the given file. - * - * @see #openFileOutput - * @see #getFilesDir - * @see #getDir - */ - public abstract File getFileStreamPath(String name); - - /** - * Returns the absolute path to the directory on the filesystem where - * files created with {@link #openFileOutput} are stored. - * - * @return Returns the path of the directory holding application files. - * - * @see #openFileOutput - * @see #getFileStreamPath - * @see #getDir - */ - public abstract File getFilesDir(); - - /** - * Returns the absolute path to the application specific cache directory - * on the filesystem. These files will be ones that get deleted first when the - * device runs low on storage - * There is no guarantee when these files will be deleted. - * - * @return Returns the path of the directory holding application cache files. - * - * @see #openFileOutput - * @see #getFileStreamPath - * @see #getDir - */ - public abstract File getCacheDir(); - - /** - * Returns an array of strings naming the private files associated with - * this Context's application package. - * - * @return Array of strings naming the private files. - * - * @see #openFileInput - * @see #openFileOutput - * @see #deleteFile - */ - public abstract String[] fileList(); - - /** - * Retrieve, creating if needed, a new directory in which the application - * can place its own custom data files. You can use the returned File - * object to create and access files in this directory. Note that files - * created through a File object will only be accessible by your own - * application; you can only set the mode of the entire directory, not - * of individual files. - * - * @param name Name of the directory to retrieve. This is a directory - * that is created as part of your application data. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_WORLD_READABLE} and - * {@link #MODE_WORLD_WRITEABLE} to control permissions. - * - * @return Returns a File object for the requested directory. The directory - * will have been created if it does not already exist. - * - * @see #openFileOutput(String, int) - */ - public abstract File getDir(String name, int mode); - - /** - * Open a new private SQLiteDatabase associated with this Context's - * application package. Create the database file if it doesn't exist. - * - * @param name The name (unique in the application package) of the database. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_WORLD_READABLE} - * and {@link #MODE_WORLD_WRITEABLE} to control permissions. - * @param factory An optional factory class that is called to instantiate a - * cursor when query is called. - * - * @return The contents of a newly created database with the given name. - * @throws android.database.sqlite.SQLiteException if the database file could not be opened. - * - * @see #MODE_PRIVATE - * @see #MODE_WORLD_READABLE - * @see #MODE_WORLD_WRITEABLE - * @see #deleteDatabase - */ - public abstract SQLiteDatabase openOrCreateDatabase(String name, - int mode, CursorFactory factory); - - /** - * Delete an existing private SQLiteDatabase associated with this Context's - * application package. - * - * @param name The name (unique in the application package) of the - * database. - * - * @return True if the database was successfully deleted; else false. - * - * @see #openOrCreateDatabase - */ - public abstract boolean deleteDatabase(String name); - - /** - * Returns the absolute path on the filesystem where a database created with - * {@link #openOrCreateDatabase} is stored. - * - * @param name The name of the database for which you would like to get - * its path. - * - * @return Returns an absolute path to the given database. - * - * @see #openOrCreateDatabase - */ - public abstract File getDatabasePath(String name); - - /** - * Returns an array of strings naming the private databases associated with - * this Context's application package. - * - * @return Array of strings naming the private databases. - * - * @see #openOrCreateDatabase - * @see #deleteDatabase - */ - public abstract String[] databaseList(); - - /** - * Like {@link #peekWallpaper}, but always returns a valid Drawable. If - * no wallpaper is set, the system default wallpaper is returned. - * - * @return Returns a Drawable object that will draw the wallpaper. - */ - public abstract Drawable getWallpaper(); - - /** - * Retrieve the current system wallpaper. This is returned as an - * abstract Drawable that you can install in a View to display whatever - * wallpaper the user has currently set. If there is no wallpaper set, - * a null pointer is returned. - * - * @return Returns a Drawable object that will draw the wallpaper or a - * null pointer if these is none. - */ - public abstract Drawable peekWallpaper(); - - /** - * Returns the desired minimum width for the wallpaper. Callers of - * {@link #setWallpaper(android.graphics.Bitmap)} or - * {@link #setWallpaper(java.io.InputStream)} should check this value - * beforehand to make sure the supplied wallpaper respects the desired - * minimum width. - * - * If the returned value is <= 0, the caller should use the width of - * the default display instead. - * - * @return The desired minimum width for the wallpaper. This value should - * be honored by applications that set the wallpaper but it is not - * mandatory. - */ - public abstract int getWallpaperDesiredMinimumWidth(); - - /** - * Returns the desired minimum height for the wallpaper. Callers of - * {@link #setWallpaper(android.graphics.Bitmap)} or - * {@link #setWallpaper(java.io.InputStream)} should check this value - * beforehand to make sure the supplied wallpaper respects the desired - * minimum height. - * - * If the returned value is <= 0, the caller should use the height of - * the default display instead. - * - * @return The desired minimum height for the wallpaper. This value should - * be honored by applications that set the wallpaper but it is not - * mandatory. - */ - public abstract int getWallpaperDesiredMinimumHeight(); - - /** - * Change the current system wallpaper to a bitmap. The given bitmap is - * converted to a PNG and stored as the wallpaper. On success, the intent - * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast. - * - * @param bitmap The bitmap to save. - * - * @throws IOException If an error occurs reverting to the default - * wallpaper. - */ - public abstract void setWallpaper(Bitmap bitmap) throws IOException; - - /** - * Change the current system wallpaper to a specific byte stream. The - * give InputStream is copied into persistent storage and will now be - * used as the wallpaper. Currently it must be either a JPEG or PNG - * image. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} - * is broadcast. - * - * @param data A stream containing the raw data to install as a wallpaper. - * - * @throws IOException If an error occurs reverting to the default - * wallpaper. - */ - public abstract void setWallpaper(InputStream data) throws IOException; - - /** - * Remove any currently set wallpaper, reverting to the system's default - * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} - * is broadcast. - * - * @throws IOException If an error occurs reverting to the default - * wallpaper. - */ - public abstract void clearWallpaper() throws IOException; - - /** - * Launch a new activity. You will not receive any information about when - * the activity exits. - * - * <p>Note that if this method is being called from outside of an - * {@link android.app.Activity} Context, then the Intent must include - * the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag. This is because, - * without being started from an existing Activity, there is no existing - * task in which to place the new activity and thus it needs to be placed - * in its own separate task. - * - * <p>This method throws {@link ActivityNotFoundException} - * if there was no Activity found to run the given Intent. - * - * @param intent The description of the activity to start. - * - * @throws ActivityNotFoundException - * - * @see PackageManager#resolveActivity - */ - public abstract void startActivity(Intent intent); - - /** - * Broadcast the given intent to all interested BroadcastReceivers. This - * call is asynchronous; it returns immediately, and you will continue - * executing while the receivers are run. No results are propagated from - * receivers and receivers can not abort the broadcast. If you want - * to allow receivers to propagate results or abort the broadcast, you must - * send an ordered broadcast using - * {@link #sendOrderedBroadcast(Intent, String)}. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) - */ - public abstract void sendBroadcast(Intent intent); - - /** - * Broadcast the given intent to all interested BroadcastReceivers, allowing - * an optional required permission to be enforced. This - * call is asynchronous; it returns immediately, and you will continue - * executing while the receivers are run. No results are propagated from - * receivers and receivers can not abort the broadcast. If you want - * to allow receivers to propagate results or abort the broadcast, you must - * send an ordered broadcast using - * {@link #sendOrderedBroadcast(Intent, String)}. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast. - * @param receiverPermission (optional) String naming a permissions that - * a receiver must hold in order to receive your broadcast. - * If null, no permission is required. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent) - * @see #sendOrderedBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) - */ - public abstract void sendBroadcast(Intent intent, - String receiverPermission); - - /** - * Broadcast the given intent to all interested BroadcastReceivers, delivering - * them one at a time to allow more preferred receivers to consume the - * broadcast before it is delivered to less preferred receivers. This - * call is asynchronous; it returns immediately, and you will continue - * executing while the receivers are run. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast. - * @param receiverPermission (optional) String naming a permissions that - * a receiver must hold in order to receive your broadcast. - * If null, no permission is required. - * - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see #sendBroadcast(Intent) - * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) - */ - public abstract void sendOrderedBroadcast(Intent intent, - String receiverPermission); - - /** - * Version of {@link #sendBroadcast(Intent)} that allows you to - * receive data back from the broadcast. This is accomplished by - * supplying your own BroadcastReceiver when calling, which will be - * treated as a final receiver at the end of the broadcast -- its - * {@link BroadcastReceiver#onReceive} method will be called with - * the result values collected from the other receivers. If you use - * an <var>resultReceiver</var> with this method, then the broadcast will - * be serialized in the same way as calling - * {@link #sendOrderedBroadcast(Intent, String)}. - * - * <p>Like {@link #sendBroadcast(Intent)}, this method is - * asynchronous; it will return before - * resultReceiver.onReceive() is called. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast. - * @param receiverPermission String naming a permissions that - * a receiver must hold in order to receive your broadcast. - * If null, no permission is required. - * @param resultReceiver Your own BroadcastReceiver to treat as the final - * receiver of the broadcast. - * @param scheduler A custom Handler with which to schedule the - * resultReceiver callback; if null it will be - * scheduled in the Context's main thread. - * @param initialCode An initial value for the result code. Often - * Activity.RESULT_OK. - * @param initialData An initial value for the result data. Often - * null. - * @param initialExtras An initial value for the result extras. Often - * null. - * - * @see #sendBroadcast(Intent) - * @see #sendBroadcast(Intent, String) - * @see #sendOrderedBroadcast(Intent, String) - * @see #sendStickyBroadcast(Intent) - * @see android.content.BroadcastReceiver - * @see #registerReceiver - * @see android.app.Activity#RESULT_OK - */ - public abstract void sendOrderedBroadcast(Intent intent, - String receiverPermission, BroadcastReceiver resultReceiver, - Handler scheduler, int initialCode, String initialData, - Bundle initialExtras); - - /** - * Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the - * Intent you are sending stays around after the broadcast is complete, - * so that others can quickly retrieve that data through the return - * value of {@link #registerReceiver(BroadcastReceiver, IntentFilter)}. In - * all other ways, this behaves the same as - * {@link #sendBroadcast(Intent)}. - * - * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY} - * permission in order to use this API. If you do not hold that - * permission, {@link SecurityException} will be thrown. - * - * @param intent The Intent to broadcast; all receivers matching this - * Intent will receive the broadcast, and the Intent will be held to - * be re-broadcast to future receivers. - * - * @see #sendBroadcast(Intent) - */ - public abstract void sendStickyBroadcast(Intent intent); - - /** - * Remove the data previously sent with {@link #sendStickyBroadcast}, - * so that it is as if the sticky broadcast had never happened. - * - * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY} - * permission in order to use this API. If you do not hold that - * permission, {@link SecurityException} will be thrown. - * - * @param intent The Intent that was previously broadcast. - * - * @see #sendStickyBroadcast - */ - public abstract void removeStickyBroadcast(Intent intent); - - /** - * Register an BroadcastReceiver to be run in the main activity thread. The - * <var>receiver</var> will be called with any broadcast Intent that - * matches <var>filter</var>, in the main application thread. - * - * <p>The system may broadcast Intents that are "sticky" -- these stay - * around after the broadcast as finished, to be sent to any later - * registrations. If your IntentFilter matches one of these sticky - * Intents, that Intent will be returned by this function - * <strong>and</strong> sent to your <var>receiver</var> as if it had just - * been broadcast. - * - * <p>There may be multiple sticky Intents that match <var>filter</var>, - * in which case each of these will be sent to <var>receiver</var>. In - * this case, only one of these can be returned directly by the function; - * which of these that is returned is arbitrarily decided by the system. - * - * <p>If you know the Intent your are registering for is sticky, you can - * supply null for your <var>receiver</var>. In this case, no receiver is - * registered -- the function simply returns the sticky Intent that - * matches <var>filter</var>. In the case of multiple matches, the same - * rules as described above apply. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * <p class="note">Note: this method <em>can not be called from an - * {@link BroadcastReceiver} component</em>. It is okay, however, to use - * this method from another BroadcastReceiver that has itself been registered with - * {@link #registerReceiver}, since the lifetime of such an BroadcastReceiver - * is tied to another object (the one that registered it).</p> - * - * @param receiver The BroadcastReceiver to handle the broadcast. - * @param filter Selects the Intent broadcasts to be received. - * - * @return The first sticky intent found that matches <var>filter</var>, - * or null if there are none. - * - * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) - * @see #sendBroadcast - * @see #unregisterReceiver - */ - public abstract Intent registerReceiver(BroadcastReceiver receiver, - IntentFilter filter); - - /** - * Register to receive intent broadcasts, to run in the context of - * <var>scheduler</var>. See - * {@link #registerReceiver(BroadcastReceiver, IntentFilter)} for more - * information. This allows you to enforce permissions on who can - * broadcast intents to your receiver, or have the receiver run in - * a different thread than the main application thread. - * - * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. - * - * @param receiver The BroadcastReceiver to handle the broadcast. - * @param filter Selects the Intent broadcasts to be received. - * @param broadcastPermission String naming a permissions that a - * broadcaster must hold in order to send an Intent to you. If null, - * no permission is required. - * @param scheduler Handler identifying the thread that will receive - * the Intent. If null, the main thread of the process will be used. - * - * @return The first sticky intent found that matches <var>filter</var>, - * or null if there are none. - * - * @see #registerReceiver(BroadcastReceiver, IntentFilter) - * @see #sendBroadcast - * @see #unregisterReceiver - */ - public abstract Intent registerReceiver(BroadcastReceiver receiver, - IntentFilter filter, - String broadcastPermission, - Handler scheduler); - - /** - * Unregister a previously registered BroadcastReceiver. <em>All</em> - * filters that have been registered for this BroadcastReceiver will be - * removed. - * - * @param receiver The BroadcastReceiver to unregister. - * - * @see #registerReceiver - */ - public abstract void unregisterReceiver(BroadcastReceiver receiver); - - /** - * Request that a given application service be started. The Intent - * can either contain the complete class name of a specific service - * implementation to start, or an abstract definition through the - * action and other fields of the kind of service to start. If this service - * is not already running, it will be instantiated and started (creating a - * process for it if needed); if it is running then it remains running. - * - * <p>Every call to this method will result in a corresponding call to - * the target service's {@link android.app.Service#onStart} method, - * with the <var>intent</var> given here. This provides a convenient way - * to submit jobs to a service without having to bind and call on to its - * interface. - * - * <p>Using startService() overrides the default service lifetime that is - * managed by {@link #bindService}: it requires the service to remain - * running until {@link #stopService} is called, regardless of whether - * any clients are connected to it. Note that calls to startService() - * are not nesting: no matter how many times you call startService(), - * a single call to {@link #stopService} will stop it. - * - * <p>The system attempts to keep running services around as much as - * possible. The only time they should be stopped is if the current - * foreground application is using so many resources that the service needs - * to be killed. If any errors happen in the service's process, it will - * automatically be restarted. - * - * <p>This function will throw {@link SecurityException} if you do not - * have permission to start the given service. - * - * @param service Identifies the service to be started. The Intent may - * specify either an explicit component name to start, or a logical - * description (action, category, etc) to match an - * {@link IntentFilter} published by a service. Additional values - * may be included in the Intent extras to supply arguments along with - * this specific start call. - * - * @return If the service is being started or is already running, the - * {@link ComponentName} of the actual service that was started is - * returned; else if the service does not exist null is returned. - * - * @throws SecurityException - * - * @see #stopService - * @see #bindService - */ - public abstract ComponentName startService(Intent service); - - /** - * Request that a given application service be stopped. If the service is - * not running, nothing happens. Otherwise it is stopped. Note that calls - * to startService() are not counted -- this stops the service no matter - * how many times it was started. - * - * <p>Note that if a stopped service still has {@link ServiceConnection} - * objects bound to it with the {@link #BIND_AUTO_CREATE} set, it will - * not be destroyed until all of these bindings are removed. See - * the {@link android.app.Service} documentation for more details on a - * service's lifecycle. - * - * <p>This function will throw {@link SecurityException} if you do not - * have permission to stop the given service. - * - * @param service Description of the service to be stopped. The Intent may - * specify either an explicit component name to start, or a logical - * description (action, category, etc) to match an - * {@link IntentFilter} published by a service. - * - * @return If there is a service matching the given Intent that is already - * running, then it is stopped and true is returned; else false is returned. - * - * @throws SecurityException - * - * @see #startService - */ - public abstract boolean stopService(Intent service); - - /** - * Connect to an application service, creating it if needed. This defines - * a dependency between your application and the service. The given - * <var>conn</var> will receive the service object when its created and be - * told if it dies and restarts. The service will be considered required - * by the system only for as long as the calling context exists. For - * example, if this Context is an Activity that is stopped, the service will - * not be required to continue running until the Activity is resumed. - * - * <p>This function will throw {@link SecurityException} if you do not - * have permission to bind to the given service. - * - * <p class="note">Note: this method <em>can not be called from an - * {@link BroadcastReceiver} component</em>. A pattern you can use to - * communicate from an BroadcastReceiver to a Service is to call - * {@link #startService} with the arguments containing the command to be - * sent, with the service calling its - * {@link android.app.Service#stopSelf(int)} method when done executing - * that command. See the API demo App/Service/Service Start Arguments - * Controller for an illustration of this. It is okay, however, to use - * this method from an BroadcastReceiver that has been registered with - * {@link #registerReceiver}, since the lifetime of this BroadcastReceiver - * is tied to another object (the one that registered it).</p> - * - * @param service Identifies the service to connect to. The Intent may - * specify either an explicit component name, or a logical - * description (action, category, etc) to match an - * {@link IntentFilter} published by a service. - * @param conn Receives information as the service is started and stopped. - * @param flags Operation options for the binding. May be 0 or - * {@link #BIND_AUTO_CREATE}. - * @return If you have successfully bound to the service, true is returned; - * false is returned if the connection is not made so you will not - * receive the service object. - * - * @throws SecurityException - * - * @see #unbindService - * @see #startService - * @see #BIND_AUTO_CREATE - */ - public abstract boolean bindService(Intent service, ServiceConnection conn, - int flags); - - /** - * Disconnect from an application service. You will no longer receive - * calls as the service is restarted, and the service is now allowed to - * stop at any time. - * - * @param conn The connection interface previously supplied to - * bindService(). - * - * @see #bindService - */ - public abstract void unbindService(ServiceConnection conn); - - /** - * Start executing an {@link android.app.Instrumentation} class. The given - * Instrumentation component will be run by killing its target application - * (if currently running), starting the target process, instantiating the - * instrumentation component, and then letting it drive the application. - * - * <p>This function is not synchronous -- it returns as soon as the - * instrumentation has started and while it is running. - * - * <p>Instrumentation is normally only allowed to run against a package - * that is either unsigned or signed with a signature that the - * the instrumentation package is also signed with (ensuring the target - * trusts the instrumentation). - * - * @param className Name of the Instrumentation component to be run. - * @param profileFile Optional path to write profiling data as the - * instrumentation runs, or null for no profiling. - * @param arguments Additional optional arguments to pass to the - * instrumentation, or null. - * - * @return Returns true if the instrumentation was successfully started, - * else false if it could not be found. - */ - public abstract boolean startInstrumentation(ComponentName className, - String profileFile, Bundle arguments); - - /** - * Return the handle to a system-level service by name. The class of the - * returned object varies by the requested name. Currently available names - * are: - * - * <dl> - * <dt> {@link #WINDOW_SERVICE} ("window") - * <dd> The top-level window manager in which you can place custom - * windows. The returned object is a {@link android.view.WindowManager}. - * <dt> {@link #LAYOUT_INFLATER_SERVICE} ("layout_inflater") - * <dd> A {@link android.view.LayoutInflater} for inflating layout resources - * in this context. - * <dt> {@link #ACTIVITY_SERVICE} ("activity") - * <dd> A {@link android.app.ActivityManager} for interacting with the - * global activity state of the system. - * <dt> {@link #POWER_SERVICE} ("power") - * <dd> A {@link android.os.PowerManager} for controlling power - * management. - * <dt> {@link #ALARM_SERVICE} ("alarm") - * <dd> A {@link android.app.AlarmManager} for receiving intents at the - * time of your choosing. - * <dt> {@link #NOTIFICATION_SERVICE} ("notification") - * <dd> A {@link android.app.NotificationManager} for informing the user - * of background events. - * <dt> {@link #KEYGUARD_SERVICE} ("keyguard") - * <dd> A {@link android.app.KeyguardManager} for controlling keyguard. - * <dt> {@link #LOCATION_SERVICE} ("location") - * <dd> A {@link android.location.LocationManager} for controlling location - * (e.g., GPS) updates. - * <dt> {@link #SEARCH_SERVICE} ("search") - * <dd> A {@link android.app.SearchManager} for handling search. - * <dt> {@link #VIBRATOR_SERVICE} ("vibrator") - * <dd> A {@link android.os.Vibrator} for interacting with the vibrator - * hardware. - * <dt> {@link #CONNECTIVITY_SERVICE} ("connection") - * <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for - * handling management of network connections. - * <dt> {@link #WIFI_SERVICE} ("wifi") - * <dd> A {@link android.net.wifi.WifiManager WifiManager} for management of - * Wi-Fi connectivity. - * <dt> {@link #INPUT_METHOD_SERVICE} ("input_method") - * <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager} - * for management of input methods. - * </dl> - * - * <p>Note: System services obtained via this API may be closely associated with - * the Context in which they are obtained from. In general, do not share the - * service objects between various different contexts (Activities, Applications, - * Services, Providers, etc.) - * - * @param name The name of the desired service. - * - * @return The service or null if the name does not exist. - * - * @see #WINDOW_SERVICE - * @see android.view.WindowManager - * @see #LAYOUT_INFLATER_SERVICE - * @see android.view.LayoutInflater - * @see #ACTIVITY_SERVICE - * @see android.app.ActivityManager - * @see #POWER_SERVICE - * @see android.os.PowerManager - * @see #ALARM_SERVICE - * @see android.app.AlarmManager - * @see #NOTIFICATION_SERVICE - * @see android.app.NotificationManager - * @see #KEYGUARD_SERVICE - * @see android.app.KeyguardManager - * @see #LOCATION_SERVICE - * @see android.location.LocationManager - * @see #SEARCH_SERVICE - * @see android.app.SearchManager - * @see #SENSOR_SERVICE - * @see android.hardware.SensorManager - * @see #VIBRATOR_SERVICE - * @see android.os.Vibrator - * @see #CONNECTIVITY_SERVICE - * @see android.net.ConnectivityManager - * @see #WIFI_SERVICE - * @see android.net.wifi.WifiManager - * @see #AUDIO_SERVICE - * @see android.media.AudioManager - * @see #TELEPHONY_SERVICE - * @see android.telephony.TelephonyManager - * @see #INPUT_METHOD_SERVICE - * @see android.view.inputmethod.InputMethodManager - */ - public abstract Object getSystemService(String name); - - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.os.PowerManager} for controlling power management, - * including "wake locks," which let you keep the device on while - * you're running long tasks. - */ - public static final String POWER_SERVICE = "power"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.view.WindowManager} for accessing the system's window - * manager. - * - * @see #getSystemService - * @see android.view.WindowManager - */ - public static final String WINDOW_SERVICE = "window"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.view.LayoutInflater} for inflating layout resources in this - * context. - * - * @see #getSystemService - * @see android.view.LayoutInflater - */ - public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.app.ActivityManager} for interacting with the global - * system state. - * - * @see #getSystemService - * @see android.app.ActivityManager - */ - public static final String ACTIVITY_SERVICE = "activity"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.app.AlarmManager} for receiving intents at a - * time of your choosing. - * - * @see #getSystemService - * @see android.app.AlarmManager - */ - public static final String ALARM_SERVICE = "alarm"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.app.NotificationManager} for informing the user of - * background events. - * - * @see #getSystemService - * @see android.app.NotificationManager - */ - public static final String NOTIFICATION_SERVICE = "notification"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.app.NotificationManager} for controlling keyguard. - * - * @see #getSystemService - * @see android.app.KeyguardManager - */ - public static final String KEYGUARD_SERVICE = "keyguard"; - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.location.LocationManager} for controlling location - * updates. - * - * @see #getSystemService - * @see android.location.LocationManager - */ - public static final String LOCATION_SERVICE = "location"; - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.app.SearchManager} for handling searches. - * - * @see #getSystemService - * @see android.app.SearchManager - */ - public static final String SEARCH_SERVICE = "search"; - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.hardware.SensorManager} for accessing sensors. - * - * @see #getSystemService - * @see android.hardware.SensorManager - */ - public static final String SENSOR_SERVICE = "sensor"; - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.bluetooth.BluetoothDevice} for interacting with Bluetooth. - * - * @see #getSystemService - * @see android.bluetooth.BluetoothDevice - * @hide - */ - public static final String BLUETOOTH_SERVICE = "bluetooth"; - /** - * Use with {@link #getSystemService} to retrieve a - * com.android.server.WallpaperService for accessing wallpapers. - * - * @see #getSystemService - */ - public static final String WALLPAPER_SERVICE = "wallpaper"; - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.os.Vibrator} for interacting with the vibration hardware. - * - * @see #getSystemService - * @see android.os.Vibrator - */ - public static final String VIBRATOR_SERVICE = "vibrator"; - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.app.StatusBarManager} for interacting with the status bar. - * - * @see #getSystemService - * @see android.app.StatusBarManager - * @hide - */ - public static final String STATUS_BAR_SERVICE = "statusbar"; - - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.net.ConnectivityManager} for handling management of - * network connections. - * - * @see #getSystemService - * @see android.net.ConnectivityManager - */ - public static final String CONNECTIVITY_SERVICE = "connectivity"; - - /** - * Use with {@link #getSystemService} to retrieve a {@link - * android.net.wifi.WifiManager} for handling management of - * Wi-Fi access. - * - * @see #getSystemService - * @see android.net.wifi.WifiManager - */ - public static final String WIFI_SERVICE = "wifi"; - - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.media.AudioManager} for handling management of volume, - * ringer modes and audio routing. - * - * @see #getSystemService - * @see android.media.AudioManager - */ - public static final String AUDIO_SERVICE = "audio"; - - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.telephony.TelephonyManager} for handling management the - * telephony features of the device. - * - * @see #getSystemService - * @see android.telephony.TelephonyManager - */ - public static final String TELEPHONY_SERVICE = "phone"; - - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.text.ClipboardManager} for accessing and modifying - * the contents of the global clipboard. - * - * @see #getSystemService - * @see android.text.ClipboardManager - */ - public static final String CLIPBOARD_SERVICE = "clipboard"; - - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.view.inputmethod.InputMethodManager} for accessing input - * methods. - * - * @see #getSystemService - */ - public static final String INPUT_METHOD_SERVICE = "input_method"; - - /** - * Use with {@link #getSystemService} to retrieve a - * {@blink android.gadget.GadgetManager} for accessing wallpapers. - * - * @hide - * @see #getSystemService - */ - public static final String GADGET_SERVICE = "gadget"; - - /** - * Determine whether the given permission is allowed for a particular - * process and user ID running in the system. - * - * @param permission The name of the permission being checked. - * @param pid The process ID being checked against. Must be > 0. - * @param uid The user ID being checked against. A uid of 0 is the root - * user, which will pass every permission check. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the given - * pid/uid is allowed that permission, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - * - * @see PackageManager#checkPermission(String, String) - * @see #checkCallingPermission - */ - public abstract int checkPermission(String permission, int pid, int uid); - - /** - * Determine whether the calling process of an IPC you are handling has been - * granted a particular permission. This is basically the same as calling - * {@link #checkPermission(String, int, int)} with the pid and uid returned - * by {@link android.os.Binder#getCallingPid} and - * {@link android.os.Binder#getCallingUid}. One important difference - * is that if you are not currently processing an IPC, this function - * will always fail. This is done to protect against accidentally - * leaking permissions; you can use {@link #checkCallingOrSelfPermission} - * to avoid this protection. - * - * @param permission The name of the permission being checked. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the calling - * pid/uid is allowed that permission, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - * - * @see PackageManager#checkPermission(String, String) - * @see #checkPermission - * @see #checkCallingOrSelfPermission - */ - public abstract int checkCallingPermission(String permission); - - /** - * Determine whether the calling process of an IPC <em>or you</em> have been - * granted a particular permission. This is the same as - * {@link #checkCallingPermission}, except it grants your own permissions - * if you are not currently processing an IPC. Use with care! - * - * @param permission The name of the permission being checked. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the calling - * pid/uid is allowed that permission, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - * - * @see PackageManager#checkPermission(String, String) - * @see #checkPermission - * @see #checkCallingPermission - */ - public abstract int checkCallingOrSelfPermission(String permission); - - /** - * If the given permission is not allowed for a particular process - * and user ID running in the system, throw a {@link SecurityException}. - * - * @param permission The name of the permission being checked. - * @param pid The process ID being checked against. Must be > 0. - * @param uid The user ID being checked against. A uid of 0 is the root - * user, which will pass every permission check. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkPermission(String, int, int) - */ - public abstract void enforcePermission( - String permission, int pid, int uid, String message); - - /** - * If the calling process of an IPC you are handling has not been - * granted a particular permission, throw a {@link - * SecurityException}. This is basically the same as calling - * {@link #enforcePermission(String, int, int, String)} with the - * pid and uid returned by {@link android.os.Binder#getCallingPid} - * and {@link android.os.Binder#getCallingUid}. One important - * difference is that if you are not currently processing an IPC, - * this function will always throw the SecurityException. This is - * done to protect against accidentally leaking permissions; you - * can use {@link #enforceCallingOrSelfPermission} to avoid this - * protection. - * - * @param permission The name of the permission being checked. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkCallingPermission(String) - */ - public abstract void enforceCallingPermission( - String permission, String message); - - /** - * If neither you nor the calling process of an IPC you are - * handling has been granted a particular permission, throw a - * {@link SecurityException}. This is the same as {@link - * #enforceCallingPermission}, except it grants your own - * permissions if you are not currently processing an IPC. Use - * with care! - * - * @param permission The name of the permission being checked. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkCallingOrSelfPermission(String) - */ - public abstract void enforceCallingOrSelfPermission( - String permission, String message); - - /** - * Grant permission to access a specific Uri to another package, regardless - * of whether that package has general permission to access the Uri's - * content provider. This can be used to grant specific, temporary - * permissions, typically in response to user interaction (such as the - * user opening an attachment that you would like someone else to - * display). - * - * <p>Normally you should use {@link Intent#FLAG_GRANT_READ_URI_PERMISSION - * Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION - * Intent.FLAG_GRANT_WRITE_URI_PERMISSION} with the Intent being used to - * start an activity instead of this function directly. If you use this - * function directly, you should be sure to call - * {@link #revokeUriPermission} when the target should no longer be allowed - * to access it. - * - * <p>To succeed, the content provider owning the Uri must have set the - * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions - * grantUriPermissions} attribute in its manifest or included the - * {@link android.R.styleable#AndroidManifestGrantUriPermission - * <grant-uri-permissions>} tag. - * - * @param toPackage The package you would like to allow to access the Uri. - * @param uri The Uri you would like to grant access to. - * @param modeFlags The desired access modes. Any combination of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION - * Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION - * Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * - * @see #revokeUriPermission - */ - public abstract void grantUriPermission(String toPackage, Uri uri, - int modeFlags); - - /** - * Remove all permissions to access a particular content provider Uri - * that were previously added with {@link #grantUriPermission}. The given - * Uri will match all previously granted Uris that are the same or a - * sub-path of the given Uri. That is, revoking "content://foo/one" will - * revoke both "content://foo/target" and "content://foo/target/sub", but not - * "content://foo". - * - * @param uri The Uri you would like to revoke access to. - * @param modeFlags The desired access modes. Any combination of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION - * Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION - * Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * - * @see #grantUriPermission - */ - public abstract void revokeUriPermission(Uri uri, int modeFlags); - - /** - * Determine whether a particular process and user ID has been granted - * permission to access a specific URI. This only checks for permissions - * that have been explicitly granted -- if the given process/uid has - * more general access to the URI's content provider then this check will - * always fail. - * - * @param uri The uri that is being checked. - * @param pid The process ID being checked against. Must be > 0. - * @param uid The user ID being checked against. A uid of 0 is the root - * user, which will pass every permission check. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the given - * pid/uid is allowed to access that uri, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - * - * @see #checkCallingUriPermission - */ - public abstract int checkUriPermission(Uri uri, int pid, int uid, int modeFlags); - - /** - * Determine whether the calling process and user ID has been - * granted permission to access a specific URI. This is basically - * the same as calling {@link #checkUriPermission(Uri, int, int, - * int)} with the pid and uid returned by {@link - * android.os.Binder#getCallingPid} and {@link - * android.os.Binder#getCallingUid}. One important difference is - * that if you are not currently processing an IPC, this function - * will always fail. - * - * @param uri The uri that is being checked. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the caller - * is allowed to access that uri, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - * - * @see #checkUriPermission(Uri, int, int, int) - */ - public abstract int checkCallingUriPermission(Uri uri, int modeFlags); - - /** - * Determine whether the calling process of an IPC <em>or you</em> has been granted - * permission to access a specific URI. This is the same as - * {@link #checkCallingUriPermission}, except it grants your own permissions - * if you are not currently processing an IPC. Use with care! - * - * @param uri The uri that is being checked. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the caller - * is allowed to access that uri, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - * - * @see #checkCallingUriPermission - */ - public abstract int checkCallingOrSelfUriPermission(Uri uri, int modeFlags); - - /** - * Check both a Uri and normal permission. This allows you to perform - * both {@link #checkPermission} and {@link #checkUriPermission} in one - * call. - * - * @param uri The Uri whose permission is to be checked, or null to not - * do this check. - * @param readPermission The permission that provides overall read access, - * or null to not do this check. - * @param writePermission The permission that provides overall write - * acess, or null to not do this check. - * @param pid The process ID being checked against. Must be > 0. - * @param uid The user ID being checked against. A uid of 0 is the root - * user, which will pass every permission check. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * - * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the caller - * is allowed to access that uri or holds one of the given permissions, or - * {@link PackageManager#PERMISSION_DENIED} if it is not. - */ - public abstract int checkUriPermission(Uri uri, String readPermission, - String writePermission, int pid, int uid, int modeFlags); - - /** - * If a particular process and user ID has not been granted - * permission to access a specific URI, throw {@link - * SecurityException}. This only checks for permissions that have - * been explicitly granted -- if the given process/uid has more - * general access to the URI's content provider then this check - * will always fail. - * - * @param uri The uri that is being checked. - * @param pid The process ID being checked against. Must be > 0. - * @param uid The user ID being checked against. A uid of 0 is the root - * user, which will pass every permission check. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkUriPermission(Uri, int, int, int) - */ - public abstract void enforceUriPermission( - Uri uri, int pid, int uid, int modeFlags, String message); - - /** - * If the calling process and user ID has not been granted - * permission to access a specific URI, throw {@link - * SecurityException}. This is basically the same as calling - * {@link #enforceUriPermission(Uri, int, int, int, String)} with - * the pid and uid returned by {@link - * android.os.Binder#getCallingPid} and {@link - * android.os.Binder#getCallingUid}. One important difference is - * that if you are not currently processing an IPC, this function - * will always throw a SecurityException. - * - * @param uri The uri that is being checked. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkCallingUriPermission(Uri, int) - */ - public abstract void enforceCallingUriPermission( - Uri uri, int modeFlags, String message); - - /** - * If the calling process of an IPC <em>or you</em> has not been - * granted permission to access a specific URI, throw {@link - * SecurityException}. This is the same as {@link - * #enforceCallingUriPermission}, except it grants your own - * permissions if you are not currently processing an IPC. Use - * with care! - * - * @param uri The uri that is being checked. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkCallingOrSelfUriPermission(Uri, int) - */ - public abstract void enforceCallingOrSelfUriPermission( - Uri uri, int modeFlags, String message); - - /** - * Enforce both a Uri and normal permission. This allows you to perform - * both {@link #enforcePermission} and {@link #enforceUriPermission} in one - * call. - * - * @param uri The Uri whose permission is to be checked, or null to not - * do this check. - * @param readPermission The permission that provides overall read access, - * or null to not do this check. - * @param writePermission The permission that provides overall write - * acess, or null to not do this check. - * @param pid The process ID being checked against. Must be > 0. - * @param uid The user ID being checked against. A uid of 0 is the root - * user, which will pass every permission check. - * @param modeFlags The type of access to grant. May be one or both of - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. - * @param message A message to include in the exception if it is thrown. - * - * @see #checkUriPermission(Uri, String, String, int, int, int) - */ - public abstract void enforceUriPermission( - Uri uri, String readPermission, String writePermission, - int pid, int uid, int modeFlags, String message); - - /** - * Flag for use with {@link #createPackageContext}: include the application - * code with the context. This means loading code into the caller's - * process, so that {@link #getClassLoader()} can be used to instantiate - * the application's classes. Setting this flags imposes security - * restrictions on what application context you can access; if the - * requested application can not be safely loaded into your process, - * java.lang.SecurityException will be thrown. If this flag is not set, - * there will be no restrictions on the packages that can be loaded, - * but {@link #getClassLoader} will always return the default system - * class loader. - */ - public static final int CONTEXT_INCLUDE_CODE = 0x00000001; - - /** - * Flag for use with {@link #createPackageContext}: ignore any security - * restrictions on the Context being requested, allowing it to always - * be loaded. For use with {@link #CONTEXT_INCLUDE_CODE} to allow code - * to be loaded into a process even when it isn't safe to do so. Use - * with extreme care! - */ - public static final int CONTEXT_IGNORE_SECURITY = 0x00000002; - - /** - * Return a new Context object for the given application name. This - * Context is the same as what the named application gets when it is - * launched, containing the same resources and class loader. Each call to - * this method returns a new instance of a Context object; Context objects - * are not shared, however they share common state (Resources, ClassLoader, - * etc) so the Context instance itself is fairly lightweight. - * - * <p>Throws {@link PackageManager.NameNotFoundException} if there is no - * application with the given package name. - * - * <p>Throws {@link java.lang.SecurityException} if the Context requested - * can not be loaded into the caller's process for security reasons (see - * {@link #CONTEXT_INCLUDE_CODE} for more information}. - * - * @param packageName Name of the application's package. - * @param flags Option flags, one of {@link #CONTEXT_INCLUDE_CODE} - * or {@link #CONTEXT_IGNORE_SECURITY}. - * - * @return A Context for the application. - * - * @throws java.lang.SecurityException - * @throws PackageManager.NameNotFoundException if there is no application with - * the given package name - */ - public abstract Context createPackageContext(String packageName, - int flags) throws PackageManager.NameNotFoundException; -} diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java deleted file mode 100644 index 36e1c34..0000000 --- a/core/java/android/content/ContextWrapper.java +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2006 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.content.pm.PackageManager; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Proxying implementation of Context that simply delegates all of its calls to - * another Context. Can be subclassed to modify behavior without changing - * the original Context. - */ -public class ContextWrapper extends Context { - Context mBase; - - public ContextWrapper(Context base) { - mBase = base; - } - - /** - * Set the base context for this ContextWrapper. All calls will then be - * delegated to the base context. Throws - * IllegalStateException if a base context has already been set. - * - * @param base The new base context for this wrapper. - */ - protected void attachBaseContext(Context base) { - if (mBase != null) { - throw new IllegalStateException("Base context already set"); - } - mBase = base; - } - - /** - * @return the base context as set by the constructor or setBaseContext - */ - public Context getBaseContext() { - return mBase; - } - - @Override - public AssetManager getAssets() { - return mBase.getAssets(); - } - - @Override - public Resources getResources() - { - return mBase.getResources(); - } - - @Override - public PackageManager getPackageManager() { - return mBase.getPackageManager(); - } - - @Override - public ContentResolver getContentResolver() { - return mBase.getContentResolver(); - } - - @Override - public Looper getMainLooper() { - return mBase.getMainLooper(); - } - - @Override - public Context getApplicationContext() { - return mBase.getApplicationContext(); - } - - @Override - public void setTheme(int resid) { - mBase.setTheme(resid); - } - - @Override - public Resources.Theme getTheme() { - return mBase.getTheme(); - } - - @Override - public ClassLoader getClassLoader() { - return mBase.getClassLoader(); - } - - @Override - public String getPackageName() { - return mBase.getPackageName(); - } - - @Override - public String getPackageResourcePath() { - return mBase.getPackageResourcePath(); - } - - @Override - public String getPackageCodePath() { - return mBase.getPackageCodePath(); - } - - @Override - public SharedPreferences getSharedPreferences(String name, int mode) { - return mBase.getSharedPreferences(name, mode); - } - - @Override - public FileInputStream openFileInput(String name) - throws FileNotFoundException { - return mBase.openFileInput(name); - } - - @Override - public FileOutputStream openFileOutput(String name, int mode) - throws FileNotFoundException { - return mBase.openFileOutput(name, mode); - } - - @Override - public boolean deleteFile(String name) { - return mBase.deleteFile(name); - } - - @Override - public File getFileStreamPath(String name) { - return mBase.getFileStreamPath(name); - } - - @Override - public String[] fileList() { - return mBase.fileList(); - } - - @Override - public File getFilesDir() { - return mBase.getFilesDir(); - } - - @Override - public File getCacheDir() { - return mBase.getCacheDir(); - } - - @Override - public File getDir(String name, int mode) { - return mBase.getDir(name, mode); - } - - @Override - public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) { - return mBase.openOrCreateDatabase(name, mode, factory); - } - - @Override - public boolean deleteDatabase(String name) { - return mBase.deleteDatabase(name); - } - - @Override - public File getDatabasePath(String name) { - return mBase.getDatabasePath(name); - } - - @Override - public String[] databaseList() { - return mBase.databaseList(); - } - - @Override - public Drawable getWallpaper() { - return mBase.getWallpaper(); - } - - @Override - public Drawable peekWallpaper() { - return mBase.peekWallpaper(); - } - - @Override - public int getWallpaperDesiredMinimumWidth() { - return mBase.getWallpaperDesiredMinimumWidth(); - } - - @Override - public int getWallpaperDesiredMinimumHeight() { - return mBase.getWallpaperDesiredMinimumHeight(); - } - - @Override - public void setWallpaper(Bitmap bitmap) throws IOException { - mBase.setWallpaper(bitmap); - } - - @Override - public void setWallpaper(InputStream data) throws IOException { - mBase.setWallpaper(data); - } - - @Override - public void clearWallpaper() throws IOException { - mBase.clearWallpaper(); - } - - @Override - public void startActivity(Intent intent) { - mBase.startActivity(intent); - } - - @Override - public void sendBroadcast(Intent intent) { - mBase.sendBroadcast(intent); - } - - @Override - public void sendBroadcast(Intent intent, String receiverPermission) { - mBase.sendBroadcast(intent, receiverPermission); - } - - @Override - public void sendOrderedBroadcast(Intent intent, - String receiverPermission) { - mBase.sendOrderedBroadcast(intent, receiverPermission); - } - - @Override - public void sendOrderedBroadcast( - Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, - Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { - mBase.sendOrderedBroadcast(intent, receiverPermission, - resultReceiver, scheduler, initialCode, - initialData, initialExtras); - } - - @Override - public void sendStickyBroadcast(Intent intent) { - mBase.sendStickyBroadcast(intent); - } - - @Override - public void removeStickyBroadcast(Intent intent) { - mBase.removeStickyBroadcast(intent); - } - - @Override - public Intent registerReceiver( - BroadcastReceiver receiver, IntentFilter filter) { - return mBase.registerReceiver(receiver, filter); - } - - @Override - public Intent registerReceiver( - BroadcastReceiver receiver, IntentFilter filter, - String broadcastPermission, Handler scheduler) { - return mBase.registerReceiver(receiver, filter, broadcastPermission, - scheduler); - } - - @Override - public void unregisterReceiver(BroadcastReceiver receiver) { - mBase.unregisterReceiver(receiver); - } - - @Override - public ComponentName startService(Intent service) { - return mBase.startService(service); - } - - @Override - public boolean stopService(Intent name) { - return mBase.stopService(name); - } - - @Override - public boolean bindService(Intent service, ServiceConnection conn, - int flags) { - return mBase.bindService(service, conn, flags); - } - - @Override - public void unbindService(ServiceConnection conn) { - mBase.unbindService(conn); - } - - @Override - public boolean startInstrumentation(ComponentName className, - String profileFile, Bundle arguments) { - return mBase.startInstrumentation(className, profileFile, arguments); - } - - @Override - public Object getSystemService(String name) { - return mBase.getSystemService(name); - } - - @Override - public int checkPermission(String permission, int pid, int uid) { - return mBase.checkPermission(permission, pid, uid); - } - - @Override - public int checkCallingPermission(String permission) { - return mBase.checkCallingPermission(permission); - } - - @Override - public int checkCallingOrSelfPermission(String permission) { - return mBase.checkCallingOrSelfPermission(permission); - } - - @Override - public void enforcePermission( - String permission, int pid, int uid, String message) { - mBase.enforcePermission(permission, pid, uid, message); - } - - @Override - public void enforceCallingPermission(String permission, String message) { - mBase.enforceCallingPermission(permission, message); - } - - @Override - public void enforceCallingOrSelfPermission( - String permission, String message) { - mBase.enforceCallingOrSelfPermission(permission, message); - } - - @Override - public void grantUriPermission(String toPackage, Uri uri, int modeFlags) { - mBase.grantUriPermission(toPackage, uri, modeFlags); - } - - @Override - public void revokeUriPermission(Uri uri, int modeFlags) { - mBase.revokeUriPermission(uri, modeFlags); - } - - @Override - public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { - return mBase.checkUriPermission(uri, pid, uid, modeFlags); - } - - @Override - public int checkCallingUriPermission(Uri uri, int modeFlags) { - return mBase.checkCallingUriPermission(uri, modeFlags); - } - - @Override - public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { - return mBase.checkCallingOrSelfUriPermission(uri, modeFlags); - } - - @Override - public int checkUriPermission(Uri uri, String readPermission, - String writePermission, int pid, int uid, int modeFlags) { - return mBase.checkUriPermission(uri, readPermission, writePermission, - pid, uid, modeFlags); - } - - @Override - public void enforceUriPermission( - Uri uri, int pid, int uid, int modeFlags, String message) { - mBase.enforceUriPermission(uri, pid, uid, modeFlags, message); - } - - @Override - public void enforceCallingUriPermission( - Uri uri, int modeFlags, String message) { - mBase.enforceCallingUriPermission(uri, modeFlags, message); - } - - @Override - public void enforceCallingOrSelfUriPermission( - Uri uri, int modeFlags, String message) { - mBase.enforceCallingOrSelfUriPermission(uri, modeFlags, message); - } - - @Override - public void enforceUriPermission( - Uri uri, String readPermission, String writePermission, - int pid, int uid, int modeFlags, String message) { - mBase.enforceUriPermission( - uri, readPermission, writePermission, pid, uid, modeFlags, - message); - } - - @Override - public Context createPackageContext(String packageName, int flags) - throws PackageManager.NameNotFoundException { - return mBase.createPackageContext(packageName, flags); - } -} diff --git a/core/java/android/content/DefaultDataHandler.java b/core/java/android/content/DefaultDataHandler.java deleted file mode 100644 index 863c9f6..0000000 --- a/core/java/android/content/DefaultDataHandler.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2008 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.net.Uri; -import android.util.Xml; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Stack; - -/** - * Inserts default data from InputStream, should be in XML format. - * If the provider syncs data to the server, the imported data will be synced to the server. - * <p>Samples:</p> - * <br/> - * Insert one row: - * <pre> - * <row uri="content://contacts/people"> - * <Col column = "name" value = "foo feebe "/> - * <Col column = "addr" value = "Tx"/> - * </row></pre> - * <br/> - * Delete, it must be in order of uri, select, and arg: - * <pre> - * <del uri="content://contacts/people" select="name=? and addr=?" - * arg1 = "foo feebe" arg2 ="Tx"/></pre> - * <br/> - * Use first row's uri to insert into another table, - * content://contacts/people/1/phones: - * <pre> - * <row uri="content://contacts/people"> - * <col column = "name" value = "foo feebe"/> - * <col column = "addr" value = "Tx"/> - * <row postfix="phones"> - * <col column="number" value="512-514-6535"/> - * </row> - * <row postfix="phones"> - * <col column="cell" value="512-514-6535"/> - * </row> - * </row></pre> - * <br/> - * Insert multiple rows in to same table and same attributes: - * <pre> - * <row uri="content://contacts/people" > - * <row> - * <col column= "name" value = "foo feebe"/> - * <col column= "addr" value = "Tx"/> - * </row> - * <row> - * </row> - * </row></pre> - * - * @hide - */ -public class DefaultDataHandler implements ContentInsertHandler { - private final static String ROW = "row"; - private final static String COL = "col"; - private final static String URI_STR = "uri"; - private final static String POSTFIX = "postfix"; - private final static String DEL = "del"; - private final static String SELECT = "select"; - private final static String ARG = "arg"; - - private Stack<Uri> mUris = new Stack<Uri>(); - private ContentValues mValues; - private ContentResolver mContentResolver; - - public void insert(ContentResolver contentResolver, InputStream in) - throws IOException, SAXException { - mContentResolver = contentResolver; - Xml.parse(in, Xml.Encoding.UTF_8, this); - } - - public void insert(ContentResolver contentResolver, String in) - throws SAXException { - mContentResolver = contentResolver; - Xml.parse(in, this); - } - - private void parseRow(Attributes atts) throws SAXException { - String uriStr = atts.getValue(URI_STR); - Uri uri; - if (uriStr != null) { - // case 1 - uri = Uri.parse(uriStr); - if (uri == null) { - throw new SAXException("attribute " + - atts.getValue(URI_STR) + " parsing failure"); - } - - } else if (mUris.size() > 0){ - // case 2 - String postfix = atts.getValue(POSTFIX); - if (postfix != null) { - uri = Uri.withAppendedPath(mUris.lastElement(), - postfix); - } else { - uri = mUris.lastElement(); - } - } else { - throw new SAXException("attribute parsing failure"); - } - - mUris.push(uri); - - } - - private Uri insertRow() { - Uri u = mContentResolver.insert(mUris.lastElement(), mValues); - mValues = null; - return u; - } - - public void startElement(String uri, String localName, String name, - Attributes atts) throws SAXException { - if (ROW.equals(localName)) { - if (mValues != null) { - // case 2, <Col> before <Row> insert last uri - if (mUris.empty()) { - throw new SAXException("uri is empty"); - } - Uri nextUri = insertRow(); - if (nextUri == null) { - throw new SAXException("insert to uri " + - mUris.lastElement().toString() + " failure"); - } else { - // make sure the stack lastElement save uri for more than one row - mUris.pop(); - mUris.push(nextUri); - parseRow(atts); - } - } else { - int attrLen = atts.getLength(); - if (attrLen == 0) { - // case 3, share same uri as last level - mUris.push(mUris.lastElement()); - } else { - parseRow(atts); - } - } - } else if (COL.equals(localName)) { - int attrLen = atts.getLength(); - if (attrLen != 2) { - throw new SAXException("illegal attributes number " + attrLen); - } - String key = atts.getValue(0); - String value = atts.getValue(1); - if (key != null && key.length() > 0 && value != null && value.length() > 0) { - if (mValues == null) { - mValues = new ContentValues(); - } - mValues.put(key, value); - } else { - throw new SAXException("illegal attributes value"); - } - } else if (DEL.equals(localName)){ - Uri u = Uri.parse(atts.getValue(URI_STR)); - if (u == null) { - throw new SAXException("attribute " + - atts.getValue(URI_STR) + " parsing failure"); - } - int attrLen = atts.getLength() - 2; - if (attrLen > 0) { - String[] selectionArgs = new String[attrLen]; - for (int i = 0; i < attrLen; i++) { - selectionArgs[i] = atts.getValue(i+2); - } - mContentResolver.delete(u, atts.getValue(1), selectionArgs); - } else if (attrLen == 0){ - mContentResolver.delete(u, atts.getValue(1), null); - } else { - mContentResolver.delete(u, null, null); - } - - } else { - throw new SAXException("unknown element: " + localName); - } - } - - public void endElement(String uri, String localName, String name) - throws SAXException { - if (ROW.equals(localName)) { - if (mUris.empty()) { - throw new SAXException("uri mismatch"); - } - if (mValues != null) { - insertRow(); - } - mUris.pop(); - } - } - - - public void characters(char[] ch, int start, int length) - throws SAXException { - // TODO Auto-generated method stub - - } - - public void endDocument() throws SAXException { - // TODO Auto-generated method stub - - } - - public void endPrefixMapping(String prefix) throws SAXException { - // TODO Auto-generated method stub - - } - - public void ignorableWhitespace(char[] ch, int start, int length) - throws SAXException { - // TODO Auto-generated method stub - - } - - public void processingInstruction(String target, String data) - throws SAXException { - // TODO Auto-generated method stub - - } - - public void setDocumentLocator(Locator locator) { - // TODO Auto-generated method stub - - } - - public void skippedEntity(String name) throws SAXException { - // TODO Auto-generated method stub - - } - - public void startDocument() throws SAXException { - // TODO Auto-generated method stub - - } - - public void startPrefixMapping(String prefix, String uri) - throws SAXException { - // TODO Auto-generated method stub - - } - -} diff --git a/core/java/android/content/DialogInterface.java b/core/java/android/content/DialogInterface.java deleted file mode 100644 index 4afa294..0000000 --- a/core/java/android/content/DialogInterface.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2006 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.view.KeyEvent; - -/** - * - */ -public interface DialogInterface { - /** - * The identifier for the positive button. - */ - public static final int BUTTON_POSITIVE = -1; - - /** - * The identifier for the negative button. - */ - public static final int BUTTON_NEGATIVE = -2; - - /** - * The identifier for the neutral button. - */ - public static final int BUTTON_NEUTRAL = -3; - - /** - * @deprecated Use {@link #BUTTON_POSITIVE} - */ - @Deprecated - public static final int BUTTON1 = BUTTON_POSITIVE; - - /** - * @deprecated Use {@link #BUTTON_NEGATIVE} - */ - @Deprecated - public static final int BUTTON2 = BUTTON_NEGATIVE; - - /** - * @deprecated Use {@link #BUTTON_NEUTRAL} - */ - @Deprecated - public static final int BUTTON3 = BUTTON_NEUTRAL; - - public void cancel(); - - public void dismiss(); - - /** - * Interface used to allow the creator of a dialog to run some code when the - * dialog is canceled. - * <p> - * This will only be called when the dialog is canceled, if the creator - * needs to know when it is dismissed in general, use - * {@link DialogInterface.OnDismissListener}. - */ - interface OnCancelListener { - /** - * This method will be invoked when the dialog is canceled. - * - * @param dialog The dialog that was canceled will be passed into the - * method. - */ - public void onCancel(DialogInterface dialog); - } - - /** - * Interface used to allow the creator of a dialog to run some code when the - * dialog is dismissed. - */ - interface OnDismissListener { - /** - * This method will be invoked when the dialog is dismissed. - * - * @param dialog The dialog that was dismissed will be passed into the - * method. - */ - public void onDismiss(DialogInterface dialog); - } - - /** - * Interface used to allow the creator of a dialog to run some code when an - * item on the dialog is clicked.. - */ - interface OnClickListener { - /** - * This method will be invoked when a button in the dialog is clicked. - * - * @param dialog The dialog that received the click. - * @param which The button that was clicked (e.g. - * {@link DialogInterface#BUTTON1}) or the position - * of the item clicked. - */ - /* TODO: Change to use BUTTON_POSITIVE after API council */ - public void onClick(DialogInterface dialog, int which); - } - - /** - * Interface used to allow the creator of a dialog to run some code when an - * item in a multi-choice dialog is clicked. - */ - interface OnMultiChoiceClickListener { - /** - * This method will be invoked when an item in the dialog is clicked. - * - * @param dialog The dialog where the selection was made. - * @param which The position of the item in the list that was clicked. - * @param isChecked True if the click checked the item, else false. - */ - public void onClick(DialogInterface dialog, int which, boolean isChecked); - } - - /** - * Interface definition for a callback to be invoked when a key event is - * dispatched to this dialog. The callback will be invoked before the key - * event is given to the dialog. - */ - interface OnKeyListener { - /** - * Called when a key is dispatched to a dialog. This allows listeners to - * get a chance to respond before the dialog. - * - * @param dialog The dialog the key has been dispatched to. - * @param keyCode The code for the physical key that was pressed - * @param event The KeyEvent object containing full information about - * the event. - * @return True if the listener has consumed the event, false otherwise. - */ - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event); - } -} diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java deleted file mode 100644 index a6ef46f..0000000 --- a/core/java/android/content/IContentProvider.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2006 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.CursorWindow; -import android.database.IBulkCursor; -import android.database.IContentObserver; -import android.net.Uri; -import android.os.RemoteException; -import android.os.IBinder; -import android.os.IInterface; -import android.os.ParcelFileDescriptor; - -import java.io.FileNotFoundException; - -/** - * The ipc interface to talk to a content provider. - * @hide - */ -public interface IContentProvider extends IInterface { - /** - * @hide - hide this because return type IBulkCursor and parameter - * IContentObserver are system private classes. - */ - public IBulkCursor bulkQuery(Uri url, String[] projection, - String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, - CursorWindow window) throws RemoteException; - public Cursor query(Uri url, String[] projection, String selection, - String[] selectionArgs, String sortOrder) throws RemoteException; - public String getType(Uri url) throws RemoteException; - public Uri insert(Uri url, ContentValues initialValues) - throws RemoteException; - public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException; - public int delete(Uri url, String selection, String[] selectionArgs) - throws RemoteException; - public int update(Uri url, ContentValues values, String selection, - String[] selectionArgs) throws RemoteException; - public ParcelFileDescriptor openFile(Uri url, String mode) - throws RemoteException, FileNotFoundException; - public ISyncAdapter getSyncAdapter() throws RemoteException; - - /* IPC constants */ - static final String descriptor = "android.content.IContentProvider"; - - static final int QUERY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; - static final int GET_TYPE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; - static final int INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2; - static final int DELETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 3; - static final int UPDATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 9; - static final int GET_SYNC_ADAPTER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 10; - static final int BULK_INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 12; - static final int OPEN_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 13; -} diff --git a/core/java/android/content/IContentService.java b/core/java/android/content/IContentService.java deleted file mode 100644 index a3047da..0000000 --- a/core/java/android/content/IContentService.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2006 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.IContentObserver; -import android.net.Uri; -import android.os.RemoteException; -import android.os.IBinder; -import android.os.IInterface; -import android.os.Bundle; - -/** - * {@hide} - */ -public interface IContentService extends IInterface -{ - public void registerContentObserver(Uri uri, boolean notifyForDescendentsn, - IContentObserver observer) throws RemoteException; - public void unregisterContentObserver(IContentObserver observer) throws RemoteException; - - public void notifyChange(Uri uri, IContentObserver observer, - boolean observerWantsSelfNotifications, boolean syncToNetwork) - throws RemoteException; - - public void startSync(Uri url, Bundle extras) throws RemoteException; - public void cancelSync(Uri uri) throws RemoteException; - - static final String SERVICE_NAME = "content"; - - /* IPC constants */ - static final String descriptor = "android.content.IContentService"; - - static final int REGISTER_CONTENT_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; - static final int UNREGISTER_CHANGE_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2; - static final int NOTIFY_CHANGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 3; - static final int START_SYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 4; - static final int CANCEL_SYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 5; -} - diff --git a/core/java/android/content/ISyncAdapter.aidl b/core/java/android/content/ISyncAdapter.aidl deleted file mode 100644 index 671188c..0000000 --- a/core/java/android/content/ISyncAdapter.aidl +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008 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.os.Bundle; -import android.content.ISyncContext; - -/** - * Interface used to control the sync activity on a SyncAdapter - * @hide - */ -oneway interface ISyncAdapter { - /** - * Initiate a sync for this account. SyncAdapter-specific parameters may - * be specified in extras, which is guaranteed to not be null. - * - * @param syncContext the ISyncContext used to indicate the progress of the sync. When - * the sync is finished (successfully or not) ISyncContext.onFinished() must be called. - * @param account the account that should be synced - * @param extras SyncAdapter-specific parameters - */ - void startSync(ISyncContext syncContext, String account, in Bundle extras); - - /** - * Cancel the most recently initiated sync. Due to race conditions, this may arrive - * after the ISyncContext.onFinished() for that sync was called. - */ - void cancelSync(); -} diff --git a/core/java/android/content/ISyncContext.aidl b/core/java/android/content/ISyncContext.aidl deleted file mode 100644 index 6d18a1c..0000000 --- a/core/java/android/content/ISyncContext.aidl +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008 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.content.SyncResult; - -/** - * Interface used by the SyncAdapter to indicate its progress. - * @hide - */ -interface ISyncContext { - /** - * Call to indicate that the SyncAdapter is making progress. E.g., if this SyncAdapter - * downloads or sends records to/from the server, this may be called after each record - * is downloaded or uploaded. - */ - void sendHeartbeat(); - - /** - * Signal that the corresponding sync session is completed. - * @param result information about this sync session - */ - void onFinished(in SyncResult result); -} diff --git a/core/java/android/content/Intent.aidl b/core/java/android/content/Intent.aidl deleted file mode 100644 index 568986b..0000000 --- a/core/java/android/content/Intent.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/content/Intent.aidl -** -** Copyright 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; - -parcelable Intent; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java deleted file mode 100644 index c1c3b49..0000000 --- a/core/java/android/content/Intent.java +++ /dev/null @@ -1,4522 +0,0 @@ -/* - * Copyright (C) 2006 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 org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.Log; -import com.android.internal.util.XmlUtils; - -import java.io.IOException; -import java.io.Serializable; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -/** - * An intent is an abstract description of an operation to be performed. It - * can be used with {@link Context#startActivity(Intent) startActivity} to - * launch an {@link android.app.Activity}, - * {@link android.content.Context#sendBroadcast(Intent) broadcastIntent} to - * send it to any interested {@link BroadcastReceiver BroadcastReceiver} components, - * and {@link android.content.Context#startService} or - * {@link android.content.Context#bindService} to communicate with a - * background {@link android.app.Service}. - * - * <p>An Intent provides a facility for performing late runtime binding between - * the code in different applications. Its most significant use is in the - * launching of activities, where it can be thought of as the glue between - * activities. It is - * basically a passive data structure holding an abstract description of an - * action to be performed. The primary pieces of information in an intent - * are:</p> - * - * <ul> - * <li> <p><b>action</b> -- The general action to be performed, such as - * {@link #ACTION_VIEW}, {@link #ACTION_EDIT}, {@link #ACTION_MAIN}, - * etc.</p> - * </li> - * <li> <p><b>data</b> -- The data to operate on, such as a person record - * in the contacts database, expressed as a {@link android.net.Uri}.</p> - * </li> - * </ul> - * - * - * <p>Some examples of action/data pairs are:</p> - * - * <ul> - * <li> <p><b>{@link #ACTION_VIEW} <i>content://contacts/1</i></b> -- Display - * information about the person whose identifier is "1".</p> - * </li> - * <li> <p><b>{@link #ACTION_DIAL} <i>content://contacts/1</i></b> -- Display - * the phone dialer with the person filled in.</p> - * </li> - * <li> <p><b>{@link #ACTION_VIEW} <i>tel:123</i></b> -- Display - * the phone dialer with the given number filled in. Note how the - * VIEW action does what what is considered the most reasonable thing for - * a particular URI.</p> - * </li> - * <li> <p><b>{@link #ACTION_DIAL} <i>tel:123</i></b> -- Display - * the phone dialer with the given number filled in.</p> - * </li> - * <li> <p><b>{@link #ACTION_EDIT} <i>content://contacts/1</i></b> -- Edit - * information about the person whose identifier is "1".</p> - * </li> - * <li> <p><b>{@link #ACTION_VIEW} <i>content://contacts/</i></b> -- Display - * a list of people, which the user can browse through. This example is a - * typical top-level entry into the Contacts application, showing you the - * list of people. Selecting a particular person to view would result in a - * new intent { <b>{@link #ACTION_VIEW} <i>content://contacts/N</i></b> } - * being used to start an activity to display that person.</p> - * </li> - * </ul> - * - * <p>In addition to these primary attributes, there are a number of secondary - * attributes that you can also include with an intent:</p> - * - * <ul> - * <li> <p><b>category</b> -- Gives additional information about the action - * to execute. For example, {@link #CATEGORY_LAUNCHER} means it should - * appear in the Launcher as a top-level application, while - * {@link #CATEGORY_ALTERNATIVE} means it should be included in a list - * of alternative actions the user can perform on a piece of data.</p> - * <li> <p><b>type</b> -- Specifies an explicit type (a MIME type) of the - * intent data. Normally the type is inferred from the data itself. - * By setting this attribute, you disable that evaluation and force - * an explicit type.</p> - * <li> <p><b>component</b> -- Specifies an explicit name of a component - * class to use for the intent. Normally this is determined by looking - * at the other information in the intent (the action, data/type, and - * categories) and matching that with a component that can handle it. - * If this attribute is set then none of the evaluation is performed, - * and this component is used exactly as is. By specifying this attribute, - * all of the other Intent attributes become optional.</p> - * <li> <p><b>extras</b> -- This is a {@link Bundle} of any additional information. - * This can be used to provide extended information to the component. - * For example, if we have a action to send an e-mail message, we could - * also include extra pieces of data here to supply a subject, body, - * etc.</p> - * </ul> - * - * <p>Here are some examples of other operations you can specify as intents - * using these additional parameters:</p> - * - * <ul> - * <li> <p><b>{@link #ACTION_MAIN} with category {@link #CATEGORY_HOME}</b> -- - * Launch the home screen.</p> - * </li> - * <li> <p><b>{@link #ACTION_GET_CONTENT} with MIME type - * <i>{@link android.provider.Contacts.Phones#CONTENT_URI - * vnd.android.cursor.item/phone}</i></b> - * -- Display the list of people's phone numbers, allowing the user to - * browse through them and pick one and return it to the parent activity.</p> - * </li> - * <li> <p><b>{@link #ACTION_GET_CONTENT} with MIME type - * <i>*{@literal /}*</i> and category {@link #CATEGORY_OPENABLE}</b> - * -- Display all pickers for data that can be opened with - * {@link ContentResolver#openInputStream(Uri) ContentResolver.openInputStream()}, - * allowing the user to pick one of them and then some data inside of it - * and returning the resulting URI to the caller. This can be used, - * for example, in an e-mail application to allow the user to pick some - * data to include as an attachment.</p> - * </li> - * </ul> - * - * <p>There are a variety of standard Intent action and category constants - * defined in the Intent class, but applications can also define their own. - * These strings use java style scoping, to ensure they are unique -- for - * example, the standard {@link #ACTION_VIEW} is called - * "android.app.action.VIEW".</p> - * - * <p>Put together, the set of actions, data types, categories, and extra data - * defines a language for the system allowing for the expression of phrases - * such as "call john smith's cell". As applications are added to the system, - * they can extend this language by adding new actions, types, and categories, or - * they can modify the behavior of existing phrases by supplying their own - * activities that handle them.</p> - * - * <a name="IntentResolution"></a> - * <h3>Intent Resolution</h3> - * - * <p>There are two primary forms of intents you will use. - * - * <ul> - * <li> <p><b>Explicit Intents</b> have specified a component (via - * {@link #setComponent} or {@link #setClass}), which provides the exact - * class to be run. Often these will not include any other information, - * simply being a way for an application to launch various internal - * activities it has as the user interacts with the application. - * - * <li> <p><b>Implicit Intents</b> have not specified a component; - * instead, they must include enough information for the system to - * determine which of the available components is best to run for that - * intent. - * </ul> - * - * <p>When using implicit intents, given such an arbitrary intent we need to - * know what to do with it. This is handled by the process of <em>Intent - * resolution</em>, which maps an Intent to an {@link android.app.Activity}, - * {@link BroadcastReceiver}, or {@link android.app.Service} (or sometimes two or - * more activities/receivers) that can handle it.</p> - * - * <p>The intent resolution mechanism basically revolves around matching an - * Intent against all of the <intent-filter> descriptions in the - * installed application packages. (Plus, in the case of broadcasts, any {@link BroadcastReceiver} - * objects explicitly registered with {@link Context#registerReceiver}.) More - * details on this can be found in the documentation on the {@link - * IntentFilter} class.</p> - * - * <p>There are three pieces of information in the Intent that are used for - * resolution: the action, type, and category. Using this information, a query - * is done on the {@link PackageManager} for a component that can handle the - * intent. The appropriate component is determined based on the intent - * information supplied in the <code>AndroidManifest.xml</code> file as - * follows:</p> - * - * <ul> - * <li> <p>The <b>action</b>, if given, must be listed by the component as - * one it handles.</p> - * <li> <p>The <b>type</b> is retrieved from the Intent's data, if not - * already supplied in the Intent. Like the action, if a type is - * included in the intent (either explicitly or implicitly in its - * data), then this must be listed by the component as one it handles.</p> - * <li> For data that is not a <code>content:</code> URI and where no explicit - * type is included in the Intent, instead the <b>scheme</b> of the - * intent data (such as <code>http:</code> or <code>mailto:</code>) is - * considered. Again like the action, if we are matching a scheme it - * must be listed by the component as one it can handle. - * <li> <p>The <b>categories</b>, if supplied, must <em>all</em> be listed - * by the activity as categories it handles. That is, if you include - * the categories {@link #CATEGORY_LAUNCHER} and - * {@link #CATEGORY_ALTERNATIVE}, then you will only resolve to components - * with an intent that lists <em>both</em> of those categories. - * Activities will very often need to support the - * {@link #CATEGORY_DEFAULT} so that they can be found by - * {@link Context#startActivity Context.startActivity()}.</p> - * </ul> - * - * <p>For example, consider the Note Pad sample application that - * allows user to browse through a list of notes data and view details about - * individual items. Text in italics indicate places were you would replace a - * name with one specific to your own package.</p> - * - * <pre> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - * package="<i>com.android.notepad</i>"> - * <application android:icon="@drawable/app_notes" - * android:label="@string/app_name"> - * - * <provider class=".NotePadProvider" - * android:authorities="<i>com.google.provider.NotePad</i>" /> - * - * <activity class=".NotesList" android:label="@string/title_notes_list"> - * <intent-filter> - * <action android:value="android.intent.action.MAIN" /> - * <category android:value="android.intent.category.LAUNCHER" /> - * </intent-filter> - * <intent-filter> - * <action android:value="android.intent.action.VIEW" /> - * <action android:value="android.intent.action.EDIT" /> - * <action android:value="android.intent.action.PICK" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter> - * <intent-filter> - * <action android:value="android.intent.action.GET_CONTENT" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </activity> - * - * <activity class=".NoteEditor" android:label="@string/title_note"> - * <intent-filter android:label="@string/resolve_edit"> - * <action android:value="android.intent.action.VIEW" /> - * <action android:value="android.intent.action.EDIT" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * - * <intent-filter> - * <action android:value="android.intent.action.INSERT" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter> - * - * </activity> - * - * <activity class=".TitleEditor" android:label="@string/title_edit_title" - * android:theme="@android:style/Theme.Dialog"> - * <intent-filter android:label="@string/resolve_title"> - * <action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <category android:value="android.intent.category.ALTERNATIVE" /> - * <category android:value="android.intent.category.SELECTED_ALTERNATIVE" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter> - * </activity> - * - * </application> - * </manifest></pre> - * - * <p>The first activity, - * <code>com.android.notepad.NotesList</code>, serves as our main - * entry into the app. It can do three things as described by its three intent - * templates: - * <ol> - * <li><pre> - * <intent-filter> - * <action android:value="{@link #ACTION_MAIN android.intent.action.MAIN}" /> - * <category android:value="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /> - * </intent-filter></pre> - * <p>This provides a top-level entry into the NotePad application: the standard - * MAIN action is a main entry point (not requiring any other information in - * the Intent), and the LAUNCHER category says that this entry point should be - * listed in the application launcher.</p> - * <li><pre> - * <intent-filter> - * <action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /> - * <action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /> - * <action android:value="{@link #ACTION_PICK android.intent.action.PICK}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter></pre> - * <p>This declares the things that the activity can do on a directory of - * notes. The type being supported is given with the <type> tag, where - * <code>vnd.android.cursor.dir/vnd.google.note</code> is a URI from which - * a Cursor of zero or more items (<code>vnd.android.cursor.dir</code>) can - * be retrieved which holds our note pad data (<code>vnd.google.note</code>). - * The activity allows the user to view or edit the directory of data (via - * the VIEW and EDIT actions), or to pick a particular note and return it - * to the caller (via the PICK action). Note also the DEFAULT category - * supplied here: this is <em>required</em> for the - * {@link Context#startActivity Context.startActivity} method to resolve your - * activity when its component name is not explicitly specified.</p> - * <li><pre> - * <intent-filter> - * <action android:value="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter></pre> - * <p>This filter describes the ability return to the caller a note selected by - * the user without needing to know where it came from. The data type - * <code>vnd.android.cursor.item/vnd.google.note</code> is a URI from which - * a Cursor of exactly one (<code>vnd.android.cursor.item</code>) item can - * be retrieved which contains our note pad data (<code>vnd.google.note</code>). - * The GET_CONTENT action is similar to the PICK action, where the activity - * will return to its caller a piece of data selected by the user. Here, - * however, the caller specifies the type of data they desire instead of - * the type of data the user will be picking from.</p> - * </ol> - * - * <p>Given these capabilities, the following intents will resolve to the - * NotesList activity:</p> - * - * <ul> - * <li> <p><b>{ action=android.app.action.MAIN }</b> matches all of the - * activities that can be used as top-level entry points into an - * application.</p> - * <li> <p><b>{ action=android.app.action.MAIN, - * category=android.app.category.LAUNCHER }</b> is the actual intent - * used by the Launcher to populate its top-level list.</p> - * <li> <p><b>{ action=android.app.action.VIEW - * data=content://com.google.provider.NotePad/notes }</b> - * displays a list of all the notes under - * "content://com.google.provider.NotePad/notes", which - * the user can browse through and see the details on.</p> - * <li> <p><b>{ action=android.app.action.PICK - * data=content://com.google.provider.NotePad/notes }</b> - * provides a list of the notes under - * "content://com.google.provider.NotePad/notes", from which - * the user can pick a note whose data URL is returned back to the caller.</p> - * <li> <p><b>{ action=android.app.action.GET_CONTENT - * type=vnd.android.cursor.item/vnd.google.note }</b> - * is similar to the pick action, but allows the caller to specify the - * kind of data they want back so that the system can find the appropriate - * activity to pick something of that data type.</p> - * </ul> - * - * <p>The second activity, - * <code>com.android.notepad.NoteEditor</code>, shows the user a single - * note entry and allows them to edit it. It can do two things as described - * by its two intent templates: - * <ol> - * <li><pre> - * <intent-filter android:label="@string/resolve_edit"> - * <action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /> - * <action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter></pre> - * <p>The first, primary, purpose of this activity is to let the user interact - * with a single note, as decribed by the MIME type - * <code>vnd.android.cursor.item/vnd.google.note</code>. The activity can - * either VIEW a note or allow the user to EDIT it. Again we support the - * DEFAULT category to allow the activity to be launched without explicitly - * specifying its component.</p> - * <li><pre> - * <intent-filter> - * <action android:value="{@link #ACTION_INSERT android.intent.action.INSERT}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> - * </intent-filter></pre> - * <p>The secondary use of this activity is to insert a new note entry into - * an existing directory of notes. This is used when the user creates a new - * note: the INSERT action is executed on the directory of notes, causing - * this activity to run and have the user create the new note data which - * it then adds to the content provider.</p> - * </ol> - * - * <p>Given these capabilities, the following intents will resolve to the - * NoteEditor activity:</p> - * - * <ul> - * <li> <p><b>{ action=android.app.action.VIEW - * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b> - * shows the user the content of note <var>{ID}</var>.</p> - * <li> <p><b>{ action=android.app.action.EDIT - * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b> - * allows the user to edit the content of note <var>{ID}</var>.</p> - * <li> <p><b>{ action=android.app.action.INSERT - * data=content://com.google.provider.NotePad/notes }</b> - * creates a new, empty note in the notes list at - * "content://com.google.provider.NotePad/notes" - * and allows the user to edit it. If they keep their changes, the URI - * of the newly created note is returned to the caller.</p> - * </ul> - * - * <p>The last activity, - * <code>com.android.notepad.TitleEditor</code>, allows the user to - * edit the title of a note. This could be implemented as a class that the - * application directly invokes (by explicitly setting its component in - * the Intent), but here we show a way you can publish alternative - * operations on existing data:</p> - * - * <pre> - * <intent-filter android:label="@string/resolve_title"> - * <action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <category android:value="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /> - * <category android:value="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> - * </intent-filter></pre> - * - * <p>In the single intent template here, we - * have created our own private action called - * <code>com.android.notepad.action.EDIT_TITLE</code> which means to - * edit the title of a note. It must be invoked on a specific note - * (data type <code>vnd.android.cursor.item/vnd.google.note</code>) like the previous - * view and edit actions, but here displays and edits the title contained - * in the note data. - * - * <p>In addition to supporting the default category as usual, our title editor - * also supports two other standard categories: ALTERNATIVE and - * SELECTED_ALTERNATIVE. Implementing - * these categories allows others to find the special action it provides - * without directly knowing about it, through the - * {@link android.content.pm.PackageManager#queryIntentActivityOptions} method, or - * more often to build dynamic menu items with - * {@link android.view.Menu#addIntentOptions}. Note that in the intent - * template here was also supply an explicit name for the template - * (via <code>android:label="@string/resolve_title"</code>) to better control - * what the user sees when presented with this activity as an alternative - * action to the data they are viewing. - * - * <p>Given these capabilities, the following intent will resolve to the - * TitleEditor activity:</p> - * - * <ul> - * <li> <p><b>{ action=com.android.notepad.action.EDIT_TITLE - * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b> - * displays and allows the user to edit the title associated - * with note <var>{ID}</var>.</p> - * </ul> - * - * <h3>Standard Activity Actions</h3> - * - * <p>These are the current standard actions that Intent defines for launching - * activities (usually through {@link Context#startActivity}. The most - * important, and by far most frequently used, are {@link #ACTION_MAIN} and - * {@link #ACTION_EDIT}. - * - * <ul> - * <li> {@link #ACTION_MAIN} - * <li> {@link #ACTION_VIEW} - * <li> {@link #ACTION_ATTACH_DATA} - * <li> {@link #ACTION_EDIT} - * <li> {@link #ACTION_PICK} - * <li> {@link #ACTION_CHOOSER} - * <li> {@link #ACTION_GET_CONTENT} - * <li> {@link #ACTION_DIAL} - * <li> {@link #ACTION_CALL} - * <li> {@link #ACTION_SEND} - * <li> {@link #ACTION_SENDTO} - * <li> {@link #ACTION_ANSWER} - * <li> {@link #ACTION_INSERT} - * <li> {@link #ACTION_DELETE} - * <li> {@link #ACTION_RUN} - * <li> {@link #ACTION_SYNC} - * <li> {@link #ACTION_PICK_ACTIVITY} - * <li> {@link #ACTION_SEARCH} - * <li> {@link #ACTION_WEB_SEARCH} - * <li> {@link #ACTION_FACTORY_TEST} - * </ul> - * - * <h3>Standard Broadcast Actions</h3> - * - * <p>These are the current standard actions that Intent defines for receiving - * broadcasts (usually through {@link Context#registerReceiver} or a - * <receiver> tag in a manifest). - * - * <ul> - * <li> {@link #ACTION_TIME_TICK} - * <li> {@link #ACTION_TIME_CHANGED} - * <li> {@link #ACTION_TIMEZONE_CHANGED} - * <li> {@link #ACTION_BOOT_COMPLETED} - * <li> {@link #ACTION_PACKAGE_ADDED} - * <li> {@link #ACTION_PACKAGE_CHANGED} - * <li> {@link #ACTION_PACKAGE_REMOVED} - * <li> {@link #ACTION_PACKAGE_RESTARTED} - * <li> {@link #ACTION_PACKAGE_DATA_CLEARED} - * <li> {@link #ACTION_UID_REMOVED} - * <li> {@link #ACTION_BATTERY_CHANGED} - * </ul> - * - * <h3>Standard Categories</h3> - * - * <p>These are the current standard categories that can be used to further - * clarify an Intent via {@link #addCategory}. - * - * <ul> - * <li> {@link #CATEGORY_DEFAULT} - * <li> {@link #CATEGORY_BROWSABLE} - * <li> {@link #CATEGORY_TAB} - * <li> {@link #CATEGORY_ALTERNATIVE} - * <li> {@link #CATEGORY_SELECTED_ALTERNATIVE} - * <li> {@link #CATEGORY_LAUNCHER} - * <li> {@link #CATEGORY_HOME} - * <li> {@link #CATEGORY_PREFERENCE} - * <li> {@link #CATEGORY_GADGET} - * <li> {@link #CATEGORY_TEST} - * </ul> - * - * <h3>Standard Extra Data</h3> - * - * <p>These are the current standard fields that can be used as extra data via - * {@link #putExtra}. - * - * <ul> - * <li> {@link #EXTRA_TEMPLATE} - * <li> {@link #EXTRA_INTENT} - * <li> {@link #EXTRA_STREAM} - * <li> {@link #EXTRA_TEXT} - * </ul> - * - * <h3>Flags</h3> - * - * <p>These are the possible flags that can be used in the Intent via - * {@link #setFlags} and {@link #addFlags}. See {@link #setFlags} for a list - * of all possible flags. - */ -public class Intent implements Parcelable { - // --------------------------------------------------------------------- - // --------------------------------------------------------------------- - // Standard intent activity actions (see action variable). - - /** - * Activity Action: Start as a main entry point, does not expect to - * receive data. - * <p>Input: nothing - * <p>Output: nothing - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_MAIN = "android.intent.action.MAIN"; - - /** - * Activity Action: Display the data to the user. This is the most common - * action performed on data -- it is the generic action you can use on - * a piece of data to get the most reasonable thing to occur. For example, - * when used on a contacts entry it will view the entry; when used on a - * mailto: URI it will bring up a compose window filled with the information - * supplied by the URI; when used with a tel: URI it will invoke the - * dialer. - * <p>Input: {@link #getData} is URI from which to retrieve data. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_VIEW = "android.intent.action.VIEW"; - - /** - * A synonym for {@link #ACTION_VIEW}, the "standard" action that is - * performed on a piece of data. - */ - public static final String ACTION_DEFAULT = ACTION_VIEW; - - /** - * Used to indicate that some piece of data should be attached to some other - * place. For example, image data could be attached to a contact. It is up - * to the recipient to decide where the data should be attached; the intent - * does not specify the ultimate destination. - * <p>Input: {@link #getData} is URI of data to be attached. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA"; - - /** - * Activity Action: Provide explicit editable access to the given data. - * <p>Input: {@link #getData} is URI of data to be edited. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_EDIT = "android.intent.action.EDIT"; - - /** - * Activity Action: Pick an existing item, or insert a new item, and then edit it. - * <p>Input: {@link #getType} is the desired MIME type of the item to create or edit. - * The extras can contain type specific data to pass through to the editing/creating - * activity. - * <p>Output: The URI of the item that was picked. This must be a content: - * URI so that any receiver can access it. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT"; - - /** - * Activity Action: Pick an item from the data, returning what was selected. - * <p>Input: {@link #getData} is URI containing a directory of data - * (vnd.android.cursor.dir/*) from which to pick an item. - * <p>Output: The URI of the item that was picked. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_PICK = "android.intent.action.PICK"; - - /** - * Activity Action: Creates a shortcut. - * <p>Input: Nothing.</p> - * <p>Output: An Intent representing the shortcut. The intent must contain three - * extras: SHORTCUT_INTENT (value: Intent), SHORTCUT_NAME (value: String), - * and SHORTCUT_ICON (value: Bitmap) or SHORTCUT_ICON_RESOURCE - * (value: ShortcutIconResource).</p> - * - * @see #EXTRA_SHORTCUT_INTENT - * @see #EXTRA_SHORTCUT_NAME - * @see #EXTRA_SHORTCUT_ICON - * @see #EXTRA_SHORTCUT_ICON_RESOURCE - * @see android.content.Intent.ShortcutIconResource - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT"; - - /** - * The name of the extra used to define the Intent of a shortcut. - * - * @see #ACTION_CREATE_SHORTCUT - */ - public static final String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT"; - /** - * The name of the extra used to define the name of a shortcut. - * - * @see #ACTION_CREATE_SHORTCUT - */ - public static final String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME"; - /** - * The name of the extra used to define the icon, as a Bitmap, of a shortcut. - * - * @see #ACTION_CREATE_SHORTCUT - */ - public static final String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON"; - /** - * The name of the extra used to define the icon, as a ShortcutIconResource, of a shortcut. - * - * @see #ACTION_CREATE_SHORTCUT - * @see android.content.Intent.ShortcutIconResource - */ - public static final String EXTRA_SHORTCUT_ICON_RESOURCE = - "android.intent.extra.shortcut.ICON_RESOURCE"; - - /** - * Represents a shortcut/live folder icon resource. - * - * @see Intent#ACTION_CREATE_SHORTCUT - * @see Intent#EXTRA_SHORTCUT_ICON_RESOURCE - * @see android.provider.LiveFolders#ACTION_CREATE_LIVE_FOLDER - * @see android.provider.LiveFolders#EXTRA_LIVE_FOLDER_ICON - */ - public static class ShortcutIconResource implements Parcelable { - /** - * The package name of the application containing the icon. - */ - public String packageName; - - /** - * The resource name of the icon, including package, name and type. - */ - public String resourceName; - - /** - * Creates a new ShortcutIconResource for the specified context and resource - * identifier. - * - * @param context The context of the application. - * @param resourceId The resource idenfitier for the icon. - * @return A new ShortcutIconResource with the specified's context package name - * and icon resource idenfitier. - */ - public static ShortcutIconResource fromContext(Context context, int resourceId) { - ShortcutIconResource icon = new ShortcutIconResource(); - icon.packageName = context.getPackageName(); - icon.resourceName = context.getResources().getResourceName(resourceId); - return icon; - } - - /** - * Used to read a ShortcutIconResource from a Parcel. - */ - public static final Parcelable.Creator<ShortcutIconResource> CREATOR = - new Parcelable.Creator<ShortcutIconResource>() { - - public ShortcutIconResource createFromParcel(Parcel source) { - ShortcutIconResource icon = new ShortcutIconResource(); - icon.packageName = source.readString(); - icon.resourceName = source.readString(); - return icon; - } - - public ShortcutIconResource[] newArray(int size) { - return new ShortcutIconResource[size]; - } - }; - - /** - * No special parcel contents. - */ - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(packageName); - dest.writeString(resourceName); - } - - @Override - public String toString() { - return resourceName; - } - } - - /** - * Activity Action: Display an activity chooser, allowing the user to pick - * what they want to before proceeding. This can be used as an alternative - * to the standard activity picker that is displayed by the system when - * you try to start an activity with multiple possible matches, with these - * differences in behavior: - * <ul> - * <li>You can specify the title that will appear in the activity chooser. - * <li>The user does not have the option to make one of the matching - * activities a preferred activity, and all possible activities will - * always be shown even if one of them is currently marked as the - * preferred activity. - * </ul> - * <p> - * This action should be used when the user will naturally expect to - * select an activity in order to proceed. An example if when not to use - * it is when the user clicks on a "mailto:" link. They would naturally - * expect to go directly to their mail app, so startActivity() should be - * called directly: it will - * either launch the current preferred app, or put up a dialog allowing the - * user to pick an app to use and optionally marking that as preferred. - * <p> - * In contrast, if the user is selecting a menu item to send a picture - * they are viewing to someone else, there are many different things they - * may want to do at this point: send it through e-mail, upload it to a - * web service, etc. In this case the CHOOSER action should be used, to - * always present to the user a list of the things they can do, with a - * nice title given by the caller such as "Send this photo with:". - * <p> - * As a convenience, an Intent of this form can be created with the - * {@link #createChooser} function. - * <p>Input: No data should be specified. get*Extra must have - * a {@link #EXTRA_INTENT} field containing the Intent being executed, - * and can optionally have a {@link #EXTRA_TITLE} field containing the - * title text to display in the chooser. - * <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER"; - - /** - * Convenience function for creating a {@link #ACTION_CHOOSER} Intent. - * - * @param target The Intent that the user will be selecting an activity - * to perform. - * @param title Optional title that will be displayed in the chooser. - * @return Return a new Intent object that you can hand to - * {@link Context#startActivity(Intent) Context.startActivity()} and - * related methods. - */ - public static Intent createChooser(Intent target, CharSequence title) { - Intent intent = new Intent(ACTION_CHOOSER); - intent.putExtra(EXTRA_INTENT, target); - if (title != null) { - intent.putExtra(EXTRA_TITLE, title); - } - return intent; - } - /** - * Activity Action: Allow the user to select a particular kind of data and - * return it. This is different than {@link #ACTION_PICK} in that here we - * just say what kind of data is desired, not a URI of existing data from - * which the user can pick. A ACTION_GET_CONTENT could allow the user to - * create the data as it runs (for example taking a picture or recording a - * sound), let them browser over the web and download the desired data, - * etc. - * <p> - * There are two main ways to use this action: if you want an specific kind - * of data, such as a person contact, you set the MIME type to the kind of - * data you want and launch it with {@link Context#startActivity(Intent)}. - * The system will then launch the best application to select that kind - * of data for you. - * <p> - * You may also be interested in any of a set of types of content the user - * can pick. For example, an e-mail application that wants to allow the - * user to add an attachment to an e-mail message can use this action to - * bring up a list of all of the types of content the user can attach. - * <p> - * In this case, you should wrap the GET_CONTENT intent with a chooser - * (through {@link #createChooser}), which will give the proper interface - * for the user to pick how to send your data and allow you to specify - * a prompt indicating what they are doing. You will usually specify a - * broad MIME type (such as image/* or {@literal *}/*), resulting in a - * broad range of content types the user can select from. - * <p> - * When using such a broad GET_CONTENT action, it is often desireable to - * only pick from data that can be represented as a stream. This is - * accomplished by requiring the {@link #CATEGORY_OPENABLE} in the Intent. - * <p> - * Input: {@link #getType} is the desired MIME type to retrieve. Note - * that no URI is supplied in the intent, as there are no constraints on - * where the returned data originally comes from. You may also include the - * {@link #CATEGORY_OPENABLE} if you can only accept data that can be - * opened as a stream. - * <p> - * Output: The URI of the item that was picked. This must be a content: - * URI so that any receiver can access it. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT"; - /** - * Activity Action: Dial a number as specified by the data. This shows a - * UI with the number being dialed, allowing the user to explicitly - * initiate the call. - * <p>Input: If nothing, an empty dialer is started; else {@link #getData} - * is URI of a phone number to be dialed or a tel: URI of an explicit phone - * number. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_DIAL = "android.intent.action.DIAL"; - /** - * Activity Action: Perform a call to someone specified by the data. - * <p>Input: If nothing, an empty dialer is started; else {@link #getData} - * is URI of a phone number to be dialed or a tel: URI of an explicit phone - * number. - * <p>Output: nothing. - * - * <p>Note: there will be restrictions on which applications can initiate a - * call; most applications should use the {@link #ACTION_DIAL}. - * <p>Note: this Intent <strong>cannot</strong> be used to call emergency - * numbers. Applications can <strong>dial</strong> emergency numbers using - * {@link #ACTION_DIAL}, however. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_CALL = "android.intent.action.CALL"; - /** - * Activity Action: Perform a call to an emergency number specified by the - * data. - * <p>Input: {@link #getData} is URI of a phone number to be dialed or a - * tel: URI of an explicit phone number. - * <p>Output: nothing. - * @hide - */ - public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY"; - /** - * Activity action: Perform a call to any number (emergency or not) - * specified by the data. - * <p>Input: {@link #getData} is URI of a phone number to be dialed or a - * tel: URI of an explicit phone number. - * <p>Output: nothing. - * @hide - */ - public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED"; - /** - * Activity Action: Send a message to someone specified by the data. - * <p>Input: {@link #getData} is URI describing the target. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SENDTO = "android.intent.action.SENDTO"; - /** - * Activity Action: Deliver some data to someone else. Who the data is - * being delivered to is not specified; it is up to the receiver of this - * action to ask the user where the data should be sent. - * <p> - * When launching a SEND intent, you should usually wrap it in a chooser - * (through {@link #createChooser}), which will give the proper interface - * for the user to pick how to send your data and allow you to specify - * a prompt indicating what they are doing. - * <p> - * Input: {@link #getType} is the MIME type of the data being sent. - * get*Extra can have either a {@link #EXTRA_TEXT} - * or {@link #EXTRA_STREAM} field, containing the data to be sent. If - * using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it - * should be the MIME type of the data in EXTRA_STREAM. Use {@literal *}/* - * if the MIME type is unknown (this will only allow senders that can - * handle generic data streams). - * <p> - * Optional standard extras, which may be interpreted by some recipients as - * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC}, - * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}. - * <p> - * Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SEND = "android.intent.action.SEND"; - /** - * Activity Action: Handle an incoming phone call. - * <p>Input: nothing. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_ANSWER = "android.intent.action.ANSWER"; - /** - * Activity Action: Insert an empty item into the given container. - * <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*) - * in which to place the data. - * <p>Output: URI of the new data that was created. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_INSERT = "android.intent.action.INSERT"; - /** - * Activity Action: Delete the given data from its container. - * <p>Input: {@link #getData} is URI of data to be deleted. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_DELETE = "android.intent.action.DELETE"; - /** - * Activity Action: Run the data, whatever that means. - * <p>Input: ? (Note: this is currently specific to the test harness.) - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_RUN = "android.intent.action.RUN"; - /** - * Activity Action: Perform a data synchronization. - * <p>Input: ? - * <p>Output: ? - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SYNC = "android.intent.action.SYNC"; - /** - * Activity Action: Pick an activity given an intent, returning the class - * selected. - * <p>Input: get*Extra field {@link #EXTRA_INTENT} is an Intent - * used with {@link PackageManager#queryIntentActivities} to determine the - * set of activities from which to pick. - * <p>Output: Class name of the activity that was selected. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY"; - /** - * Activity Action: Perform a search. - * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)} - * is the text to search for. If empty, simply - * enter your search results Activity with the search UI activated. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SEARCH = "android.intent.action.SEARCH"; - /** - * Activity Action: Perform a web search. - * <p> - * Input: {@link android.app.SearchManager#QUERY - * getStringExtra(SearchManager.QUERY)} is the text to search for. If it is - * a url starts with http or https, the site will be opened. If it is plain - * text, Google search will be applied. - * <p> - * Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH"; - /** - * Activity Action: List all available applications - * <p>Input: Nothing. - * <p>Output: nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_ALL_APPS = "android.intent.action.ALL_APPS"; - /** - * Activity Action: Show settings for choosing wallpaper - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER"; - - /** - * Activity Action: Show activity for reporting a bug. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT"; - - /** - * Activity Action: Main entry point for factory tests. Only used when - * the device is booting in factory test node. The implementing package - * must be installed in the system image. - * <p>Input: nothing - * <p>Output: nothing - */ - public static final String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST"; - - /** - * Activity Action: The user pressed the "call" button to go to the dialer - * or other appropriate UI for placing a call. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON"; - - /** - * Activity Action: Start Voice Command. - * <p>Input: Nothing. - * <p>Output: Nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; - - // --------------------------------------------------------------------- - // --------------------------------------------------------------------- - // Standard intent broadcast actions (see action variable). - - /** - * Broadcast Action: Sent after the screen turns off. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"; - /** - * Broadcast Action: Sent after the screen turns on. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON"; - /** - * Broadcast Action: The current time has changed. Sent every - * minute. You can <em>not</em> receive this through components declared - * in manifests, only by exlicitly registering for it with - * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) - * Context.registerReceiver()}. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK"; - /** - * Broadcast Action: The time was set. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_TIME_CHANGED = "android.intent.action.TIME_SET"; - /** - * Broadcast Action: The date has changed. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED"; - /** - * Broadcast Action: The timezone has changed. The intent will have the following extra values:</p> - * <ul> - * <li><em>time-zone</em> - The java.util.TimeZone.getID() value identifying the new time zone.</li> - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED"; - /** - * Alarm Changed Action: This is broadcast when the AlarmClock - * application's alarm is set or unset. It is used by the - * AlarmClock application and the StatusBar service. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED"; - /** - * Sync State Changed Action: This is broadcast when the sync starts or stops or when one has - * been failing for a long time. It is used by the SyncManager and the StatusBar service. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_SYNC_STATE_CHANGED - = "android.intent.action.SYNC_STATE_CHANGED"; - /** - * Broadcast Action: This is broadcast once, after the system has finished - * booting. It can be used to perform application-specific initialization, - * such as installing alarms. You must hold the - * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission - * in order to receive this broadcast. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; - /** - * Broadcast Action: This is broadcast when a user action should request a - * temporary system dialog to dismiss. Some examples of temporary system - * dialogs are the notification window-shade and the recent tasks dialog. - */ - public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS"; - /** - * Broadcast Action: Trigger the download and eventual installation - * of a package. - * <p>Input: {@link #getData} is the URI of the package file to download. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; - /** - * Broadcast Action: A new application package has been installed on the - * device. The data contains the name of the package. - * <p>My include the following extras: - * <ul> - * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package. - * <li> {@link #EXTRA_REPLACING} is set to true if this is following - * an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package. - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED"; - /** - * Broadcast Action: An existing application package has been removed from - * the device. The data contains the name of the package. The package - * that is being installed does <em>not</em> receive this Intent. - * <ul> - * <li> {@link #EXTRA_UID} containing the integer uid previously assigned - * to the package. - * <li> {@link #EXTRA_DATA_REMOVED} is set to true if the entire - * application -- data and code -- is being removed. - * <li> {@link #EXTRA_REPLACING} is set to true if this will be followed - * by an {@link #ACTION_PACKAGE_ADDED} broadcast for the same package. - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; - /** - * Broadcast Action: An existing application package has been changed (e.g. a component has been - * enabled or disabled. The data contains the name of the package. - * <ul> - * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED"; - /** - * Broadcast Action: The user has restarted a package, and all of its - * processes have been killed. All runtime state - * associated with it (processes, alarms, notifications, etc) should - * be removed. The data contains the name of the package. - * <ul> - * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; - /** - * Broadcast Action: The user has cleared the data of a package. This should - * be preceded by {@link #ACTION_PACKAGE_RESTARTED}, after which all of - * its persistent data is erased and this broadcast sent. The data contains - * the name of the package. - * <ul> - * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED"; - /** - * Broadcast Action: A user ID has been removed from the system. The user - * ID number is stored in the extra data under {@link #EXTRA_UID}. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED"; - /** - * Broadcast Action: The current system wallpaper has changed. See - * {@link Context#getWallpaper} for retrieving the new wallpaper. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED"; - /** - * Broadcast Action: The current device {@link android.content.res.Configuration} - * (orientation, locale, etc) has changed. When such a change happens, the - * UIs (view hierarchy) will need to be rebuilt based on this new - * information; for the most part, applications don't need to worry about - * this, because the system will take care of stopping and restarting the - * application to make sure it sees the new changes. Some system code that - * can not be restarted will need to watch for this action and handle it - * appropriately. - * - * @see android.content.res.Configuration - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED"; - /** - * Broadcast Action: The charging state, or charge level of the battery has - * changed. - * - * <p class="note"> - * You can <em>not</em> receive this through components declared - * in manifests, only by exlicitly registering for it with - * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) - * Context.registerReceiver()}. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED"; - /** - * Broadcast Action: Indicates low battery condition on the device. - * This broadcast corresponds to the "Low battery warning" system dialog. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW"; - /** - * Broadcast Action: Indicates low memory condition on the device - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW"; - /** - * Broadcast Action: Indicates low memory condition on the device no longer exists - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK"; - /** - * Broadcast Action: Indicates low memory condition notification acknowledged by user - * and package management should be started. - * This is triggered by the user from the ACTION_DEVICE_STORAGE_LOW - * notification. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE"; - /** - * Broadcast Action: The device has entered USB Mass Storage mode. - * This is used mainly for the USB Settings panel. - * Apps should listen for ACTION_MEDIA_MOUNTED and ACTION_MEDIA_UNMOUNTED broadcasts to be notified - * when the SD card file system is mounted or unmounted - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED"; - - /** - * Broadcast Action: The device has exited USB Mass Storage mode. - * This is used mainly for the USB Settings panel. - * Apps should listen for ACTION_MEDIA_MOUNTED and ACTION_MEDIA_UNMOUNTED broadcasts to be notified - * when the SD card file system is mounted or unmounted - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED"; - - /** - * Broadcast Action: External media has been removed. - * The path to the mount point for the removed media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_REMOVED = "android.intent.action.MEDIA_REMOVED"; - - /** - * Broadcast Action: External media is present, but not mounted at its mount point. - * The path to the mount point for the removed media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED"; - - /** - * Broadcast Action: External media is present, and being disk-checked - * The path to the mount point for the checking media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING"; - - /** - * Broadcast Action: External media is present, but is using an incompatible fs (or is blank) - * The path to the mount point for the checking media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_NOFS = "android.intent.action.MEDIA_NOFS"; - - /** - * Broadcast Action: External media is present and mounted at its mount point. - * The path to the mount point for the removed media is contained in the Intent.mData field. - * The Intent contains an extra with name "read-only" and Boolean value to indicate if the - * media was mounted read only. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_MOUNTED = "android.intent.action.MEDIA_MOUNTED"; - - /** - * Broadcast Action: External media is unmounted because it is being shared via USB mass storage. - * The path to the mount point for the removed media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_SHARED = "android.intent.action.MEDIA_SHARED"; - - /** - * Broadcast Action: External media was removed from SD card slot, but mount point was not unmounted. - * The path to the mount point for the removed media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL"; - - /** - * Broadcast Action: External media is present but cannot be mounted. - * The path to the mount point for the removed media is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE"; - - /** - * Broadcast Action: User has expressed the desire to remove the external storage media. - * Applications should close all files they have open within the mount point when they receive this intent. - * The path to the mount point for the media to be ejected is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_EJECT = "android.intent.action.MEDIA_EJECT"; - - /** - * Broadcast Action: The media scanner has started scanning a directory. - * The path to the directory being scanned is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_SCANNER_STARTED = "android.intent.action.MEDIA_SCANNER_STARTED"; - - /** - * Broadcast Action: The media scanner has finished scanning a directory. - * The path to the scanned directory is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_SCANNER_FINISHED = "android.intent.action.MEDIA_SCANNER_FINISHED"; - - /** - * Broadcast Action: Request the media scanner to scan a file and add it to the media database. - * The path to the file is contained in the Intent.mData field. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE"; - - /** - * Broadcast Action: The "Media Button" was pressed. Includes a single - * extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that - * caused the broadcast. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON"; - - /** - * Broadcast Action: The "Camera Button" was pressed. Includes a single - * extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that - * caused the broadcast. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON"; - - // *** NOTE: @todo(*) The following really should go into a more domain-specific - // location; they are not general-purpose actions. - - /** - * Broadcast Action: An GTalk connection has been established. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_GTALK_SERVICE_CONNECTED = - "android.intent.action.GTALK_CONNECTED"; - - /** - * Broadcast Action: An GTalk connection has been disconnected. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_GTALK_SERVICE_DISCONNECTED = - "android.intent.action.GTALK_DISCONNECTED"; - - /** - * Broadcast Action: An input method has been changed. - * {@hide pending API Council approval} - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_INPUT_METHOD_CHANGED = - "android.intent.action.INPUT_METHOD_CHANGED"; - - /** - * <p>Broadcast Action: The user has switched the phone into or out of Airplane Mode. One or - * more radios have been turned off or on. The intent will have the following extra value:</p> - * <ul> - * <li><em>state</em> - A boolean value indicating whether Airplane Mode is on. If true, - * then cell radio and possibly other radios such as bluetooth or WiFi may have also been - * turned off</li> - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE"; - - /** - * Broadcast Action: Some content providers have parts of their namespace - * where they publish new events or items that the user may be especially - * interested in. For these things, they may broadcast this action when the - * set of interesting items change. - * - * For example, GmailProvider sends this notification when the set of unread - * mail in the inbox changes. - * - * <p>The data of the intent identifies which part of which provider - * changed. When queried through the content resolver, the data URI will - * return the data set in question. - * - * <p>The intent will have the following extra values: - * <ul> - * <li><em>count</em> - The number of items in the data set. This is the - * same as the number of items in the cursor returned by querying the - * data URI. </li> - * </ul> - * - * This intent will be sent at boot (if the count is non-zero) and when the - * data set changes. It is possible for the data set to change without the - * count changing (for example, if a new unread message arrives in the same - * sync operation in which a message is archived). The phone should still - * ring/vibrate/etc as normal in this case. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_PROVIDER_CHANGED = - "android.intent.action.PROVIDER_CHANGED"; - - /** - * Broadcast Action: Wired Headset plugged in or unplugged. - * - * <p>The intent will have the following extra values: - * <ul> - * <li><em>state</em> - 0 for unplugged, 1 for plugged. </li> - * <li><em>name</em> - Headset type, human readable string </li> - * </ul> - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HEADSET_PLUG = - "android.intent.action.HEADSET_PLUG"; - - /** - * Broadcast Action: An outgoing call is about to be placed. - * - * <p>The Intent will have the following extra value: - * <ul> - * <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> - - * the phone number originally intended to be dialed.</li> - * </ul> - * <p>Once the broadcast is finished, the resultData is used as the actual - * number to call. If <code>null</code>, no call will be placed.</p> - * <p>It is perfectly acceptable for multiple receivers to process the - * outgoing call in turn: for example, a parental control application - * might verify that the user is authorized to place the call at that - * time, then a number-rewriting application might add an area code if - * one was not specified.</p> - * <p>For consistency, any receiver whose purpose is to prohibit phone - * calls should have a priority of 0, to ensure it will see the final - * phone number to be dialed. - * Any receiver whose purpose is to rewrite phone numbers to be called - * should have a positive priority. - * Negative priorities are reserved for the system for this broadcast; - * using them may cause problems.</p> - * <p>Any BroadcastReceiver receiving this Intent <em>must not</em> - * abort the broadcast.</p> - * <p>Emergency calls cannot be intercepted using this mechanism, and - * other calls cannot be modified to call emergency numbers using this - * mechanism. - * <p>You must hold the - * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS} - * permission to receive this Intent.</p> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_NEW_OUTGOING_CALL = - "android.intent.action.NEW_OUTGOING_CALL"; - - /** - * Broadcast Action: Have the device reboot. This is only for use by - * system code. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_REBOOT = - "android.intent.action.REBOOT"; - - // --------------------------------------------------------------------- - // --------------------------------------------------------------------- - // Standard intent categories (see addCategory()). - - /** - * Set if the activity should be an option for the default action - * (center press) to perform on a piece of data. Setting this will - * hide from the user any activities without it set when performing an - * action on some data. Note that this is normal -not- set in the - * Intent when initiating an action -- it is for use in intent filters - * specified in packages. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_DEFAULT = "android.intent.category.DEFAULT"; - /** - * Activities that can be safely invoked from a browser must support this - * category. For example, if the user is viewing a web page or an e-mail - * and clicks on a link in the text, the Intent generated execute that - * link will require the BROWSABLE category, so that only activities - * supporting this category will be considered as possible actions. By - * supporting this category, you are promising that there is nothing - * damaging (without user intervention) that can happen by invoking any - * matching Intent. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE"; - /** - * Set if the activity should be considered as an alternative action to - * the data the user is currently viewing. See also - * {@link #CATEGORY_SELECTED_ALTERNATIVE} for an alternative action that - * applies to the selection in a list of items. - * - * <p>Supporting this category means that you would like your activity to be - * displayed in the set of alternative things the user can do, usually as - * part of the current activity's options menu. You will usually want to - * include a specific label in the <intent-filter> of this action - * describing to the user what it does. - * - * <p>The action of IntentFilter with this category is important in that it - * describes the specific action the target will perform. This generally - * should not be a generic action (such as {@link #ACTION_VIEW}, but rather - * a specific name such as "com.android.camera.action.CROP. Only one - * alternative of any particular action will be shown to the user, so using - * a specific action like this makes sure that your alternative will be - * displayed while also allowing other applications to provide their own - * overrides of that particular action. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE"; - /** - * Set if the activity should be considered as an alternative selection - * action to the data the user has currently selected. This is like - * {@link #CATEGORY_ALTERNATIVE}, but is used in activities showing a list - * of items from which the user can select, giving them alternatives to the - * default action that will be performed on it. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE"; - /** - * Intended to be used as a tab inside of an containing TabActivity. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_TAB = "android.intent.category.TAB"; - /** - * This activity can be embedded inside of another activity that is hosting - * gadgets. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_GADGET = "android.intent.category.GADGET"; - /** - * Should be displayed in the top-level launcher. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"; - /** - * This is the home activity, that is the first activity that is displayed - * when the device boots. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_HOME = "android.intent.category.HOME"; - /** - * This activity is a preference panel. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_PREFERENCE = "android.intent.category.PREFERENCE"; - /** - * This activity is a development preference panel. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_DEVELOPMENT_PREFERENCE = "android.intent.category.DEVELOPMENT_PREFERENCE"; - /** - * Capable of running inside a parent activity container. - * - * <p>Note: being removed in favor of more explicit categories such as - * CATEGORY_GADGET - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_EMBED = "android.intent.category.EMBED"; - /** - * This activity may be exercised by the monkey or other automated test tools. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_MONKEY = "android.intent.category.MONKEY"; - /** - * To be used as a test (not part of the normal user experience). - */ - public static final String CATEGORY_TEST = "android.intent.category.TEST"; - /** - * To be used as a unit test (run through the Test Harness). - */ - public static final String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST"; - /** - * To be used as an sample code example (not part of the normal user - * experience). - */ - public static final String CATEGORY_SAMPLE_CODE = "android.intent.category.SAMPLE_CODE"; - /** - * Used to indicate that a GET_CONTENT intent only wants URIs that can be opened with - * ContentResolver.openInputStream. Openable URIs must support the columns in OpenableColumns - * when queried, though it is allowable for those columns to be blank. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE"; - - /** - * To be used as code under test for framework instrumentation tests. - */ - public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST = - "android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"; - // --------------------------------------------------------------------- - // --------------------------------------------------------------------- - // Standard extra data keys. - - /** - * The initial data to place in a newly created record. Use with - * {@link #ACTION_INSERT}. The data here is a Map containing the same - * fields as would be given to the underlying ContentProvider.insert() - * call. - */ - public static final String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE"; - - /** - * A constant CharSequence that is associated with the Intent, used with - * {@link #ACTION_SEND} to supply the literal data to be sent. Note that - * this may be a styled CharSequence, so you must use - * {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to - * retrieve it. - */ - public static final String EXTRA_TEXT = "android.intent.extra.TEXT"; - - /** - * A content: URI holding a stream of data associated with the Intent, - * used with {@link #ACTION_SEND} to supply the data being sent. - */ - public static final String EXTRA_STREAM = "android.intent.extra.STREAM"; - - /** - * A String[] holding e-mail addresses that should be delivered to. - */ - public static final String EXTRA_EMAIL = "android.intent.extra.EMAIL"; - - /** - * A String[] holding e-mail addresses that should be carbon copied. - */ - public static final String EXTRA_CC = "android.intent.extra.CC"; - - /** - * A String[] holding e-mail addresses that should be blind carbon copied. - */ - public static final String EXTRA_BCC = "android.intent.extra.BCC"; - - /** - * A constant string holding the desired subject line of a message. - */ - public static final String EXTRA_SUBJECT = "android.intent.extra.SUBJECT"; - - /** - * An Intent describing the choices you would like shown with - * {@link #ACTION_PICK_ACTIVITY}. - */ - public static final String EXTRA_INTENT = "android.intent.extra.INTENT"; - - /** - * A CharSequence dialog title to provide to the user when used with a - * {@link #ACTION_CHOOSER}. - */ - public static final String EXTRA_TITLE = "android.intent.extra.TITLE"; - - /** - * A {@link android.view.KeyEvent} object containing the event that - * triggered the creation of the Intent it is in. - */ - public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT"; - - /** - * Used as an boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} or - * {@link android.content.Intent#ACTION_PACKAGE_CHANGED} intents to override the default action - * of restarting the application. - */ - public static final String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP"; - - /** - * A String holding the phone number originally entered in - * {@link android.content.Intent#ACTION_NEW_OUTGOING_CALL}, or the actual - * number to call in a {@link android.content.Intent#ACTION_CALL}. - */ - public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER"; - /** - * Used as an int extra field in {@link android.content.Intent#ACTION_UID_REMOVED} - * intents to supply the uid the package had been assigned. Also an optional - * extra in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} or - * {@link android.content.Intent#ACTION_PACKAGE_CHANGED} for the same - * purpose. - */ - public static final String EXTRA_UID = "android.intent.extra.UID"; - - /** - * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} - * intents to indicate whether this represents a full uninstall (removing - * both the code and its data) or a partial uninstall (leaving its data, - * implying that this is an update). - */ - public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED"; - - /** - * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} - * intents to indicate that this is a replacement of the package, so this - * broadcast will immediately be followed by an add broadcast for a - * different version of the same package. - */ - public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING"; - - /** - * Used as an int extra field in {@link android.app.AlarmManager} intents - * to tell the application being invoked how many pending alarms are being - * delievered with the intent. For one-shot alarms this will always be 1. - * For recurring alarms, this might be greater than 1 if the device was - * asleep or powered off at the time an earlier alarm would have been - * delivered. - */ - public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT"; - - /** - * Used as an int extra field in {@link android.content.Intent#ACTION_VOICE_COMMAND} - * intents to request which audio route the voice command should prefer. - * The value should be a route from {@link android.media.AudioManager}, for - * example ROUTE_BLUETOOTH_SCO. Providing this value is optional. - * {@hide pending API Council approval} - */ - public static final String EXTRA_AUDIO_ROUTE = "android.intent.extra.AUDIO_ROUTE"; - - // --------------------------------------------------------------------- - // --------------------------------------------------------------------- - // Intent flags (see mFlags variable). - - /** - * If set, the recipient of this Intent will be granted permission to - * perform read operations on the Uri in the Intent's data. - */ - public static final int FLAG_GRANT_READ_URI_PERMISSION = 0x00000001; - /** - * If set, the recipient of this Intent will be granted permission to - * perform write operations on the Uri in the Intent's data. - */ - public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 0x00000002; - /** - * Can be set by the caller to indicate that this Intent is coming from - * a background operation, not from direct user interaction. - */ - public static final int FLAG_FROM_BACKGROUND = 0x00000004; - /** - * A flag you can enable for debugging: when set, log messages will be - * printed during the resolution of this intent to show you what has - * been found to create the final resolved list. - */ - public static final int FLAG_DEBUG_LOG_RESOLUTION = 0x00000008; - - /** - * If set, the new activity is not kept in the history stack. As soon as - * the user navigates away from it, the activity is finished. This may also - * be set with the {@link android.R.styleable#AndroidManifestActivity_noHistory - * noHistory} attribute. - */ - public static final int FLAG_ACTIVITY_NO_HISTORY = 0x40000000; - /** - * If set, the activity will not be launched if it is already running - * at the top of the history stack. - */ - public static final int FLAG_ACTIVITY_SINGLE_TOP = 0x20000000; - /** - * If set, this activity will become the start of a new task on this - * history stack. A task (from the activity that started it to the - * next task activity) defines an atomic group of activities that the - * user can move to. Tasks can be moved to the foreground and background; - * all of the activities inside of a particular task always remain in - * the same order. See - * <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals: - * Activities and Tasks</a> for more details on tasks. - * - * <p>This flag is generally used by activities that want - * to present a "launcher" style behavior: they give the user a list of - * separate things that can be done, which otherwise run completely - * independently of the activity launching them. - * - * <p>When using this flag, if a task is already running for the activity - * you are now starting, then a new activity will not be started; instead, - * the current task will simply be brought to the front of the screen with - * the state it was last in. See {@link #FLAG_ACTIVITY_MULTIPLE_TASK} for a flag - * to disable this behavior. - * - * <p>This flag can not be used when the caller is requesting a result from - * the activity being launched. - */ - public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000; - /** - * <strong>Do not use this flag unless you are implementing your own - * top-level application launcher.</strong> Used in conjunction with - * {@link #FLAG_ACTIVITY_NEW_TASK} to disable the - * behavior of bringing an existing task to the foreground. When set, - * a new task is <em>always</em> started to host the Activity for the - * Intent, regardless of whether there is already an existing task running - * the same thing. - * - * <p><strong>Because the default system does not include graphical task management, - * you should not use this flag unless you provide some way for a user to - * return back to the tasks you have launched.</strong> - * - * <p>This flag is ignored if - * {@link #FLAG_ACTIVITY_NEW_TASK} is not set. - * - * <p>See <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals: - * Activities and Tasks</a> for more details on tasks. - */ - public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000; - /** - * If set, and the activity being launched is already running in the - * current task, then instead of launching a new instance of that activity, - * all of the other activities on top of it will be closed and this Intent - * will be delivered to the (now on top) old activity as a new Intent. - * - * <p>For example, consider a task consisting of the activities: A, B, C, D. - * If D calls startActivity() with an Intent that resolves to the component - * of activity B, then C and D will be finished and B receive the given - * Intent, resulting in the stack now being: A, B. - * - * <p>The currently running instance of task B in the above example will - * either receive the new intent you are starting here in its - * onNewIntent() method, or be itself finished and restarted with the - * new intent. If it has declared its launch mode to be "multiple" (the - * default) it will be finished and re-created; for all other launch modes - * it will receive the Intent in the current instance. - * - * <p>This launch mode can also be used to good effect in conjunction with - * {@link #FLAG_ACTIVITY_NEW_TASK}: if used to start the root activity - * of a task, it will bring any currently running instance of that task - * to the foreground, and then clear it to its root state. This is - * especially useful, for example, when launching an activity from the - * notification manager. - * - * <p>See <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals: - * Activities and Tasks</a> for more details on tasks. - */ - public static final int FLAG_ACTIVITY_CLEAR_TOP = 0x04000000; - /** - * If set and this intent is being used to launch a new activity from an - * existing one, then the reply target of the existing activity will be - * transfered to the new activity. This way the new activity can call - * {@link android.app.Activity#setResult} and have that result sent back to - * the reply target of the original activity. - */ - public static final int FLAG_ACTIVITY_FORWARD_RESULT = 0x02000000; - /** - * If set and this intent is being used to launch a new activity from an - * existing one, the current activity will not be counted as the top - * activity for deciding whether the new intent should be delivered to - * the top instead of starting a new one. The previous activity will - * be used as the top, with the assumption being that the current activity - * will finish itself immediately. - */ - public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 0x01000000; - /** - * If set, the new activity is not kept in the list of recently launched - * activities. - */ - public static final int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 0x00800000; - /** - * This flag is not normally set by application code, but set for you by - * the system as described in the - * {@link android.R.styleable#AndroidManifestActivity_launchMode - * launchMode} documentation for the singleTask mode. - */ - public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0x00400000; - /** - * If set, and this activity is either being started in a new task or - * bringing to the top an existing task, then it will be launched as - * the front door of the task. This will result in the application of - * any affinities needed to have that task in the proper state (either - * moving activities to or from it), or simply resetting that task to - * its initial state if needed. - */ - public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0x00200000; - /** - * This flag is not normally set by application code, but set for you by - * the system if this activity is being launched from history - * (longpress home key). - */ - public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 0x00100000; - /** - * If set, this marks a point in the task's activity stack that should - * be cleared when the task is reset. That is, the next time the task - * is broad to the foreground with - * {@link #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED} (typically as a result of - * the user re-launching it from home), this activity and all on top of - * it will be finished so that the user does not return to them, but - * instead returns to whatever activity preceeded it. - * - * <p>This is useful for cases where you have a logical break in your - * application. For example, an e-mail application may have a command - * to view an attachment, which launches an image view activity to - * display it. This activity should be part of the e-mail application's - * task, since it is a part of the task the user is involved in. However, - * if the user leaves that task, and later selects the e-mail app from - * home, we may like them to return to the conversation they were - * viewing, not the picture attachment, since that is confusing. By - * setting this flag when launching the image viewer, that viewer and - * any activities it starts will be removed the next time the user returns - * to mail. - */ - public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000; - /** - * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint} - * callback from occurring on the current frontmost activity before it is - * paused as the newly-started activity is brought to the front. - * - * <p>Typically, an activity can rely on that callback to indicate that an - * explicit user action has caused their activity to be moved out of the - * foreground. The callback marks an appropriate point in the activity's - * lifecycle for it to dismiss any notifications that it intends to display - * "until the user has seen them," such as a blinking LED. - * - * <p>If an activity is ever started via any non-user-driven events such as - * phone-call receipt or an alarm handler, this flag should be passed to {@link - * Context#startActivity Context.startActivity}, ensuring that the pausing - * activity does not think the user has acknowledged its notification. - */ - public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000; - /** - * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, - * this flag will cause the launched activity to be brought to the front of its - * task's history stack if it is already running. - * - * <p>For example, consider a task consisting of four activities: A, B, C, D. - * If D calls startActivity() with an Intent that resolves to the component - * of activity B, then B will be brought to the front of the history stack, - * with this resulting order: A, C, D, B. - * - * This flag will be ignored if {@link #FLAG_ACTIVITY_CLEAR_TOP} is also - * specified. - */ - public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 0X00020000; - /** - * If set, when sending a broadcast only registered receivers will be - * called -- no BroadcastReceiver components will be launched. - */ - public static final int FLAG_RECEIVER_REGISTERED_ONLY = 0x40000000; - /** - * If set, when sending a broadcast <i>before boot has completed</i> only - * registered receivers will be called -- no BroadcastReceiver components - * will be launched. Sticky intent state will be recorded properly even - * if no receivers wind up being called. If {@link #FLAG_RECEIVER_REGISTERED_ONLY} - * is specified in the broadcast intent, this flag is unnecessary. - * - * <p>This flag is only for use by system sevices as a convenience to - * avoid having to implement a more complex mechanism around detection - * of boot completion. - * - * @hide - */ - public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000; - - // --------------------------------------------------------------------- - - private String mAction; - private Uri mData; - private String mType; - private ComponentName mComponent; - private int mFlags; - private HashSet<String> mCategories; - private Bundle mExtras; - - // --------------------------------------------------------------------- - - /** - * Create an empty intent. - */ - public Intent() { - } - - /** - * Copy constructor. - */ - public Intent(Intent o) { - this.mAction = o.mAction; - this.mData = o.mData; - this.mType = o.mType; - this.mComponent = o.mComponent; - this.mFlags = o.mFlags; - if (o.mCategories != null) { - this.mCategories = new HashSet<String>(o.mCategories); - } - if (o.mExtras != null) { - this.mExtras = new Bundle(o.mExtras); - } - } - - @Override - public Object clone() { - return new Intent(this); - } - - private Intent(Intent o, boolean all) { - this.mAction = o.mAction; - this.mData = o.mData; - this.mType = o.mType; - this.mComponent = o.mComponent; - if (o.mCategories != null) { - this.mCategories = new HashSet<String>(o.mCategories); - } - } - - /** - * Make a clone of only the parts of the Intent that are relevant for - * filter matching: the action, data, type, component, and categories. - */ - public Intent cloneFilter() { - return new Intent(this, false); - } - - /** - * Create an intent with a given action. All other fields (data, type, - * class) are null. Note that the action <em>must</em> be in a - * namespace because Intents are used globally in the system -- for - * example the system VIEW action is android.intent.action.VIEW; an - * application's custom action would be something like - * com.google.app.myapp.CUSTOM_ACTION. - * - * @param action The Intent action, such as ACTION_VIEW. - */ - public Intent(String action) { - mAction = action; - } - - /** - * Create an intent with a given action and for a given data url. Note - * that the action <em>must</em> be in a namespace because Intents are - * used globally in the system -- for example the system VIEW action is - * android.intent.action.VIEW; an application's custom action would be - * something like com.google.app.myapp.CUSTOM_ACTION. - * - * @param action The Intent action, such as ACTION_VIEW. - * @param uri The Intent data URI. - */ - public Intent(String action, Uri uri) { - mAction = action; - mData = uri; - } - - /** - * Create an intent for a specific component. All other fields (action, data, - * type, class) are null, though they can be modified later with explicit - * calls. This provides a convenient way to create an intent that is - * intended to execute a hard-coded class name, rather than relying on the - * system to find an appropriate class for you; see {@link #setComponent} - * for more information on the repercussions of this. - * - * @param packageContext A Context of the application package implementing - * this class. - * @param cls The component class that is to be used for the intent. - * - * @see #setClass - * @see #setComponent - * @see #Intent(String, android.net.Uri , Context, Class) - */ - public Intent(Context packageContext, Class<?> cls) { - mComponent = new ComponentName(packageContext, cls); - } - - /** - * Create an intent for a specific component with a specified action and data. - * This is equivalent using {@link #Intent(String, android.net.Uri)} to - * construct the Intent and then calling {@link #setClass} to set its - * class. - * - * @param action The Intent action, such as ACTION_VIEW. - * @param uri The Intent data URI. - * @param packageContext A Context of the application package implementing - * this class. - * @param cls The component class that is to be used for the intent. - * - * @see #Intent(String, android.net.Uri) - * @see #Intent(Context, Class) - * @see #setClass - * @see #setComponent - */ - public Intent(String action, Uri uri, - Context packageContext, Class<?> cls) { - mAction = action; - mData = uri; - mComponent = new ComponentName(packageContext, cls); - } - - /** - * Create an intent from a URI. This URI may encode the action, - * category, and other intent fields, if it was returned by toURI(). If - * the Intent was not generate by toURI(), its data will be the entire URI - * and its action will be ACTION_VIEW. - * - * <p>The URI given here must not be relative -- that is, it must include - * the scheme and full path. - * - * @param uri The URI to turn into an Intent. - * - * @return Intent The newly created Intent object. - * - * @see #toURI - */ - public static Intent getIntent(String uri) throws URISyntaxException { - int i = 0; - try { - // simple case - i = uri.lastIndexOf("#"); - if (i == -1) return new Intent(ACTION_VIEW, Uri.parse(uri)); - - // old format Intent URI - if (!uri.startsWith("#Intent;", i)) return getIntentOld(uri); - - // new format - Intent intent = new Intent(ACTION_VIEW); - - // fetch data part, if present - if (i > 0) { - intent.mData = Uri.parse(uri.substring(0, i)); - } - i += "#Intent;".length(); - - // loop over contents of Intent, all name=value; - while (!uri.startsWith("end", i)) { - int eq = uri.indexOf('=', i); - int semi = uri.indexOf(';', eq); - String value = uri.substring(eq + 1, semi); - - // action - if (uri.startsWith("action=", i)) { - intent.mAction = value; - } - - // categories - else if (uri.startsWith("category=", i)) { - intent.addCategory(value); - } - - // type - else if (uri.startsWith("type=", i)) { - intent.mType = value; - } - - // launch flags - else if (uri.startsWith("launchFlags=", i)) { - intent.mFlags = Integer.decode(value).intValue(); - } - - // component - else if (uri.startsWith("component=", i)) { - intent.mComponent = ComponentName.unflattenFromString(value); - } - - // extra - else { - String key = Uri.decode(uri.substring(i + 2, eq)); - value = Uri.decode(value); - // create Bundle if it doesn't already exist - if (intent.mExtras == null) intent.mExtras = new Bundle(); - Bundle b = intent.mExtras; - // add EXTRA - if (uri.startsWith("S.", i)) b.putString(key, value); - else if (uri.startsWith("B.", i)) b.putBoolean(key, Boolean.parseBoolean(value)); - else if (uri.startsWith("b.", i)) b.putByte(key, Byte.parseByte(value)); - else if (uri.startsWith("c.", i)) b.putChar(key, value.charAt(0)); - else if (uri.startsWith("d.", i)) b.putDouble(key, Double.parseDouble(value)); - else if (uri.startsWith("f.", i)) b.putFloat(key, Float.parseFloat(value)); - else if (uri.startsWith("i.", i)) b.putInt(key, Integer.parseInt(value)); - else if (uri.startsWith("l.", i)) b.putLong(key, Long.parseLong(value)); - else if (uri.startsWith("s.", i)) b.putShort(key, Short.parseShort(value)); - else throw new URISyntaxException(uri, "unknown EXTRA type", i); - } - - // move to the next item - i = semi + 1; - } - - return intent; - - } catch (IndexOutOfBoundsException e) { - throw new URISyntaxException(uri, "illegal Intent URI format", i); - } - } - - public static Intent getIntentOld(String uri) throws URISyntaxException { - Intent intent; - - int i = uri.lastIndexOf('#'); - if (i >= 0) { - Uri data = null; - String action = null; - if (i > 0) { - data = Uri.parse(uri.substring(0, i)); - } - - i++; - - if (uri.regionMatches(i, "action(", 0, 7)) { - i += 7; - int j = uri.indexOf(')', i); - action = uri.substring(i, j); - i = j + 1; - } - - intent = new Intent(action, data); - - if (uri.regionMatches(i, "categories(", 0, 11)) { - i += 11; - int j = uri.indexOf(')', i); - while (i < j) { - int sep = uri.indexOf('!', i); - if (sep < 0) sep = j; - if (i < sep) { - intent.addCategory(uri.substring(i, sep)); - } - i = sep + 1; - } - i = j + 1; - } - - if (uri.regionMatches(i, "type(", 0, 5)) { - i += 5; - int j = uri.indexOf(')', i); - intent.mType = uri.substring(i, j); - i = j + 1; - } - - if (uri.regionMatches(i, "launchFlags(", 0, 12)) { - i += 12; - int j = uri.indexOf(')', i); - intent.mFlags = Integer.decode(uri.substring(i, j)).intValue(); - i = j + 1; - } - - if (uri.regionMatches(i, "component(", 0, 10)) { - i += 10; - int j = uri.indexOf(')', i); - int sep = uri.indexOf('!', i); - if (sep >= 0 && sep < j) { - String pkg = uri.substring(i, sep); - String cls = uri.substring(sep + 1, j); - intent.mComponent = new ComponentName(pkg, cls); - } - i = j + 1; - } - - if (uri.regionMatches(i, "extras(", 0, 7)) { - i += 7; - - final int closeParen = uri.indexOf(')', i); - if (closeParen == -1) throw new URISyntaxException(uri, - "EXTRA missing trailing ')'", i); - - while (i < closeParen) { - // fetch the key value - int j = uri.indexOf('=', i); - if (j <= i + 1 || i >= closeParen) { - throw new URISyntaxException(uri, "EXTRA missing '='", i); - } - char type = uri.charAt(i); - i++; - String key = uri.substring(i, j); - i = j + 1; - - // get type-value - j = uri.indexOf('!', i); - if (j == -1 || j >= closeParen) j = closeParen; - if (i >= j) throw new URISyntaxException(uri, "EXTRA missing '!'", i); - String value = uri.substring(i, j); - i = j; - - // create Bundle if it doesn't already exist - if (intent.mExtras == null) intent.mExtras = new Bundle(); - - // add item to bundle - try { - switch (type) { - case 'S': - intent.mExtras.putString(key, Uri.decode(value)); - break; - case 'B': - intent.mExtras.putBoolean(key, Boolean.parseBoolean(value)); - break; - case 'b': - intent.mExtras.putByte(key, Byte.parseByte(value)); - break; - case 'c': - intent.mExtras.putChar(key, Uri.decode(value).charAt(0)); - break; - case 'd': - intent.mExtras.putDouble(key, Double.parseDouble(value)); - break; - case 'f': - intent.mExtras.putFloat(key, Float.parseFloat(value)); - break; - case 'i': - intent.mExtras.putInt(key, Integer.parseInt(value)); - break; - case 'l': - intent.mExtras.putLong(key, Long.parseLong(value)); - break; - case 's': - intent.mExtras.putShort(key, Short.parseShort(value)); - break; - default: - throw new URISyntaxException(uri, "EXTRA has unknown type", i); - } - } catch (NumberFormatException e) { - throw new URISyntaxException(uri, "EXTRA value can't be parsed", i); - } - - char ch = uri.charAt(i); - if (ch == ')') break; - if (ch != '!') throw new URISyntaxException(uri, "EXTRA missing '!'", i); - i++; - } - } - - if (intent.mAction == null) { - // By default, if no action is specified, then use VIEW. - intent.mAction = ACTION_VIEW; - } - - } else { - intent = new Intent(ACTION_VIEW, Uri.parse(uri)); - } - - return intent; - } - - /** - * Retrieve the general action to be performed, such as - * {@link #ACTION_VIEW}. The action describes the general way the rest of - * the information in the intent should be interpreted -- most importantly, - * what to do with the data returned by {@link #getData}. - * - * @return The action of this intent or null if none is specified. - * - * @see #setAction - */ - public String getAction() { - return mAction; - } - - /** - * Retrieve data this intent is operating on. This URI specifies the name - * of the data; often it uses the content: scheme, specifying data in a - * content provider. Other schemes may be handled by specific activities, - * such as http: by the web browser. - * - * @return The URI of the data this intent is targeting or null. - * - * @see #getScheme - * @see #setData - */ - public Uri getData() { - return mData; - } - - /** - * The same as {@link #getData()}, but returns the URI as an encoded - * String. - */ - public String getDataString() { - return mData != null ? mData.toString() : null; - } - - /** - * Return the scheme portion of the intent's data. If the data is null or - * does not include a scheme, null is returned. Otherwise, the scheme - * prefix without the final ':' is returned, i.e. "http". - * - * <p>This is the same as calling getData().getScheme() (and checking for - * null data). - * - * @return The scheme of this intent. - * - * @see #getData - */ - public String getScheme() { - return mData != null ? mData.getScheme() : null; - } - - /** - * Retrieve any explicit MIME type included in the intent. This is usually - * null, as the type is determined by the intent data. - * - * @return If a type was manually set, it is returned; else null is - * returned. - * - * @see #resolveType(ContentResolver) - * @see #setType - */ - public String getType() { - return mType; - } - - /** - * Return the MIME data type of this intent. If the type field is - * explicitly set, that is simply returned. Otherwise, if the data is set, - * the type of that data is returned. If neither fields are set, a null is - * returned. - * - * @return The MIME type of this intent. - * - * @see #getType - * @see #resolveType(ContentResolver) - */ - public String resolveType(Context context) { - return resolveType(context.getContentResolver()); - } - - /** - * Return the MIME data type of this intent. If the type field is - * explicitly set, that is simply returned. Otherwise, if the data is set, - * the type of that data is returned. If neither fields are set, a null is - * returned. - * - * @param resolver A ContentResolver that can be used to determine the MIME - * type of the intent's data. - * - * @return The MIME type of this intent. - * - * @see #getType - * @see #resolveType(Context) - */ - public String resolveType(ContentResolver resolver) { - if (mType != null) { - return mType; - } - if (mData != null) { - if ("content".equals(mData.getScheme())) { - return resolver.getType(mData); - } - } - return null; - } - - /** - * Return the MIME data type of this intent, only if it will be needed for - * intent resolution. This is not generally useful for application code; - * it is used by the frameworks for communicating with back-end system - * services. - * - * @param resolver A ContentResolver that can be used to determine the MIME - * type of the intent's data. - * - * @return The MIME type of this intent, or null if it is unknown or not - * needed. - */ - public String resolveTypeIfNeeded(ContentResolver resolver) { - if (mComponent != null) { - return mType; - } - return resolveType(resolver); - } - - /** - * Check if an category exists in the intent. - * - * @param category The category to check. - * - * @return boolean True if the intent contains the category, else false. - * - * @see #getCategories - * @see #addCategory - */ - public boolean hasCategory(String category) { - return mCategories != null && mCategories.contains(category); - } - - /** - * Return the set of all categories in the intent. If there are no categories, - * returns NULL. - * - * @return Set The set of categories you can examine. Do not modify! - * - * @see #hasCategory - * @see #addCategory - */ - public Set<String> getCategories() { - return mCategories; - } - - /** - * Sets the ClassLoader that will be used when unmarshalling - * any Parcelable values from the extras of this Intent. - * - * @param loader a ClassLoader, or null to use the default loader - * at the time of unmarshalling. - */ - public void setExtrasClassLoader(ClassLoader loader) { - if (mExtras != null) { - mExtras.setClassLoader(loader); - } - } - - /** - * Returns true if an extra value is associated with the given name. - * @param name the extra's name - * @return true if the given extra is present. - */ - public boolean hasExtra(String name) { - return mExtras != null && mExtras.containsKey(name); - } - - /** - * Returns true if the Intent's extras contain a parcelled file descriptor. - * @return true if the Intent contains a parcelled file descriptor. - */ - public boolean hasFileDescriptors() { - return mExtras != null && mExtras.hasFileDescriptors(); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if none was found. - * - * @deprecated - * @hide - */ - @Deprecated - public Object getExtra(String name) { - return getExtra(name, null); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, boolean) - */ - public boolean getBooleanExtra(String name, boolean defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getBoolean(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, byte) - */ - public byte getByteExtra(String name, byte defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getByte(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, short) - */ - public short getShortExtra(String name, short defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getShort(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, char) - */ - public char getCharExtra(String name, char defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getChar(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, int) - */ - public int getIntExtra(String name, int defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getInt(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, long) - */ - public long getLongExtra(String name, long defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getLong(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra(), - * or the default value if no such item is present - * - * @see #putExtra(String, float) - */ - public float getFloatExtra(String name, float defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getFloat(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue the value to be returned if no value of the desired - * type is stored with the given name. - * - * @return the value of an item that previously added with putExtra() - * or the default value if none was found. - * - * @see #putExtra(String, double) - */ - public double getDoubleExtra(String name, double defaultValue) { - return mExtras == null ? defaultValue : - mExtras.getDouble(name, defaultValue); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no String value was found. - * - * @see #putExtra(String, String) - */ - public String getStringExtra(String name) { - return mExtras == null ? null : mExtras.getString(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no CharSequence value was found. - * - * @see #putExtra(String, CharSequence) - */ - public CharSequence getCharSequenceExtra(String name) { - return mExtras == null ? null : mExtras.getCharSequence(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no Parcelable value was found. - * - * @see #putExtra(String, Parcelable) - */ - public <T extends Parcelable> T getParcelableExtra(String name) { - return mExtras == null ? null : mExtras.<T>getParcelable(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no Parcelable[] value was found. - * - * @see #putExtra(String, Parcelable[]) - */ - public Parcelable[] getParcelableArrayExtra(String name) { - return mExtras == null ? null : mExtras.getParcelableArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no ArrayList<Parcelable> value was found. - * - * @see #putParcelableArrayListExtra(String, ArrayList) - */ - public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) { - return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no Serializable value was found. - * - * @see #putExtra(String, Serializable) - */ - public Serializable getSerializableExtra(String name) { - return mExtras == null ? null : mExtras.getSerializable(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no ArrayList<Integer> value was found. - * - * @see #putIntegerArrayListExtra(String, ArrayList) - */ - public ArrayList<Integer> getIntegerArrayListExtra(String name) { - return mExtras == null ? null : mExtras.getIntegerArrayList(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no ArrayList<String> value was found. - * - * @see #putStringArrayListExtra(String, ArrayList) - */ - public ArrayList<String> getStringArrayListExtra(String name) { - return mExtras == null ? null : mExtras.getStringArrayList(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no boolean array value was found. - * - * @see #putExtra(String, boolean[]) - */ - public boolean[] getBooleanArrayExtra(String name) { - return mExtras == null ? null : mExtras.getBooleanArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no byte array value was found. - * - * @see #putExtra(String, byte[]) - */ - public byte[] getByteArrayExtra(String name) { - return mExtras == null ? null : mExtras.getByteArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no short array value was found. - * - * @see #putExtra(String, short[]) - */ - public short[] getShortArrayExtra(String name) { - return mExtras == null ? null : mExtras.getShortArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no char array value was found. - * - * @see #putExtra(String, char[]) - */ - public char[] getCharArrayExtra(String name) { - return mExtras == null ? null : mExtras.getCharArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no int array value was found. - * - * @see #putExtra(String, int[]) - */ - public int[] getIntArrayExtra(String name) { - return mExtras == null ? null : mExtras.getIntArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no long array value was found. - * - * @see #putExtra(String, long[]) - */ - public long[] getLongArrayExtra(String name) { - return mExtras == null ? null : mExtras.getLongArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no float array value was found. - * - * @see #putExtra(String, float[]) - */ - public float[] getFloatArrayExtra(String name) { - return mExtras == null ? null : mExtras.getFloatArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no double array value was found. - * - * @see #putExtra(String, double[]) - */ - public double[] getDoubleArrayExtra(String name) { - return mExtras == null ? null : mExtras.getDoubleArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no String array value was found. - * - * @see #putExtra(String, String[]) - */ - public String[] getStringArrayExtra(String name) { - return mExtras == null ? null : mExtras.getStringArray(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no Bundle value was found. - * - * @see #putExtra(String, Bundle) - */ - public Bundle getBundleExtra(String name) { - return mExtras == null ? null : mExtras.getBundle(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * - * @return the value of an item that previously added with putExtra() - * or null if no IBinder value was found. - * - * @see #putExtra(String, IBinder) - * - * @deprecated - * @hide - */ - @Deprecated - public IBinder getIBinderExtra(String name) { - return mExtras == null ? null : mExtras.getIBinder(name); - } - - /** - * Retrieve extended data from the intent. - * - * @param name The name of the desired item. - * @param defaultValue The default value to return in case no item is - * associated with the key 'name' - * - * @return the value of an item that previously added with putExtra() - * or defaultValue if none was found. - * - * @see #putExtra - * - * @deprecated - * @hide - */ - @Deprecated - public Object getExtra(String name, Object defaultValue) { - Object result = defaultValue; - if (mExtras != null) { - Object result2 = mExtras.get(name); - if (result2 != null) { - result = result2; - } - } - - return result; - } - - /** - * Retrieves a map of extended data from the intent. - * - * @return the map of all extras previously added with putExtra(), - * or null if none have been added. - */ - public Bundle getExtras() { - return (mExtras != null) - ? new Bundle(mExtras) - : null; - } - - /** - * Retrieve any special flags associated with this intent. You will - * normally just set them with {@link #setFlags} and let the system - * take the appropriate action with them. - * - * @return int The currently set flags. - * - * @see #setFlags - */ - public int getFlags() { - return mFlags; - } - - /** - * Retrieve the concrete component associated with the intent. When receiving - * an intent, this is the component that was found to best handle it (that is, - * yourself) and will always be non-null; in all other cases it will be - * null unless explicitly set. - * - * @return The name of the application component to handle the intent. - * - * @see #resolveActivity - * @see #setComponent - */ - public ComponentName getComponent() { - return mComponent; - } - - /** - * Return the Activity component that should be used to handle this intent. - * The appropriate component is determined based on the information in the - * intent, evaluated as follows: - * - * <p>If {@link #getComponent} returns an explicit class, that is returned - * without any further consideration. - * - * <p>The activity must handle the {@link Intent#CATEGORY_DEFAULT} Intent - * category to be considered. - * - * <p>If {@link #getAction} is non-NULL, the activity must handle this - * action. - * - * <p>If {@link #resolveType} returns non-NULL, the activity must handle - * this type. - * - * <p>If {@link #addCategory} has added any categories, the activity must - * handle ALL of the categories specified. - * - * <p>If there are no activities that satisfy all of these conditions, a - * null string is returned. - * - * <p>If multiple activities are found to satisfy the intent, the one with - * the highest priority will be used. If there are multiple activities - * with the same priority, the system will either pick the best activity - * based on user preference, or resolve to a system class that will allow - * the user to pick an activity and forward from there. - * - * <p>This method is implemented simply by calling - * {@link PackageManager#resolveActivity} with the "defaultOnly" parameter - * true.</p> - * <p> This API is called for you as part of starting an activity from an - * intent. You do not normally need to call it yourself.</p> - * - * @param pm The package manager with which to resolve the Intent. - * - * @return Name of the component implementing an activity that can - * display the intent. - * - * @see #setComponent - * @see #getComponent - * @see #resolveActivityInfo - */ - public ComponentName resolveActivity(PackageManager pm) { - if (mComponent != null) { - return mComponent; - } - - ResolveInfo info = pm.resolveActivity( - this, PackageManager.MATCH_DEFAULT_ONLY); - if (info != null) { - return new ComponentName( - info.activityInfo.applicationInfo.packageName, - info.activityInfo.name); - } - - return null; - } - - /** - * Resolve the Intent into an {@link ActivityInfo} - * describing the activity that should execute the intent. Resolution - * follows the same rules as described for {@link #resolveActivity}, but - * you get back the completely information about the resolved activity - * instead of just its class name. - * - * @param pm The package manager with which to resolve the Intent. - * @param flags Addition information to retrieve as per - * {@link PackageManager#getActivityInfo(ComponentName, int) - * PackageManager.getActivityInfo()}. - * - * @return PackageManager.ActivityInfo - * - * @see #resolveActivity - */ - public ActivityInfo resolveActivityInfo(PackageManager pm, int flags) { - ActivityInfo ai = null; - if (mComponent != null) { - try { - ai = pm.getActivityInfo(mComponent, flags); - } catch (PackageManager.NameNotFoundException e) { - // ignore - } - } else { - ResolveInfo info = pm.resolveActivity( - this, PackageManager.MATCH_DEFAULT_ONLY); - if (info != null) { - ai = info.activityInfo; - } - } - - return ai; - } - - /** - * Set the general action to be performed. - * - * @param action An action name, such as ACTION_VIEW. Application-specific - * actions should be prefixed with the vendor's package name. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #getAction - */ - public Intent setAction(String action) { - mAction = action; - return this; - } - - /** - * Set the data this intent is operating on. This method automatically - * clears any type that was previously set by {@link #setType}. - * - * @param data The URI of the data this intent is now targeting. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #getData - * @see #setType - * @see #setDataAndType - */ - public Intent setData(Uri data) { - mData = data; - mType = null; - return this; - } - - /** - * Set an explicit MIME data type. This is used to create intents that - * only specify a type and not data, for example to indicate the type of - * data to return. This method automatically clears any data that was - * previously set by {@link #setData}. - * - * @param type The MIME type of the data being handled by this intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #getType - * @see #setData - * @see #setDataAndType - */ - public Intent setType(String type) { - mData = null; - mType = type; - return this; - } - - /** - * (Usually optional) Set the data for the intent along with an explicit - * MIME data type. This method should very rarely be used -- it allows you - * to override the MIME type that would ordinarily be inferred from the - * data with your own type given here. - * - * @param data The URI of the data this intent is now targeting. - * @param type The MIME type of the data being handled by this intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setData - * @see #setType - */ - public Intent setDataAndType(Uri data, String type) { - mData = data; - mType = type; - return this; - } - - /** - * Add a new category to the intent. Categories provide additional detail - * about the action the intent is perform. When resolving an intent, only - * activities that provide <em>all</em> of the requested categories will be - * used. - * - * @param category The desired category. This can be either one of the - * predefined Intent categories, or a custom category in your own - * namespace. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #hasCategory - * @see #removeCategory - */ - public Intent addCategory(String category) { - if (mCategories == null) { - mCategories = new HashSet<String>(); - } - mCategories.add(category); - return this; - } - - /** - * Remove an category from an intent. - * - * @param category The category to remove. - * - * @see #addCategory - */ - public void removeCategory(String category) { - if (mCategories != null) { - mCategories.remove(category); - if (mCategories.size() == 0) { - mCategories = null; - } - } - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The boolean data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getBooleanExtra(String, boolean) - */ - public Intent putExtra(String name, boolean value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putBoolean(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The byte data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getByteExtra(String, byte) - */ - public Intent putExtra(String name, byte value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putByte(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The char data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharExtra(String, char) - */ - public Intent putExtra(String name, char value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putChar(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The short data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getShortExtra(String, short) - */ - public Intent putExtra(String name, short value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putShort(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The integer data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIntExtra(String, int) - */ - public Intent putExtra(String name, int value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putInt(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The long data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getLongExtra(String, long) - */ - public Intent putExtra(String name, long value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putLong(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The float data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getFloatExtra(String, float) - */ - public Intent putExtra(String name, float value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putFloat(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The double data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getDoubleExtra(String, double) - */ - public Intent putExtra(String name, double value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putDouble(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The String data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getStringExtra(String) - */ - public Intent putExtra(String name, String value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putString(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The CharSequence data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharSequenceExtra(String) - */ - public Intent putExtra(String name, CharSequence value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putCharSequence(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Parcelable data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getParcelableExtra(String) - */ - public Intent putExtra(String name, Parcelable value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putParcelable(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Parcelable[] data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getParcelableArrayExtra(String) - */ - public Intent putExtra(String name, Parcelable[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putParcelableArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<Parcelable> data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getParcelableArrayListExtra(String) - */ - public Intent putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putParcelableArrayList(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<Integer> data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIntegerArrayListExtra(String) - */ - public Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putIntegerArrayList(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The ArrayList<String> data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getStringArrayListExtra(String) - */ - public Intent putStringArrayListExtra(String name, ArrayList<String> value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putStringArrayList(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Serializable data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getSerializableExtra(String) - */ - public Intent putExtra(String name, Serializable value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putSerializable(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The boolean array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getBooleanArrayExtra(String) - */ - public Intent putExtra(String name, boolean[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putBooleanArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The byte array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getByteArrayExtra(String) - */ - public Intent putExtra(String name, byte[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putByteArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The short array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getShortArrayExtra(String) - */ - public Intent putExtra(String name, short[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putShortArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The char array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getCharArrayExtra(String) - */ - public Intent putExtra(String name, char[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putCharArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The int array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIntArrayExtra(String) - */ - public Intent putExtra(String name, int[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putIntArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The byte array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getLongArrayExtra(String) - */ - public Intent putExtra(String name, long[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putLongArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The float array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getFloatArrayExtra(String) - */ - public Intent putExtra(String name, float[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putFloatArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The double array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getDoubleArrayExtra(String) - */ - public Intent putExtra(String name, double[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putDoubleArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The String array data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getStringArrayExtra(String) - */ - public Intent putExtra(String name, String[] value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putStringArray(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The Bundle data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getBundleExtra(String) - */ - public Intent putExtra(String name, Bundle value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putBundle(name, value); - return this; - } - - /** - * Add extended data to the intent. The name must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param name The name of the extra data, with package prefix. - * @param value The IBinder data value. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #putExtras - * @see #removeExtra - * @see #getIBinderExtra(String) - * - * @deprecated - * @hide - */ - @Deprecated - public Intent putExtra(String name, IBinder value) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putIBinder(name, value); - return this; - } - - /** - * Copy all extras in 'src' in to this intent. - * - * @param src Contains the extras to copy. - * - * @see #putExtra - */ - public Intent putExtras(Intent src) { - if (src.mExtras != null) { - if (mExtras == null) { - mExtras = new Bundle(src.mExtras); - } else { - mExtras.putAll(src.mExtras); - } - } - return this; - } - - /** - * Add a set of extended data to the intent. The keys must include a package - * prefix, for example the app com.android.contacts would use names - * like "com.android.contacts.ShowAll". - * - * @param extras The Bundle of extras to add to this intent. - * - * @see #putExtra - * @see #removeExtra - */ - public Intent putExtras(Bundle extras) { - if (mExtras == null) { - mExtras = new Bundle(); - } - mExtras.putAll(extras); - return this; - } - - /** - * Completely replace the extras in the Intent with the extras in the - * given Intent. - * - * @param src The exact extras contained in this Intent are copied - * into the target intent, replacing any that were previously there. - */ - public Intent replaceExtras(Intent src) { - mExtras = src.mExtras != null ? new Bundle(src.mExtras) : null; - return this; - } - - /** - * Completely replace the extras in the Intent with the given Bundle of - * extras. - * - * @param extras The new set of extras in the Intent, or null to erase - * all extras. - */ - public Intent replaceExtras(Bundle extras) { - mExtras = extras != null ? new Bundle(extras) : null; - return this; - } - - /** - * Remove extended data from the intent. - * - * @see #putExtra - */ - public void removeExtra(String name) { - if (mExtras != null) { - mExtras.remove(name); - if (mExtras.size() == 0) { - mExtras = null; - } - } - } - - /** - * Set special flags controlling how this intent is handled. Most values - * here depend on the type of component being executed by the Intent, - * specifically the FLAG_ACTIVITY_* flags are all for use with - * {@link Context#startActivity Context.startActivity()} and the - * FLAG_RECEIVER_* flags are all for use with - * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}. - * - * <p>See the <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals: - * Activities and Tasks</a> documentation for important information on how some of these options impact - * the behavior of your application. - * - * @param flags The desired flags. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #getFlags - * @see #addFlags - * - * @see #FLAG_GRANT_READ_URI_PERMISSION - * @see #FLAG_GRANT_WRITE_URI_PERMISSION - * @see #FLAG_DEBUG_LOG_RESOLUTION - * @see #FLAG_FROM_BACKGROUND - * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT - * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET - * @see #FLAG_ACTIVITY_CLEAR_TOP - * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - * @see #FLAG_ACTIVITY_FORWARD_RESULT - * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - * @see #FLAG_ACTIVITY_MULTIPLE_TASK - * @see #FLAG_ACTIVITY_NEW_TASK - * @see #FLAG_ACTIVITY_NO_HISTORY - * @see #FLAG_ACTIVITY_NO_USER_ACTION - * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP - * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - * @see #FLAG_ACTIVITY_SINGLE_TOP - * @see #FLAG_RECEIVER_REGISTERED_ONLY - */ - public Intent setFlags(int flags) { - mFlags = flags; - return this; - } - - /** - * Add additional flags to the intent (or with existing flags - * value). - * - * @param flags The new flags to set. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setFlags - */ - public Intent addFlags(int flags) { - mFlags |= flags; - return this; - } - - /** - * (Usually optional) Explicitly set the component to handle the intent. - * If left with the default value of null, the system will determine the - * appropriate class to use based on the other fields (action, data, - * type, categories) in the Intent. If this class is defined, the - * specified class will always be used regardless of the other fields. You - * should only set this value when you know you absolutely want a specific - * class to be used; otherwise it is better to let the system find the - * appropriate class so that you will respect the installed applications - * and user preferences. - * - * @param component The name of the application component to handle the - * intent, or null to let the system find one for you. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setClass - * @see #setClassName(Context, String) - * @see #setClassName(String, String) - * @see #getComponent - * @see #resolveActivity - */ - public Intent setComponent(ComponentName component) { - mComponent = component; - return this; - } - - /** - * Convenience for calling {@link #setComponent} with an - * explicit class name. - * - * @param packageContext A Context of the application package implementing - * this class. - * @param className The name of a class inside of the application package - * that will be used as the component for this Intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setComponent - * @see #setClass - */ - public Intent setClassName(Context packageContext, String className) { - mComponent = new ComponentName(packageContext, className); - return this; - } - - /** - * Convenience for calling {@link #setComponent} with an - * explicit application package name and class name. - * - * @param packageName The name of the package implementing the desired - * component. - * @param className The name of a class inside of the application package - * that will be used as the component for this Intent. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setComponent - * @see #setClass - */ - public Intent setClassName(String packageName, String className) { - mComponent = new ComponentName(packageName, className); - return this; - } - - /** - * Convenience for calling {@link #setComponent(ComponentName)} with the - * name returned by a {@link Class} object. - * - * @param packageContext A Context of the application package implementing - * this class. - * @param cls The class name to set, equivalent to - * <code>setClassName(context, cls.getName())</code>. - * - * @return Returns the same Intent object, for chaining multiple calls - * into a single statement. - * - * @see #setComponent - */ - public Intent setClass(Context packageContext, Class<?> cls) { - mComponent = new ComponentName(packageContext, cls); - return this; - } - - /** - * Use with {@link #fillIn} to allow the current action value to be - * overwritten, even if it is already set. - */ - public static final int FILL_IN_ACTION = 1<<0; - - /** - * Use with {@link #fillIn} to allow the current data or type value - * overwritten, even if it is already set. - */ - public static final int FILL_IN_DATA = 1<<1; - - /** - * Use with {@link #fillIn} to allow the current categories to be - * overwritten, even if they are already set. - */ - public static final int FILL_IN_CATEGORIES = 1<<2; - - /** - * Use with {@link #fillIn} to allow the current component value to be - * overwritten, even if it is already set. - */ - public static final int FILL_IN_COMPONENT = 1<<3; - - /** - * Copy the contents of <var>other</var> in to this object, but only - * where fields are not defined by this object. For purposes of a field - * being defined, the following pieces of data in the Intent are - * considered to be separate fields: - * - * <ul> - * <li> action, as set by {@link #setAction}. - * <li> data URI and MIME type, as set by {@link #setData(Uri)}, - * {@link #setType(String)}, or {@link #setDataAndType(Uri, String)}. - * <li> categories, as set by {@link #addCategory}. - * <li> component, as set by {@link #setComponent(ComponentName)} or - * related methods. - * <li> each top-level name in the associated extras. - * </ul> - * - * <p>In addition, you can use the {@link #FILL_IN_ACTION}, - * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and - * {@link #FILL_IN_COMPONENT} to override the restriction where the - * corresponding field will not be replaced if it is already set. - * - * <p>For example, consider Intent A with {data="foo", categories="bar"} - * and Intent B with {action="gotit", data-type="some/thing", - * categories="one","two"}. - * - * <p>Calling A.fillIn(B, Intent.FILL_IN_DATA) will result in A now - * containing: {action="gotit", data-type="some/thing", - * categories="bar"}. - * - * @param other Another Intent whose values are to be used to fill in - * the current one. - * @param flags Options to control which fields can be filled in. - * - * @return Returns a bit mask of {@link #FILL_IN_ACTION}, - * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and - * {@link #FILL_IN_COMPONENT} indicating which fields were changed. - */ - public int fillIn(Intent other, int flags) { - int changes = 0; - if ((mAction == null && other.mAction == null) - || (flags&FILL_IN_ACTION) != 0) { - mAction = other.mAction; - changes |= FILL_IN_ACTION; - } - if ((mData == null && mType == null && - (other.mData != null || other.mType != null)) - || (flags&FILL_IN_DATA) != 0) { - mData = other.mData; - mType = other.mType; - changes |= FILL_IN_DATA; - } - if ((mCategories == null && other.mCategories == null) - || (flags&FILL_IN_CATEGORIES) != 0) { - if (other.mCategories != null) { - mCategories = new HashSet<String>(other.mCategories); - } - changes |= FILL_IN_CATEGORIES; - } - if ((mComponent == null && other.mComponent == null) - || (flags&FILL_IN_COMPONENT) != 0) { - mComponent = other.mComponent; - changes |= FILL_IN_COMPONENT; - } - mFlags |= other.mFlags; - if (mExtras == null) { - if (other.mExtras != null) { - mExtras = new Bundle(other.mExtras); - } - } else if (other.mExtras != null) { - try { - Bundle newb = new Bundle(other.mExtras); - newb.putAll(mExtras); - mExtras = newb; - } catch (RuntimeException e) { - // Modifying the extras can cause us to unparcel the contents - // of the bundle, and if we do this in the system process that - // may fail. We really should handle this (i.e., the Bundle - // impl shouldn't be on top of a plain map), but for now just - // ignore it and keep the original contents. :( - Log.w("Intent", "Failure filling in extras", e); - } - } - return changes; - } - - /** - * Wrapper class holding an Intent and implementing comparisons on it for - * the purpose of filtering. The class implements its - * {@link #equals equals()} and {@link #hashCode hashCode()} methods as - * simple calls to {@link Intent#filterEquals(Intent)} filterEquals()} and - * {@link android.content.Intent#filterHashCode()} filterHashCode()} - * on the wrapped Intent. - */ - public static final class FilterComparison { - private final Intent mIntent; - private final int mHashCode; - - public FilterComparison(Intent intent) { - mIntent = intent; - mHashCode = intent.filterHashCode(); - } - - /** - * Return the Intent that this FilterComparison represents. - * @return Returns the Intent held by the FilterComparison. Do - * not modify! - */ - public Intent getIntent() { - return mIntent; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof FilterComparison) { - Intent other = ((FilterComparison)obj).mIntent; - return mIntent.filterEquals(other); - } - return false; - } - - @Override - public int hashCode() { - return mHashCode; - } - } - - /** - * Determine if two intents are the same for the purposes of intent - * resolution (filtering). That is, if their action, data, type, - * class, and categories are the same. This does <em>not</em> compare - * any extra data included in the intents. - * - * @param other The other Intent to compare against. - * - * @return Returns true if action, data, type, class, and categories - * are the same. - */ - public boolean filterEquals(Intent other) { - if (other == null) { - return false; - } - if (mAction != other.mAction) { - if (mAction != null) { - if (!mAction.equals(other.mAction)) { - return false; - } - } else { - if (!other.mAction.equals(mAction)) { - return false; - } - } - } - if (mData != other.mData) { - if (mData != null) { - if (!mData.equals(other.mData)) { - return false; - } - } else { - if (!other.mData.equals(mData)) { - return false; - } - } - } - if (mType != other.mType) { - if (mType != null) { - if (!mType.equals(other.mType)) { - return false; - } - } else { - if (!other.mType.equals(mType)) { - return false; - } - } - } - if (mComponent != other.mComponent) { - if (mComponent != null) { - if (!mComponent.equals(other.mComponent)) { - return false; - } - } else { - if (!other.mComponent.equals(mComponent)) { - return false; - } - } - } - if (mCategories != other.mCategories) { - if (mCategories != null) { - if (!mCategories.equals(other.mCategories)) { - return false; - } - } else { - if (!other.mCategories.equals(mCategories)) { - return false; - } - } - } - - return true; - } - - /** - * Generate hash code that matches semantics of filterEquals(). - * - * @return Returns the hash value of the action, data, type, class, and - * categories. - * - * @see #filterEquals - */ - public int filterHashCode() { - int code = 0; - if (mAction != null) { - code += mAction.hashCode(); - } - if (mData != null) { - code += mData.hashCode(); - } - if (mType != null) { - code += mType.hashCode(); - } - if (mComponent != null) { - code += mComponent.hashCode(); - } - if (mCategories != null) { - code += mCategories.hashCode(); - } - return code; - } - - @Override - public String toString() { - StringBuilder b = new StringBuilder(); - - b.append("Intent {"); - if (mAction != null) b.append(" action=").append(mAction); - if (mCategories != null) { - b.append(" categories={"); - Iterator<String> i = mCategories.iterator(); - boolean didone = false; - while (i.hasNext()) { - if (didone) b.append(","); - didone = true; - b.append(i.next()); - } - b.append("}"); - } - if (mData != null) b.append(" data=").append(mData); - if (mType != null) b.append(" type=").append(mType); - if (mFlags != 0) b.append(" flags=0x").append(Integer.toHexString(mFlags)); - if (mComponent != null) b.append(" comp=").append(mComponent.toShortString()); - if (mExtras != null) b.append(" (has extras)"); - b.append(" }"); - - return b.toString(); - } - - public String toURI() { - StringBuilder uri = new StringBuilder(mData != null ? mData.toString() : ""); - - uri.append("#Intent;"); - - if (mAction != null) { - uri.append("action=").append(mAction).append(';'); - } - if (mCategories != null) { - for (String category : mCategories) { - uri.append("category=").append(category).append(';'); - } - } - if (mType != null) { - uri.append("type=").append(mType).append(';'); - } - if (mFlags != 0) { - uri.append("launchFlags=0x").append(Integer.toHexString(mFlags)).append(';'); - } - if (mComponent != null) { - uri.append("component=").append(mComponent.flattenToShortString()).append(';'); - } - if (mExtras != null) { - for (String key : mExtras.keySet()) { - final Object value = mExtras.get(key); - char entryType = - value instanceof String ? 'S' : - value instanceof Boolean ? 'B' : - value instanceof Byte ? 'b' : - value instanceof Character ? 'c' : - value instanceof Double ? 'd' : - value instanceof Float ? 'f' : - value instanceof Integer ? 'i' : - value instanceof Long ? 'l' : - value instanceof Short ? 's' : - '\0'; - - if (entryType != '\0') { - uri.append(entryType); - uri.append('.'); - uri.append(Uri.encode(key)); - uri.append('='); - uri.append(Uri.encode(value.toString())); - uri.append(';'); - } - } - } - - uri.append("end"); - - return uri.toString(); - } - - public int describeContents() { - return (mExtras != null) ? mExtras.describeContents() : 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(mAction); - Uri.writeToParcel(out, mData); - out.writeString(mType); - out.writeInt(mFlags); - ComponentName.writeToParcel(mComponent, out); - - if (mCategories != null) { - out.writeInt(mCategories.size()); - for (String category : mCategories) { - out.writeString(category); - } - } else { - out.writeInt(0); - } - - out.writeBundle(mExtras); - } - - public static final Parcelable.Creator<Intent> CREATOR - = new Parcelable.Creator<Intent>() { - public Intent createFromParcel(Parcel in) { - return new Intent(in); - } - public Intent[] newArray(int size) { - return new Intent[size]; - } - }; - - private Intent(Parcel in) { - readFromParcel(in); - } - - public void readFromParcel(Parcel in) { - mAction = in.readString(); - mData = Uri.CREATOR.createFromParcel(in); - mType = in.readString(); - mFlags = in.readInt(); - mComponent = ComponentName.readFromParcel(in); - - int N = in.readInt(); - if (N > 0) { - mCategories = new HashSet<String>(); - int i; - for (i=0; i<N; i++) { - mCategories.add(in.readString()); - } - } else { - mCategories = null; - } - - mExtras = in.readBundle(); - } - - /** - * Parses the "intent" element (and its children) from XML and instantiates - * an Intent object. The given XML parser should be located at the tag - * where parsing should start (often named "intent"), from which the - * basic action, data, type, and package and class name will be - * retrieved. The function will then parse in to any child elements, - * looking for <category android:name="xxx"> tags to add categories and - * <extra android:name="xxx" android:value="yyy"> to attach extra data - * to the intent. - * - * @param resources The Resources to use when inflating resources. - * @param parser The XML parser pointing at an "intent" tag. - * @param attrs The AttributeSet interface for retrieving extended - * attribute data at the current <var>parser</var> location. - * @return An Intent object matching the XML data. - * @throws XmlPullParserException If there was an XML parsing error. - * @throws IOException If there was an I/O error. - */ - public static Intent parseIntent(Resources resources, XmlPullParser parser, AttributeSet attrs) - throws XmlPullParserException, IOException { - Intent intent = new Intent(); - - TypedArray sa = resources.obtainAttributes(attrs, - com.android.internal.R.styleable.Intent); - - intent.setAction(sa.getString(com.android.internal.R.styleable.Intent_action)); - - String data = sa.getString(com.android.internal.R.styleable.Intent_data); - String mimeType = sa.getString(com.android.internal.R.styleable.Intent_mimeType); - intent.setDataAndType(data != null ? Uri.parse(data) : null, mimeType); - - String packageName = sa.getString(com.android.internal.R.styleable.Intent_targetPackage); - String className = sa.getString(com.android.internal.R.styleable.Intent_targetClass); - if (packageName != null && className != null) { - intent.setComponent(new ComponentName(packageName, className)); - } - - sa.recycle(); - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - String nodeName = parser.getName(); - if (nodeName.equals("category")) { - sa = resources.obtainAttributes(attrs, - com.android.internal.R.styleable.IntentCategory); - String cat = sa.getString(com.android.internal.R.styleable.IntentCategory_name); - sa.recycle(); - - if (cat != null) { - intent.addCategory(cat); - } - XmlUtils.skipCurrentTag(parser); - - } else if (nodeName.equals("extra")) { - if (intent.mExtras == null) { - intent.mExtras = new Bundle(); - } - resources.parseBundleExtra("extra", attrs, intent.mExtras); - XmlUtils.skipCurrentTag(parser); - - } else { - XmlUtils.skipCurrentTag(parser); - } - } - - return intent; - } -} diff --git a/core/java/android/content/IntentFilter.aidl b/core/java/android/content/IntentFilter.aidl deleted file mode 100644 index a9bcd5e..0000000 --- a/core/java/android/content/IntentFilter.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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; - -parcelable IntentFilter; diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java deleted file mode 100644 index e81bc86..0000000 --- a/core/java/android/content/IntentFilter.java +++ /dev/null @@ -1,1408 +0,0 @@ -/* - * Copyright (C) 2006 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 org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Set; - -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.PatternMatcher; -import android.util.AndroidException; -import android.util.Config; -import android.util.Log; -import android.util.Printer; -import com.android.internal.util.XmlUtils; - -/** - * Structured description of Intent values to be matched. An IntentFilter can - * match against actions, categories, and data (either via its type, scheme, - * and/or path) in an Intent. It also includes a "priority" value which is - * used to order multiple matching filters. - * - * <p>IntentFilter objects are often created in XML as part of a package's - * {@link android.R.styleable#AndroidManifest AndroidManifest.xml} file, - * using {@link android.R.styleable#AndroidManifestIntentFilter intent-filter} - * tags. - * - * <p>There are three Intent characteristics you can filter on: the - * <em>action</em>, <em>data</em>, and <em>categories</em>. For each of these - * characteristics you can provide - * multiple possible matching values (via {@link #addAction}, - * {@link #addDataType}, {@link #addDataScheme} {@link #addDataAuthority}, - * {@link #addDataPath}, and {@link #addCategory}, respectively). - * For actions, the field - * will not be tested if no values have been given (treating it as a wildcard); - * if no data characteristics are specified, however, then the filter will - * only match intents that contain no data. - * - * <p>The data characteristic is - * itself divided into three attributes: type, scheme, authority, and path. - * Any that are - * specified must match the contents of the Intent. If you specify a scheme - * but no type, only Intent that does not have a type (such as mailto:) will - * match; a content: URI will never match because they always have a MIME type - * that is supplied by their content provider. Specifying a type with no scheme - * has somewhat special meaning: it will match either an Intent with no URI - * field, or an Intent with a content: or file: URI. If you specify neither, - * then only an Intent with no data or type will match. To specify an authority, - * you must also specify one or more schemes that it is associated with. - * To specify a path, you also must specify both one or more authorities and - * one or more schemes it is associated with. - * - * <p>A match is based on the following rules. Note that - * for an IntentFilter to match an Intent, three conditions must hold: - * the <strong>action</strong> and <strong>category</strong> must match, and - * the data (both the <strong>data type</strong> and - * <strong>data scheme+authority+path</strong> if specified) must match. - * - * <p><strong>Action</strong> matches if any of the given values match the - * Intent action, <em>or</em> if no actions were specified in the filter. - * - * <p><strong>Data Type</strong> matches if any of the given values match the - * Intent type. The Intent - * type is determined by calling {@link Intent#resolveType}. A wildcard can be - * used for the MIME sub-type, in both the Intent and IntentFilter, so that the - * type "audio/*" will match "audio/mpeg", "audio/aiff", "audio/*", etc. - * - * <p><strong>Data Scheme</strong> matches if any of the given values match the - * Intent data's scheme. - * The Intent scheme is determined by calling {@link Intent#getData} - * and {@link android.net.Uri#getScheme} on that URI. - * - * <p><strong>Data Authority</strong> matches if any of the given values match - * the Intent's data authority <em>and</em> one of the data scheme's in the filter - * has matched the Intent, <em>or</em> no authories were supplied in the filter. - * The Intent authority is determined by calling - * {@link Intent#getData} and {@link android.net.Uri#getAuthority} on that URI. - * - * <p><strong>Data Path</strong> matches if any of the given values match the - * Intent's data path <em>and</em> both a scheme and authority in the filter - * has matched against the Intent, <em>or</em> no paths were supplied in the - * filter. The Intent authority is determined by calling - * {@link Intent#getData} and {@link android.net.Uri#getPath} on that URI. - * - * <p><strong>Categories</strong> match if <em>all</em> of the categories in - * the Intent match categories given in the filter. Extra categories in the - * filter that are not in the Intent will not cause the match to fail. Note - * that unlike the action, an IntentFilter with no categories - * will only match an Intent that does not have any categories. - */ -public class IntentFilter implements Parcelable { - private static final String SGLOB_STR = "sglob"; - private static final String PREFIX_STR = "prefix"; - private static final String LITERAL_STR = "literal"; - private static final String PATH_STR = "path"; - private static final String PORT_STR = "port"; - private static final String HOST_STR = "host"; - private static final String AUTH_STR = "auth"; - private static final String SCHEME_STR = "scheme"; - private static final String TYPE_STR = "type"; - private static final String CAT_STR = "cat"; - private static final String NAME_STR = "name"; - private static final String ACTION_STR = "action"; - - /** - * The filter {@link #setPriority} value at which system high-priority - * receivers are placed; that is, receivers that should execute before - * application code. Applications should never use filters with this or - * higher priorities. - * - * @see #setPriority - */ - public static final int SYSTEM_HIGH_PRIORITY = 1000; - - /** - * The filter {@link #setPriority} value at which system low-priority - * receivers are placed; that is, receivers that should execute after - * application code. Applications should never use filters with this or - * lower priorities. - * - * @see #setPriority - */ - public static final int SYSTEM_LOW_PRIORITY = -1000; - - /** - * The part of a match constant that describes the category of match - * that occurred. May be either {@link #MATCH_CATEGORY_EMPTY}, - * {@link #MATCH_CATEGORY_SCHEME}, {@link #MATCH_CATEGORY_HOST}, - * {@link #MATCH_CATEGORY_PORT}, - * {@link #MATCH_CATEGORY_PATH}, or {@link #MATCH_CATEGORY_TYPE}. Higher - * values indicate a better match. - */ - public static final int MATCH_CATEGORY_MASK = 0xfff0000; - - /** - * The part of a match constant that applies a quality adjustment to the - * basic category of match. The value {@link #MATCH_ADJUSTMENT_NORMAL} - * is no adjustment; higher numbers than that improve the quality, while - * lower numbers reduce it. - */ - public static final int MATCH_ADJUSTMENT_MASK = 0x000ffff; - - /** - * Quality adjustment applied to the category of match that signifies - * the default, base value; higher numbers improve the quality while - * lower numbers reduce it. - */ - public static final int MATCH_ADJUSTMENT_NORMAL = 0x8000; - - /** - * The filter matched an intent that had no data specified. - */ - public static final int MATCH_CATEGORY_EMPTY = 0x0100000; - /** - * The filter matched an intent with the same data URI scheme. - */ - public static final int MATCH_CATEGORY_SCHEME = 0x0200000; - /** - * The filter matched an intent with the same data URI scheme and - * authority host. - */ - public static final int MATCH_CATEGORY_HOST = 0x0300000; - /** - * The filter matched an intent with the same data URI scheme and - * authority host and port. - */ - public static final int MATCH_CATEGORY_PORT = 0x0400000; - /** - * The filter matched an intent with the same data URI scheme, - * authority, and path. - */ - public static final int MATCH_CATEGORY_PATH = 0x0500000; - /** - * The filter matched an intent with the same data MIME type. - */ - public static final int MATCH_CATEGORY_TYPE = 0x0600000; - - /** - * The filter didn't match due to different MIME types. - */ - public static final int NO_MATCH_TYPE = -1; - /** - * The filter didn't match due to different data URIs. - */ - public static final int NO_MATCH_DATA = -2; - /** - * The filter didn't match due to different actions. - */ - public static final int NO_MATCH_ACTION = -3; - /** - * The filter didn't match because it required one or more categories - * that were not in the Intent. - */ - public static final int NO_MATCH_CATEGORY = -4; - - private int mPriority; - private final ArrayList<String> mActions; - private ArrayList<String> mCategories = null; - private ArrayList<String> mDataSchemes = null; - private ArrayList<AuthorityEntry> mDataAuthorities = null; - private ArrayList<PatternMatcher> mDataPaths = null; - private ArrayList<String> mDataTypes = null; - private boolean mHasPartialTypes = false; - - // These functions are the start of more optimized code for managing - // the string sets... not yet implemented. - - private static int findStringInSet(String[] set, String string, - int[] lengths, int lenPos) { - if (set == null) return -1; - final int N = lengths[lenPos]; - for (int i=0; i<N; i++) { - if (set[i].equals(string)) return i; - } - return -1; - } - - private static String[] addStringToSet(String[] set, String string, - int[] lengths, int lenPos) { - if (findStringInSet(set, string, lengths, lenPos) >= 0) return set; - if (set == null) { - set = new String[2]; - set[0] = string; - lengths[lenPos] = 1; - return set; - } - final int N = lengths[lenPos]; - if (N < set.length) { - set[N] = string; - lengths[lenPos] = N+1; - return set; - } - - String[] newSet = new String[(N*3)/2 + 2]; - System.arraycopy(set, 0, newSet, 0, N); - set = newSet; - set[N] = string; - lengths[lenPos] = N+1; - return set; - } - - private static String[] removeStringFromSet(String[] set, String string, - int[] lengths, int lenPos) { - int pos = findStringInSet(set, string, lengths, lenPos); - if (pos < 0) return set; - final int N = lengths[lenPos]; - if (N > (set.length/4)) { - int copyLen = N-(pos+1); - if (copyLen > 0) { - System.arraycopy(set, pos+1, set, pos, copyLen); - } - set[N-1] = null; - lengths[lenPos] = N-1; - return set; - } - - String[] newSet = new String[set.length/3]; - if (pos > 0) System.arraycopy(set, 0, newSet, 0, pos); - if ((pos+1) < N) System.arraycopy(set, pos+1, newSet, pos, N-(pos+1)); - return newSet; - } - - /** - * This exception is thrown when a given MIME type does not have a valid - * syntax. - */ - public static class MalformedMimeTypeException extends AndroidException { - public MalformedMimeTypeException() { - } - - public MalformedMimeTypeException(String name) { - super(name); - } - }; - - /** - * Create a new IntentFilter instance with a specified action and MIME - * type, where you know the MIME type is correctly formatted. This catches - * the {@link MalformedMimeTypeException} exception that the constructor - * can call and turns it into a runtime exception. - * - * @param action The action to match, i.e. Intent.ACTION_VIEW. - * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person". - * - * @return A new IntentFilter for the given action and type. - * - * @see #IntentFilter(String, String) - */ - public static IntentFilter create(String action, String dataType) { - try { - return new IntentFilter(action, dataType); - } catch (MalformedMimeTypeException e) { - throw new RuntimeException("Bad MIME type", e); - } - } - - /** - * New empty IntentFilter. - */ - public IntentFilter() { - mPriority = 0; - mActions = new ArrayList<String>(); - } - - /** - * New IntentFilter that matches a single action with no data. If - * no data characteristics are subsequently specified, then the - * filter will only match intents that contain no data. - * - * @param action The action to match, i.e. Intent.ACTION_MAIN. - */ - public IntentFilter(String action) { - mPriority = 0; - mActions = new ArrayList<String>(); - addAction(action); - } - - /** - * New IntentFilter that matches a single action and data type. - * - * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is - * not syntactically correct. - * - * @param action The action to match, i.e. Intent.ACTION_VIEW. - * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person". - * - */ - public IntentFilter(String action, String dataType) - throws MalformedMimeTypeException { - mPriority = 0; - mActions = new ArrayList<String>(); - addDataType(dataType); - } - - /** - * New IntentFilter containing a copy of an existing filter. - * - * @param o The original filter to copy. - */ - public IntentFilter(IntentFilter o) { - mPriority = o.mPriority; - mActions = new ArrayList<String>(o.mActions); - if (o.mCategories != null) { - mCategories = new ArrayList<String>(o.mCategories); - } - if (o.mDataTypes != null) { - mDataTypes = new ArrayList<String>(o.mDataTypes); - } - if (o.mDataSchemes != null) { - mDataSchemes = new ArrayList<String>(o.mDataSchemes); - } - if (o.mDataAuthorities != null) { - mDataAuthorities = new ArrayList<AuthorityEntry>(o.mDataAuthorities); - } - if (o.mDataPaths != null) { - mDataPaths = new ArrayList<PatternMatcher>(o.mDataPaths); - } - mHasPartialTypes = o.mHasPartialTypes; - } - - /** - * Modify priority of this filter. The default priority is 0. Positive - * values will be before the default, lower values will be after it. - * Applications must use a value that is larger than - * {@link #SYSTEM_LOW_PRIORITY} and smaller than - * {@link #SYSTEM_HIGH_PRIORITY} . - * - * @param priority The new priority value. - * - * @see #getPriority - * @see #SYSTEM_LOW_PRIORITY - * @see #SYSTEM_HIGH_PRIORITY - */ - public final void setPriority(int priority) { - mPriority = priority; - } - - /** - * Return the priority of this filter. - * - * @return The priority of the filter. - * - * @see #setPriority - */ - public final int getPriority() { - return mPriority; - } - - /** - * Add a new Intent action to match against. If any actions are included - * in the filter, then an Intent's action must be one of those values for - * it to match. If no actions are included, the Intent action is ignored. - * - * @param action Name of the action to match, i.e. Intent.ACTION_VIEW. - */ - public final void addAction(String action) { - if (!mActions.contains(action)) { - mActions.add(action.intern()); - } - } - - /** - * Return the number of actions in the filter. - */ - public final int countActions() { - return mActions.size(); - } - - /** - * Return an action in the filter. - */ - public final String getAction(int index) { - return mActions.get(index); - } - - /** - * Is the given action included in the filter? Note that if the filter - * does not include any actions, false will <em>always</em> be returned. - * - * @param action The action to look for. - * - * @return True if the action is explicitly mentioned in the filter. - */ - public final boolean hasAction(String action) { - return mActions.contains(action); - } - - /** - * Match this filter against an Intent's action. If the filter does not - * specify any actions, the match will always fail. - * - * @param action The desired action to look for. - * - * @return True if the action is listed in the filter or the filter does - * not specify any actions. - */ - public final boolean matchAction(String action) { - if (action == null || mActions == null || mActions.size() == 0) { - return false; - } - return mActions.contains(action); - } - - /** - * Return an iterator over the filter's actions. If there are no actions, - * returns null. - */ - public final Iterator<String> actionsIterator() { - return mActions != null ? mActions.iterator() : null; - } - - /** - * Add a new Intent data type to match against. If any types are - * included in the filter, then an Intent's data must be <em>either</em> - * one of these types <em>or</em> a matching scheme. If no data types - * are included, then an Intent will only match if it specifies no data. - * - * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is - * not syntactically correct. - * - * @param type Name of the data type to match, i.e. "vnd.android.cursor.dir/person". - * - * @see #matchData - */ - public final void addDataType(String type) - throws MalformedMimeTypeException { - final int slashpos = type.indexOf('/'); - final int typelen = type.length(); - if (slashpos > 0 && typelen >= slashpos+2) { - if (mDataTypes == null) mDataTypes = new ArrayList<String>(); - if (typelen == slashpos+2 && type.charAt(slashpos+1) == '*') { - String str = type.substring(0, slashpos); - if (!mDataTypes.contains(str)) { - mDataTypes.add(str.intern()); - } - mHasPartialTypes = true; - } else { - if (!mDataTypes.contains(type)) { - mDataTypes.add(type.intern()); - } - } - return; - } - - throw new MalformedMimeTypeException(type); - } - - /** - * Is the given data type included in the filter? Note that if the filter - * does not include any type, false will <em>always</em> be returned. - * - * @param type The data type to look for. - * - * @return True if the type is explicitly mentioned in the filter. - */ - public final boolean hasDataType(String type) { - return mDataTypes != null && findMimeType(type); - } - - /** - * Return the number of data types in the filter. - */ - public final int countDataTypes() { - return mDataTypes != null ? mDataTypes.size() : 0; - } - - /** - * Return a data type in the filter. - */ - public final String getDataType(int index) { - return mDataTypes.get(index); - } - - /** - * Return an iterator over the filter's data types. - */ - public final Iterator<String> typesIterator() { - return mDataTypes != null ? mDataTypes.iterator() : null; - } - - /** - * Add a new Intent data scheme to match against. If any schemes are - * included in the filter, then an Intent's data must be <em>either</em> - * one of these schemes <em>or</em> a matching data type. If no schemes - * are included, then an Intent will match only if it includes no data. - * - * @param scheme Name of the scheme to match, i.e. "http". - * - * @see #matchData - */ - public final void addDataScheme(String scheme) { - if (mDataSchemes == null) mDataSchemes = new ArrayList<String>(); - if (!mDataSchemes.contains(scheme)) { - mDataSchemes.add(scheme.intern()); - } - } - - /** - * Return the number of data schemes in the filter. - */ - public final int countDataSchemes() { - return mDataSchemes != null ? mDataSchemes.size() : 0; - } - - /** - * Return a data scheme in the filter. - */ - public final String getDataScheme(int index) { - return mDataSchemes.get(index); - } - - /** - * Is the given data scheme included in the filter? Note that if the - * filter does not include any scheme, false will <em>always</em> be - * returned. - * - * @param scheme The data scheme to look for. - * - * @return True if the scheme is explicitly mentioned in the filter. - */ - public final boolean hasDataScheme(String scheme) { - return mDataSchemes != null && mDataSchemes.contains(scheme); - } - - /** - * Return an iterator over the filter's data schemes. - */ - public final Iterator<String> schemesIterator() { - return mDataSchemes != null ? mDataSchemes.iterator() : null; - } - - /** - * This is an entry for a single authority in the Iterator returned by - * {@link #authoritiesIterator()}. - */ - public final static class AuthorityEntry { - private final String mOrigHost; - private final String mHost; - private final boolean mWild; - private final int mPort; - - public AuthorityEntry(String host, String port) { - mOrigHost = host; - mWild = host.length() > 0 && host.charAt(0) == '*'; - mHost = mWild ? host.substring(1).intern() : host; - mPort = port != null ? Integer.parseInt(port) : -1; - } - - AuthorityEntry(Parcel src) { - mOrigHost = src.readString(); - mHost = src.readString(); - mWild = src.readInt() != 0; - mPort = src.readInt(); - } - - void writeToParcel(Parcel dest) { - dest.writeString(mOrigHost); - dest.writeString(mHost); - dest.writeInt(mWild ? 1 : 0); - dest.writeInt(mPort); - } - - public String getHost() { - return mOrigHost; - } - - public int getPort() { - return mPort; - } - - public int match(Uri data) { - String host = data.getHost(); - if (host == null) { - return NO_MATCH_DATA; - } - if (Config.LOGV) Log.v("IntentFilter", - "Match host " + host + ": " + mHost); - if (mWild) { - if (host.length() < mHost.length()) { - return NO_MATCH_DATA; - } - host = host.substring(host.length()-mHost.length()); - } - if (host.compareToIgnoreCase(mHost) != 0) { - return NO_MATCH_DATA; - } - if (mPort >= 0) { - if (mPort != data.getPort()) { - return NO_MATCH_DATA; - } - return MATCH_CATEGORY_PORT; - } - return MATCH_CATEGORY_HOST; - } - }; - - /** - * Add a new Intent data authority to match against. The filter must - * include one or more schemes (via {@link #addDataScheme}) for the - * authority to be considered. If any authorities are - * included in the filter, then an Intent's data must match one of - * them. If no authorities are included, then only the scheme must match. - * - * @param host The host part of the authority to match. May start with a - * single '*' to wildcard the front of the host name. - * @param port Optional port part of the authority to match. If null, any - * port is allowed. - * - * @see #matchData - * @see #addDataScheme - */ - public final void addDataAuthority(String host, String port) { - if (mDataAuthorities == null) mDataAuthorities = - new ArrayList<AuthorityEntry>(); - if (port != null) port = port.intern(); - mDataAuthorities.add(new AuthorityEntry(host.intern(), port)); - } - - /** - * Return the number of data authorities in the filter. - */ - public final int countDataAuthorities() { - return mDataAuthorities != null ? mDataAuthorities.size() : 0; - } - - /** - * Return a data authority in the filter. - */ - public final AuthorityEntry getDataAuthority(int index) { - return mDataAuthorities.get(index); - } - - /** - * Is the given data authority included in the filter? Note that if the - * filter does not include any authorities, false will <em>always</em> be - * returned. - * - * @param data The data whose authority is being looked for. - * - * @return Returns true if the data string matches an authority listed in the - * filter. - */ - public final boolean hasDataAuthority(Uri data) { - return matchDataAuthority(data) >= 0; - } - - /** - * Return an iterator over the filter's data authorities. - */ - public final Iterator<AuthorityEntry> authoritiesIterator() { - return mDataAuthorities != null ? mDataAuthorities.iterator() : null; - } - - /** - * Add a new Intent data oath to match against. The filter must - * include one or more schemes (via {@link #addDataScheme}) <em>and</em> - * one or more authorities (via {@link #addDataAuthority}) for the - * path to be considered. If any paths are - * included in the filter, then an Intent's data must match one of - * them. If no paths are included, then only the scheme/authority must - * match. - * - * <p>The path given here can either be a literal that must directly - * match or match against a prefix, or it can be a simple globbing pattern. - * If the latter, you can use '*' anywhere in the pattern to match zero - * or more instances of the previous character, '.' as a wildcard to match - * any character, and '\' to escape the next character. - * - * @param path Either a raw string that must exactly match the file - * path, or a simple pattern, depending on <var>type</var>. - * @param type Determines how <var>path</var> will be compared to - * determine a match: either {@link PatternMatcher#PATTERN_LITERAL}, - * {@link PatternMatcher#PATTERN_PREFIX}, or - * {@link PatternMatcher#PATTERN_SIMPLE_GLOB}. - * - * @see #matchData - * @see #addDataScheme - * @see #addDataAuthority - */ - public final void addDataPath(String path, int type) { - if (mDataPaths == null) mDataPaths = new ArrayList<PatternMatcher>(); - mDataPaths.add(new PatternMatcher(path.intern(), type)); - } - - /** - * Return the number of data paths in the filter. - */ - public final int countDataPaths() { - return mDataPaths != null ? mDataPaths.size() : 0; - } - - /** - * Return a data path in the filter. - */ - public final PatternMatcher getDataPath(int index) { - return mDataPaths.get(index); - } - - /** - * Is the given data path included in the filter? Note that if the - * filter does not include any paths, false will <em>always</em> be - * returned. - * - * @param data The data path to look for. This is without the scheme - * prefix. - * - * @return True if the data string matches a path listed in the - * filter. - */ - public final boolean hasDataPath(String data) { - if (mDataPaths == null) { - return false; - } - Iterator<PatternMatcher> i = mDataPaths.iterator(); - while (i.hasNext()) { - final PatternMatcher pe = i.next(); - if (pe.match(data)) { - return true; - } - } - return false; - } - - /** - * Return an iterator over the filter's data paths. - */ - public final Iterator<PatternMatcher> pathsIterator() { - return mDataPaths != null ? mDataPaths.iterator() : null; - } - - /** - * Match this intent filter against the given Intent data. This ignores - * the data scheme -- unlike {@link #matchData}, the authority will match - * regardless of whether there is a matching scheme. - * - * @param data The data whose authority is being looked for. - * - * @return Returns either {@link #MATCH_CATEGORY_HOST}, - * {@link #MATCH_CATEGORY_PORT}, {@link #NO_MATCH_DATA}. - */ - public final int matchDataAuthority(Uri data) { - if (mDataAuthorities == null) { - return NO_MATCH_DATA; - } - Iterator<AuthorityEntry> i = mDataAuthorities.iterator(); - while (i.hasNext()) { - final AuthorityEntry ae = i.next(); - int match = ae.match(data); - if (match >= 0) { - return match; - } - } - return NO_MATCH_DATA; - } - - /** - * Match this filter against an Intent's data (type, scheme and path). If - * the filter does not specify any types and does not specify any - * schemes/paths, the match will only succeed if the intent does not - * also specify a type or data. - * - * <p>Note that to match against an authority, you must also specify a base - * scheme the authority is in. To match against a data path, both a scheme - * and authority must be specified. If the filter does not specify any - * types or schemes that it matches against, it is considered to be empty - * (any authority or data path given is ignored, as if it were empty as - * well). - * - * @param type The desired data type to look for, as returned by - * Intent.resolveType(). - * @param scheme The desired data scheme to look for, as returned by - * Intent.getScheme(). - * @param data The full data string to match against, as supplied in - * Intent.data. - * - * @return Returns either a valid match constant (a combination of - * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}), - * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match - * or {@link #NO_MATCH_DATA} if the scheme/path didn't match. - * - * @see #match - */ - public final int matchData(String type, String scheme, Uri data) { - final ArrayList<String> types = mDataTypes; - final ArrayList<String> schemes = mDataSchemes; - final ArrayList<AuthorityEntry> authorities = mDataAuthorities; - final ArrayList<PatternMatcher> paths = mDataPaths; - - int match = MATCH_CATEGORY_EMPTY; - - if (types == null && schemes == null) { - return ((type == null && data == null) - ? (MATCH_CATEGORY_EMPTY+MATCH_ADJUSTMENT_NORMAL) : NO_MATCH_DATA); - } - - if (schemes != null) { - if (schemes.contains(scheme != null ? scheme : "")) { - match = MATCH_CATEGORY_SCHEME; - } else { - return NO_MATCH_DATA; - } - - if (authorities != null) { - int authMatch = matchDataAuthority(data); - if (authMatch >= 0) { - if (paths == null) { - match = authMatch; - } else if (hasDataPath(data.getPath())) { - match = MATCH_CATEGORY_PATH; - } else { - return NO_MATCH_DATA; - } - } else { - return NO_MATCH_DATA; - } - } - } else { - // Special case: match either an Intent with no data URI, - // or with a scheme: URI. This is to give a convenience for - // the common case where you want to deal with data in a - // content provider, which is done by type, and we don't want - // to force everyone to say they handle content: or file: URIs. - if (scheme != null && !"".equals(scheme) - && !"content".equals(scheme) - && !"file".equals(scheme)) { - return NO_MATCH_DATA; - } - } - - if (types != null) { - if (findMimeType(type)) { - match = MATCH_CATEGORY_TYPE; - } else { - return NO_MATCH_TYPE; - } - } else { - // If no MIME types are specified, then we will only match against - // an Intent that does not have a MIME type. - if (type != null) { - return NO_MATCH_TYPE; - } - } - - return match + MATCH_ADJUSTMENT_NORMAL; - } - - /** - * Add a new Intent category to match against. The semantics of - * categories is the opposite of actions -- an Intent includes the - * categories that it requires, all of which must be included in the - * filter in order to match. In other words, adding a category to the - * filter has no impact on matching unless that category is specified in - * the intent. - * - * @param category Name of category to match, i.e. Intent.CATEGORY_EMBED. - */ - public final void addCategory(String category) { - if (mCategories == null) mCategories = new ArrayList<String>(); - if (!mCategories.contains(category)) { - mCategories.add(category.intern()); - } - } - - /** - * Return the number of categories in the filter. - */ - public final int countCategories() { - return mCategories != null ? mCategories.size() : 0; - } - - /** - * Return a category in the filter. - */ - public final String getCategory(int index) { - return mCategories.get(index); - } - - /** - * Is the given category included in the filter? - * - * @param category The category that the filter supports. - * - * @return True if the category is explicitly mentioned in the filter. - */ - public final boolean hasCategory(String category) { - return mCategories != null && mCategories.contains(category); - } - - /** - * Return an iterator over the filter's categories. - */ - public final Iterator<String> categoriesIterator() { - return mCategories != null ? mCategories.iterator() : null; - } - - /** - * Match this filter against an Intent's categories. Each category in - * the Intent must be specified by the filter; if any are not in the - * filter, the match fails. - * - * @param categories The categories included in the intent, as returned by - * Intent.getCategories(). - * - * @return If all categories match (success), null; else the name of the - * first category that didn't match. - */ - public final String matchCategories(Set<String> categories) { - if (categories == null) { - return null; - } - - Iterator<String> it = categories.iterator(); - - if (mCategories == null) { - return it.hasNext() ? it.next() : null; - } - - while (it.hasNext()) { - final String category = it.next(); - if (!mCategories.contains(category)) { - return category; - } - } - - return null; - } - - /** - * Test whether this filter matches the given <var>intent</var>. - * - * @param intent The Intent to compare against. - * @param resolve If true, the intent's type will be resolved by calling - * Intent.resolveType(); otherwise a simple match against - * Intent.type will be performed. - * @param logTag Tag to use in debugging messages. - * - * @return Returns either a valid match constant (a combination of - * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}), - * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match, - * {@link #NO_MATCH_DATA} if the scheme/path didn't match, - * {@link #NO_MATCH_ACTION if the action didn't match, or - * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match. - * - * @return How well the filter matches. Negative if it doesn't match, - * zero or positive positive value if it does with a higher - * value representing a better match. - * - * @see #match(String, String, String, android.net.Uri , Set, String) - */ - public final int match(ContentResolver resolver, Intent intent, - boolean resolve, String logTag) { - String type = resolve ? intent.resolveType(resolver) : intent.getType(); - return match(intent.getAction(), type, intent.getScheme(), - intent.getData(), intent.getCategories(), logTag); - } - - /** - * Test whether this filter matches the given intent data. A match is - * only successful if the actions and categories in the Intent match - * against the filter, as described in {@link IntentFilter}; in that case, - * the match result returned will be as per {@link #matchData}. - * - * @param action The intent action to match against (Intent.getAction). - * @param type The intent type to match against (Intent.resolveType()). - * @param scheme The data scheme to match against (Intent.getScheme()). - * @param data The data URI to match against (Intent.getData()). - * @param categories The categories to match against - * (Intent.getCategories()). - * @param logTag Tag to use in debugging messages. - * - * @return Returns either a valid match constant (a combination of - * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}), - * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match, - * {@link #NO_MATCH_DATA} if the scheme/path didn't match, - * {@link #NO_MATCH_ACTION if the action didn't match, or - * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match. - * - * @see #matchData - * @see Intent#getAction - * @see Intent#resolveType - * @see Intent#getScheme - * @see Intent#getData - * @see Intent#getCategories - */ - public final int match(String action, String type, String scheme, - Uri data, Set<String> categories, String logTag) { - if (action != null && !matchAction(action)) { - if (Config.LOGV) Log.v( - logTag, "No matching action " + action + " for " + this); - return NO_MATCH_ACTION; - } - - int dataMatch = matchData(type, scheme, data); - if (dataMatch < 0) { - if (Config.LOGV) { - if (dataMatch == NO_MATCH_TYPE) { - Log.v(logTag, "No matching type " + type - + " for " + this); - } - if (dataMatch == NO_MATCH_DATA) { - Log.v(logTag, "No matching scheme/path " + data - + " for " + this); - } - } - return dataMatch; - } - - String categoryMatch = matchCategories(categories); - if (categoryMatch != null) { - if (Config.LOGV) Log.v( - logTag, "No matching category " - + categoryMatch + " for " + this); - return NO_MATCH_CATEGORY; - } - - // It would be nice to treat container activities as more - // important than ones that can be embedded, but this is not the way... - if (false) { - if (categories != null) { - dataMatch -= mCategories.size() - categories.size(); - } - } - - return dataMatch; - } - - /** - * Write the contents of the IntentFilter as an XML stream. - */ - public void writeToXml(XmlSerializer serializer) throws IOException { - int N = countActions(); - for (int i=0; i<N; i++) { - serializer.startTag(null, ACTION_STR); - serializer.attribute(null, NAME_STR, mActions.get(i)); - serializer.endTag(null, ACTION_STR); - } - N = countCategories(); - for (int i=0; i<N; i++) { - serializer.startTag(null, CAT_STR); - serializer.attribute(null, NAME_STR, mCategories.get(i)); - serializer.endTag(null, CAT_STR); - } - N = countDataTypes(); - for (int i=0; i<N; i++) { - serializer.startTag(null, TYPE_STR); - String type = mDataTypes.get(i); - if (type.indexOf('/') < 0) type = type + "/*"; - serializer.attribute(null, NAME_STR, type); - serializer.endTag(null, TYPE_STR); - } - N = countDataSchemes(); - for (int i=0; i<N; i++) { - serializer.startTag(null, SCHEME_STR); - serializer.attribute(null, NAME_STR, mDataSchemes.get(i)); - serializer.endTag(null, SCHEME_STR); - } - N = countDataAuthorities(); - for (int i=0; i<N; i++) { - serializer.startTag(null, AUTH_STR); - AuthorityEntry ae = mDataAuthorities.get(i); - serializer.attribute(null, HOST_STR, ae.getHost()); - if (ae.getPort() >= 0) { - serializer.attribute(null, PORT_STR, Integer.toString(ae.getPort())); - } - serializer.endTag(null, AUTH_STR); - } - N = countDataPaths(); - for (int i=0; i<N; i++) { - serializer.startTag(null, PATH_STR); - PatternMatcher pe = mDataPaths.get(i); - switch (pe.getType()) { - case PatternMatcher.PATTERN_LITERAL: - serializer.attribute(null, LITERAL_STR, pe.getPath()); - break; - case PatternMatcher.PATTERN_PREFIX: - serializer.attribute(null, PREFIX_STR, pe.getPath()); - break; - case PatternMatcher.PATTERN_SIMPLE_GLOB: - serializer.attribute(null, SGLOB_STR, pe.getPath()); - break; - } - serializer.endTag(null, PATH_STR); - } - } - - public void readFromXml(XmlPullParser parser) throws XmlPullParserException, - IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG - || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals(ACTION_STR)) { - String name = parser.getAttributeValue(null, NAME_STR); - if (name != null) { - addAction(name); - } - } else if (tagName.equals(CAT_STR)) { - String name = parser.getAttributeValue(null, NAME_STR); - if (name != null) { - addCategory(name); - } - } else if (tagName.equals(TYPE_STR)) { - String name = parser.getAttributeValue(null, NAME_STR); - if (name != null) { - try { - addDataType(name); - } catch (MalformedMimeTypeException e) { - } - } - } else if (tagName.equals(SCHEME_STR)) { - String name = parser.getAttributeValue(null, NAME_STR); - if (name != null) { - addDataScheme(name); - } - } else if (tagName.equals(AUTH_STR)) { - String host = parser.getAttributeValue(null, HOST_STR); - String port = parser.getAttributeValue(null, PORT_STR); - if (host != null) { - addDataAuthority(host, port); - } - } else if (tagName.equals(PATH_STR)) { - String path = parser.getAttributeValue(null, LITERAL_STR); - if (path != null) { - addDataPath(path, PatternMatcher.PATTERN_LITERAL); - } else if ((path=parser.getAttributeValue(null, PREFIX_STR)) != null) { - addDataPath(path, PatternMatcher.PATTERN_PREFIX); - } else if ((path=parser.getAttributeValue(null, SGLOB_STR)) != null) { - addDataPath(path, PatternMatcher.PATTERN_SIMPLE_GLOB); - } - } else { - Log.w("IntentFilter", "Unknown tag parsing IntentFilter: " + tagName); - } - XmlUtils.skipCurrentTag(parser); - } - } - - public void dump(Printer du, String prefix) { - if (mActions.size() > 0) { - Iterator<String> it = mActions.iterator(); - while (it.hasNext()) { - du.println(prefix + "Action: \"" + it.next() + "\""); - } - } - if (mCategories != null) { - Iterator<String> it = mCategories.iterator(); - while (it.hasNext()) { - du.println(prefix + "Category: \"" + it.next() + "\""); - } - } - if (mDataSchemes != null) { - Iterator<String> it = mDataSchemes.iterator(); - while (it.hasNext()) { - du.println(prefix + "Data Scheme: \"" + it.next() + "\""); - } - } - if (mDataAuthorities != null) { - Iterator<AuthorityEntry> it = mDataAuthorities.iterator(); - while (it.hasNext()) { - AuthorityEntry ae = it.next(); - du.println(prefix + "Data Authority: \"" + ae.mHost + "\":" - + ae.mPort + (ae.mWild ? " WILD" : "")); - } - } - if (mDataPaths != null) { - Iterator<PatternMatcher> it = mDataPaths.iterator(); - while (it.hasNext()) { - PatternMatcher pe = it.next(); - du.println(prefix + "Data Path: \"" + pe + "\""); - } - } - if (mDataTypes != null) { - Iterator<String> it = mDataTypes.iterator(); - while (it.hasNext()) { - du.println(prefix + "Data Type: \"" + it.next() + "\""); - } - } - du.println(prefix + "mPriority=" + mPriority - + ", mHasPartialTypes=" + mHasPartialTypes); - } - - public static final Parcelable.Creator<IntentFilter> CREATOR - = new Parcelable.Creator<IntentFilter>() { - public IntentFilter createFromParcel(Parcel source) { - return new IntentFilter(source); - } - - public IntentFilter[] newArray(int size) { - return new IntentFilter[size]; - } - }; - - public final int describeContents() { - return 0; - } - - public final void writeToParcel(Parcel dest, int flags) { - dest.writeStringList(mActions); - if (mCategories != null) { - dest.writeInt(1); - dest.writeStringList(mCategories); - } else { - dest.writeInt(0); - } - if (mDataSchemes != null) { - dest.writeInt(1); - dest.writeStringList(mDataSchemes); - } else { - dest.writeInt(0); - } - if (mDataTypes != null) { - dest.writeInt(1); - dest.writeStringList(mDataTypes); - } else { - dest.writeInt(0); - } - if (mDataAuthorities != null) { - final int N = mDataAuthorities.size(); - dest.writeInt(N); - for (int i=0; i<N; i++) { - mDataAuthorities.get(i).writeToParcel(dest); - } - } else { - dest.writeInt(0); - } - if (mDataPaths != null) { - final int N = mDataPaths.size(); - dest.writeInt(N); - for (int i=0; i<N; i++) { - mDataPaths.get(i).writeToParcel(dest, 0); - } - } else { - dest.writeInt(0); - } - dest.writeInt(mPriority); - dest.writeInt(mHasPartialTypes ? 1 : 0); - } - - /** - * For debugging -- perform a check on the filter, return true if it passed - * or false if it failed. - * - * {@hide} - */ - public boolean debugCheck() { - return true; - - // This code looks for intent filters that do not specify data. - /* - if (mActions != null && mActions.size() == 1 - && mActions.contains(Intent.ACTION_MAIN)) { - return true; - } - - if (mDataTypes == null && mDataSchemes == null) { - Log.w("IntentFilter", "QUESTIONABLE INTENT FILTER:"); - dump(Log.WARN, "IntentFilter", " "); - return false; - } - - return true; - */ - } - - private IntentFilter(Parcel source) { - mActions = new ArrayList<String>(); - source.readStringList(mActions); - if (source.readInt() != 0) { - mCategories = new ArrayList<String>(); - source.readStringList(mCategories); - } - if (source.readInt() != 0) { - mDataSchemes = new ArrayList<String>(); - source.readStringList(mDataSchemes); - } - if (source.readInt() != 0) { - mDataTypes = new ArrayList<String>(); - source.readStringList(mDataTypes); - } - int N = source.readInt(); - if (N > 0) { - mDataAuthorities = new ArrayList<AuthorityEntry>(); - for (int i=0; i<N; i++) { - mDataAuthorities.add(new AuthorityEntry(source)); - } - } - N = source.readInt(); - if (N > 0) { - mDataPaths = new ArrayList<PatternMatcher>(); - for (int i=0; i<N; i++) { - mDataPaths.add(new PatternMatcher(source)); - } - } - mPriority = source.readInt(); - mHasPartialTypes = source.readInt() > 0; - } - - private final boolean findMimeType(String type) { - final ArrayList<String> t = mDataTypes; - - if (type == null) { - return false; - } - - if (t.contains(type)) { - return true; - } - - // Deal with an Intent wanting to match every type in the IntentFilter. - final int typeLength = type.length(); - if (typeLength == 3 && type.equals("*/*")) { - return !t.isEmpty(); - } - - // Deal with this IntentFilter wanting to match every Intent type. - if (mHasPartialTypes && t.contains("*")) { - return true; - } - - final int slashpos = type.indexOf('/'); - if (slashpos > 0) { - if (mHasPartialTypes && t.contains(type.substring(0, slashpos))) { - return true; - } - if (typeLength == slashpos+2 && type.charAt(slashpos+1) == '*') { - // Need to look through all types for one that matches - // our base... - final Iterator<String> it = t.iterator(); - while (it.hasNext()) { - String v = it.next(); - if (type.regionMatches(0, v, 0, slashpos+1)) { - return true; - } - } - } - } - - return false; - } -} diff --git a/core/java/android/content/MutableContextWrapper.java b/core/java/android/content/MutableContextWrapper.java deleted file mode 100644 index 820479c..0000000 --- a/core/java/android/content/MutableContextWrapper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2006 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; - -/** - * Special version of {@link ContextWrapper} that allows the base context to - * be modified after it is initially set. - */ -public class MutableContextWrapper extends ContextWrapper { - public MutableContextWrapper(Context base) { - super(base); - } - - /** - * Change the base context for this ContextWrapper. All calls will then be - * delegated to the base context. Unlike ContextWrapper, the base context - * can be changed even after one is already set. - * - * @param base The new base context for this wrapper. - */ - public void setBaseContext(Context base) { - mBase = base; - } -} diff --git a/core/java/android/content/ReceiverCallNotAllowedException.java b/core/java/android/content/ReceiverCallNotAllowedException.java deleted file mode 100644 index 96b269c..0000000 --- a/core/java/android/content/ReceiverCallNotAllowedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2006 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.util.AndroidRuntimeException; - -/** - * This exception is thrown from {@link Context#registerReceiver} and - * {@link Context#bindService} when these methods are being used from - * an {@link BroadcastReceiver} component. In this case, the component will no - * longer be active upon returning from receiving the Intent, so it is - * not valid to use asynchronous APIs. - */ -public class ReceiverCallNotAllowedException extends AndroidRuntimeException { - public ReceiverCallNotAllowedException(String msg) { - super(msg); - } -} diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java deleted file mode 100644 index 3d89e92..0000000 --- a/core/java/android/content/SearchRecentSuggestionsProvider.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (C) 2008 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.app.SearchManager; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -/** - * This superclass can be used to create a simple search suggestions provider for your application. - * It creates suggestions (as the user types) based on recent queries and/or recent views. - * - * <p>In order to use this class, you must do the following. - * - * <ul> - * <li>Implement and test query search, as described in {@link android.app.SearchManager}. (This - * provider will send any suggested queries via the standard - * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent, which you'll already - * support once you have implemented and tested basic searchability.)</li> - * <li>Create a Content Provider within your application by extending - * {@link android.content.SearchRecentSuggestionsProvider}. The class you create will be - * very simple - typically, it will have only a constructor. But the constructor has a very - * important responsibility: When it calls {@link #setupSuggestions(String, int)}, it - * <i>configures</i> the provider to match the requirements of your searchable activity.</li> - * <li>Create a manifest entry describing your provider. Typically this would be as simple - * as adding the following lines: - * <pre class="prettyprint"> - * <!-- Content provider for search suggestions --> - * <provider android:name="YourSuggestionProviderClass" - * android:authorities="your.suggestion.authority" /></pre> - * </li> - * <li>Please note that you <i>do not</i> instantiate this content provider directly from within - * your code. This is done automatically by the system Content Resolver, when the search dialog - * looks for suggestions.</li> - * <li>In order for the Content Resolver to do this, you must update your searchable activity's - * XML configuration file with information about your content provider. The following additions - * are usually sufficient: - * <pre class="prettyprint"> - * android:searchSuggestAuthority="your.suggestion.authority" - * android:searchSuggestSelection=" ? "</pre> - * </li> - * <li>In your searchable activities, capture any user-generated queries and record them - * for future searches by calling {@link android.provider.SearchRecentSuggestions#saveRecentQuery - * SearchRecentSuggestions.saveRecentQuery()}.</li> - * </ul> - * - * @see android.provider.SearchRecentSuggestions - */ -public class SearchRecentSuggestionsProvider extends ContentProvider { - // debugging support - private static final String TAG = "SuggestionsProvider"; - - // client-provided configuration values - private String mAuthority; - private int mMode; - private boolean mTwoLineDisplay; - - // general database configuration and tables - private SQLiteOpenHelper mOpenHelper; - private static final String sDatabaseName = "suggestions.db"; - private static final String sSuggestions = "suggestions"; - private static final String ORDER_BY = "date DESC"; - private static final String NULL_COLUMN = "query"; - - // Table of database versions. Don't forget to update! - // NOTE: These version values are shifted left 8 bits (x 256) in order to create space for - // a small set of mode bitflags in the version int. - // - // 1 original implementation with queries, and 1 or 2 display columns - // 1->2 added UNIQUE constraint to display1 column - private static final int DATABASE_VERSION = 2 * 256; - - /** - * This mode bit configures the database to record recent queries. <i>required</i> - * - * @see #setupSuggestions(String, int) - */ - public static final int DATABASE_MODE_QUERIES = 1; - /** - * This mode bit configures the database to include a 2nd annotation line with each entry. - * <i>optional</i> - * - * @see #setupSuggestions(String, int) - */ - public static final int DATABASE_MODE_2LINES = 2; - - // Uri and query support - private static final int URI_MATCH_SUGGEST = 1; - - private Uri mSuggestionsUri; - private UriMatcher mUriMatcher; - - private String mSuggestSuggestionClause; - private String[] mSuggestionProjection; - - /** - * Builds the database. This version has extra support for using the version field - * as a mode flags field, and configures the database columns depending on the mode bits - * (features) requested by the extending class. - * - * @hide - */ - private static class DatabaseHelper extends SQLiteOpenHelper { - - private int mNewVersion; - - public DatabaseHelper(Context context, int newVersion) { - super(context, sDatabaseName, null, newVersion); - mNewVersion = newVersion; - } - - @Override - public void onCreate(SQLiteDatabase db) { - StringBuilder builder = new StringBuilder(); - builder.append("CREATE TABLE suggestions (" + - "_id INTEGER PRIMARY KEY" + - ",display1 TEXT UNIQUE ON CONFLICT REPLACE"); - if (0 != (mNewVersion & DATABASE_MODE_2LINES)) { - builder.append(",display2 TEXT"); - } - builder.append(",query TEXT" + - ",date LONG" + - ");"); - db.execSQL(builder.toString()); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS suggestions"); - onCreate(db); - } - } - - /** - * In order to use this class, you must extend it, and call this setup function from your - * constructor. In your application or activities, you must provide the same values when - * you create the {@link android.provider.SearchRecentSuggestions} helper. - * - * @param authority This must match the authority that you've declared in your manifest. - * @param mode You can use mode flags here to determine certain functional aspects of your - * database. Note, this value should not change from run to run, because when it does change, - * your suggestions database may be wiped. - * - * @see #DATABASE_MODE_QUERIES - * @see #DATABASE_MODE_2LINES - */ - protected void setupSuggestions(String authority, int mode) { - if (TextUtils.isEmpty(authority) || - ((mode & DATABASE_MODE_QUERIES) == 0)) { - throw new IllegalArgumentException(); - } - // unpack mode flags - mTwoLineDisplay = (0 != (mode & DATABASE_MODE_2LINES)); - - // saved values - mAuthority = new String(authority); - mMode = mode; - - // derived values - mSuggestionsUri = Uri.parse("content://" + mAuthority + "/suggestions"); - mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - mUriMatcher.addURI(mAuthority, SearchManager.SUGGEST_URI_PATH_QUERY, URI_MATCH_SUGGEST); - - if (mTwoLineDisplay) { - mSuggestSuggestionClause = "display1 LIKE ? OR display2 LIKE ?"; - - mSuggestionProjection = new String [] { - "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT, - "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1, - "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2, - "query AS " + SearchManager.SUGGEST_COLUMN_QUERY, - "_id" - }; - } else { - mSuggestSuggestionClause = "display1 LIKE ?"; - - mSuggestionProjection = new String [] { - "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT, - "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1, - "query AS " + SearchManager.SUGGEST_COLUMN_QUERY, - "_id" - }; - } - - - } - - /** - * This method is provided for use by the ContentResolver. Do not override, or directly - * call from your own code. - */ - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - - final int length = uri.getPathSegments().size(); - if (length != 1) { - throw new IllegalArgumentException("Unknown Uri"); - } - - final String base = uri.getPathSegments().get(0); - int count = 0; - if (base.equals(sSuggestions)) { - count = db.delete(sSuggestions, selection, selectionArgs); - } else { - throw new IllegalArgumentException("Unknown Uri"); - } - getContext().getContentResolver().notifyChange(uri, null); - return count; - } - - /** - * This method is provided for use by the ContentResolver. Do not override, or directly - * call from your own code. - */ - @Override - public String getType(Uri uri) { - if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) { - return SearchManager.SUGGEST_MIME_TYPE; - } - int length = uri.getPathSegments().size(); - if (length >= 1) { - String base = uri.getPathSegments().get(0); - if (base.equals(sSuggestions)) { - if (length == 1) { - return "vnd.android.cursor.dir/suggestion"; - } else if (length == 2) { - return "vnd.android.cursor.item/suggestion"; - } - } - } - throw new IllegalArgumentException("Unknown Uri"); - } - - /** - * This method is provided for use by the ContentResolver. Do not override, or directly - * call from your own code. - */ - @Override - public Uri insert(Uri uri, ContentValues values) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - - int length = uri.getPathSegments().size(); - if (length < 1) { - throw new IllegalArgumentException("Unknown Uri"); - } - // Note: This table has on-conflict-replace semantics, so insert() may actually replace() - long rowID = -1; - String base = uri.getPathSegments().get(0); - Uri newUri = null; - if (base.equals(sSuggestions)) { - if (length == 1) { - rowID = db.insert(sSuggestions, NULL_COLUMN, values); - if (rowID > 0) { - newUri = Uri.withAppendedPath(mSuggestionsUri, String.valueOf(rowID)); - } - } - } - if (rowID < 0) { - throw new IllegalArgumentException("Unknown Uri"); - } - getContext().getContentResolver().notifyChange(newUri, null); - return newUri; - } - - /** - * This method is provided for use by the ContentResolver. Do not override, or directly - * call from your own code. - */ - @Override - public boolean onCreate() { - if (mAuthority == null || mMode == 0) { - throw new IllegalArgumentException("Provider not configured"); - } - int mWorkingDbVersion = DATABASE_VERSION + mMode; - mOpenHelper = new DatabaseHelper(getContext(), mWorkingDbVersion); - - return true; - } - - /** - * This method is provided for use by the ContentResolver. Do not override, or directly - * call from your own code. - */ - // TODO: Confirm no injection attacks here, or rewrite. - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - - // special case for actual suggestions (from search manager) - if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) { - String suggestSelection; - String[] myArgs; - if (TextUtils.isEmpty(selectionArgs[0])) { - suggestSelection = null; - myArgs = null; - } else { - String like = "%" + selectionArgs[0] + "%"; - if (mTwoLineDisplay) { - myArgs = new String [] { like, like }; - } else { - myArgs = new String [] { like }; - } - suggestSelection = mSuggestSuggestionClause; - } - // Suggestions are always performed with the default sort order - Cursor c = db.query(sSuggestions, mSuggestionProjection, - suggestSelection, myArgs, null, null, ORDER_BY, null); - c.setNotificationUri(getContext().getContentResolver(), uri); - return c; - } - - // otherwise process arguments and perform a standard query - int length = uri.getPathSegments().size(); - if (length != 1 && length != 2) { - throw new IllegalArgumentException("Unknown Uri"); - } - - String base = uri.getPathSegments().get(0); - if (!base.equals(sSuggestions)) { - throw new IllegalArgumentException("Unknown Uri"); - } - - String[] useProjection = null; - if (projection != null && projection.length > 0) { - useProjection = new String[projection.length + 1]; - System.arraycopy(projection, 0, useProjection, 0, projection.length); - useProjection[projection.length] = "_id AS _id"; - } - - StringBuilder whereClause = new StringBuilder(256); - if (length == 2) { - whereClause.append("(_id = ").append(uri.getPathSegments().get(1)).append(")"); - } - - // Tack on the user's selection, if present - if (selection != null && selection.length() > 0) { - if (whereClause.length() > 0) { - whereClause.append(" AND "); - } - - whereClause.append('('); - whereClause.append(selection); - whereClause.append(')'); - } - - // And perform the generic query as requested - Cursor c = db.query(base, useProjection, whereClause.toString(), - selectionArgs, null, null, sortOrder, - null); - c.setNotificationUri(getContext().getContentResolver(), uri); - return c; - } - - /** - * This method is provided for use by the ContentResolver. Do not override, or directly - * call from your own code. - */ - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException("Not implemented"); - } - -} diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java deleted file mode 100644 index d115ce4..0000000 --- a/core/java/android/content/ServiceConnection.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2006 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.os.IBinder; - -/** - * Interface for monitoring the state of an application service. See - * {@link android.app.Service} and - * {@link Context#bindService Context.bindService()} for more information. - * <p>Like many callbacks from the system, the methods on this class are called - * from the main thread of your process. - */ -public interface ServiceConnection { - /** - * Called when a connection to the Service has been established, with - * the {@link android.os.IBinder} of the communication channel to the - * Service. - * - * @param name The concrete component name of the service that has - * been connected. - * - * @param service The IBinder of the Service's communication channel, - * which you can now make calls on. - */ - public void onServiceConnected(ComponentName name, IBinder service); - - /** - * Called when a connection to the Service has been lost. This typically - * happens when the process hosting the service has crashed or been killed. - * This does <em>not</em> remove the ServiceConnection itself -- this - * binding to the service will remain active, and you will receive a call - * to {@link #onServiceConnected} when the Service is next running. - * - * @param name The concrete component name of the service whose - * connection has been lost. - */ - public void onServiceDisconnected(ComponentName name); -} diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java deleted file mode 100644 index a15e29e..0000000 --- a/core/java/android/content/SharedPreferences.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2006 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 java.util.Map; - -/** - * Interface for accessing and modifying preference data returned by {@link - * Context#getSharedPreferences}. For any particular set of preferences, - * there is a single instance of this class that all clients share. - * Modifications to the preferences must go through an {@link Editor} object - * to ensure the preference values remain in a consistent state and control - * when they are committed to storage. - * - * <p><em>Note: currently this class does not support use across multiple - * processes. This will be added later.</em> - * - * @see Context#getSharedPreferences - */ -public interface SharedPreferences { - /** - * Interface definition for a callback to be invoked when a shared - * preference is changed. - */ - public interface OnSharedPreferenceChangeListener { - /** - * Called when a shared preference is changed, added, or removed. This - * may be called even if a preference is set to its existing value. - * - * @param sharedPreferences The {@link SharedPreferences} that received - * the change. - * @param key The key of the preference that was changed, added, or - * removed. - */ - void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key); - } - - /** - * Interface used for modifying values in a {@link SharedPreferences} - * object. All changes you make in an editor are batched, and not copied - * back to the original {@link SharedPreferences} or persistent storage - * until you call {@link #commit}. - */ - public interface Editor { - /** - * Set a String value in the preferences editor, to be written back once - * {@link #commit} is called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putString(String key, String value); - - /** - * Set an int value in the preferences editor, to be written back once - * {@link #commit} is called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putInt(String key, int value); - - /** - * Set a long value in the preferences editor, to be written back once - * {@link #commit} is called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putLong(String key, long value); - - /** - * Set a float value in the preferences editor, to be written back once - * {@link #commit} is called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putFloat(String key, float value); - - /** - * Set a boolean value in the preferences editor, to be written back - * once {@link #commit} is called. - * - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor putBoolean(String key, boolean value); - - /** - * Mark in the editor that a preference value should be removed, which - * will be done in the actual preferences once {@link #commit} is - * called. - * - * <p>Note that when committing back to the preferences, all removals - * are done first, regardless of whether you called remove before - * or after put methods on this editor. - * - * @param key The name of the preference to remove. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor remove(String key); - - /** - * Mark in the editor to remove <em>all</em> values from the - * preferences. Once commit is called, the only remaining preferences - * will be any that you have defined in this editor. - * - * <p>Note that when committing back to the preferences, the clear - * is done first, regardless of whether you called clear before - * or after put methods on this editor. - * - * @return Returns a reference to the same Editor object, so you can - * chain put calls together. - */ - Editor clear(); - - /** - * Commit your preferences changes back from this Editor to the - * {@link SharedPreferences} object it is editing. This atomically - * performs the requested modifications, replacing whatever is currently - * in the SharedPreferences. - * - * <p>Note that when two editors are modifying preferences at the same - * time, the last one to call commit wins. - * - * @return Returns true if the new values were successfully written - * to persistent storage. - */ - boolean commit(); - } - - /** - * Retrieve all values from the preferences. - * - * @return Returns a map containing a list of pairs key/value representing - * the preferences. - * - * @throws NullPointerException - */ - Map<String, ?> getAll(); - - /** - * Retrieve a String value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a String. - * - * @throws ClassCastException - */ - String getString(String key, String defValue); - - /** - * Retrieve an int value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * an int. - * - * @throws ClassCastException - */ - int getInt(String key, int defValue); - - /** - * Retrieve a long value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a long. - * - * @throws ClassCastException - */ - long getLong(String key, long defValue); - - /** - * Retrieve a float value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a float. - * - * @throws ClassCastException - */ - float getFloat(String key, float defValue); - - /** - * Retrieve a boolean value from the preferences. - * - * @param key The name of the preference to retrieve. - * @param defValue Value to return if this preference does not exist. - * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that is not - * a boolean. - * - * @throws ClassCastException - */ - boolean getBoolean(String key, boolean defValue); - - /** - * Checks whether the preferences contains a preference. - * - * @param key The name of the preference to check. - * @return Returns true if the preference exists in the preferences, - * otherwise false. - */ - boolean contains(String key); - - /** - * Create a new Editor for these preferences, through which you can make - * modifications to the data in the preferences and atomically commit those - * changes back to the SharedPreferences object. - * - * <p>Note that you <em>must</em> call {@link Editor#commit} to have any - * changes you perform in the Editor actually show up in the - * SharedPreferences. - * - * @return Returns a new instance of the {@link Editor} interface, allowing - * you to modify the values in this SharedPreferences object. - */ - Editor edit(); - - /** - * Registers a callback to be invoked when a change happens to a preference. - * - * @param listener The callback that will run. - * @see #unregisterOnSharedPreferenceChangeListener - */ - void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); - - /** - * Unregisters a previous callback. - * - * @param listener The callback that should be unregistered. - * @see #registerOnSharedPreferenceChangeListener - */ - void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); -} diff --git a/core/java/android/content/SyncAdapter.java b/core/java/android/content/SyncAdapter.java deleted file mode 100644 index 7826e50..0000000 --- a/core/java/android/content/SyncAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2006 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.os.Bundle; -import android.os.RemoteException; - -/** - * @hide - */ -public abstract class SyncAdapter { - private static final String TAG = "SyncAdapter"; - - /** Kernel event log tag. Also listed in data/etc/event-log-tags. */ - public static final int LOG_SYNC_DETAILS = 2743; - - class Transport extends ISyncAdapter.Stub { - public void startSync(ISyncContext syncContext, String account, - Bundle extras) throws RemoteException { - SyncAdapter.this.startSync(new SyncContext(syncContext), account, extras); - } - - public void cancelSync() throws RemoteException { - SyncAdapter.this.cancelSync(); - } - } - - Transport mTransport = new Transport(); - - /** - * Get the Transport object. (note this is package private). - */ - final ISyncAdapter getISyncAdapter() - { - return mTransport; - } - - /** - * Initiate a sync for this account. SyncAdapter-specific parameters may - * be specified in extras, which is guaranteed to not be null. IPC invocations - * of this method and cancelSync() are guaranteed to be serialized. - * - * @param syncContext the ISyncContext used to indicate the progress of the sync. When - * the sync is finished (successfully or not) ISyncContext.onFinished() must be called. - * @param account the account that should be synced - * @param extras SyncAdapter-specific parameters - */ - public abstract void startSync(SyncContext syncContext, String account, Bundle extras); - - /** - * Cancel the most recently initiated sync. Due to race conditions, this may arrive - * after the ISyncContext.onFinished() for that sync was called. IPC invocations - * of this method and startSync() are guaranteed to be serialized. - */ - public abstract void cancelSync(); -} diff --git a/core/java/android/content/SyncContext.java b/core/java/android/content/SyncContext.java deleted file mode 100644 index f4faa04..0000000 --- a/core/java/android/content/SyncContext.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2008 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.os.RemoteException; -import android.os.SystemClock; - -/** - * @hide - */ -public class SyncContext { - private ISyncContext mSyncContext; - private long mLastHeartbeatSendTime; - - private static final long HEARTBEAT_SEND_INTERVAL_IN_MS = 1000; - - public SyncContext(ISyncContext syncContextInterface) { - mSyncContext = syncContextInterface; - mLastHeartbeatSendTime = 0; - } - - /** - * Call to update the status text for this sync. This internally invokes - * {@link #updateHeartbeat}, so it also takes the place of a call to that. - * - * @param message the current status message for this sync - */ - public void setStatusText(String message) { - updateHeartbeat(); - } - - /** - * Call to indicate that the SyncAdapter is making progress. E.g., if this SyncAdapter - * downloads or sends records to/from the server, this may be called after each record - * is downloaded or uploaded. - */ - public void updateHeartbeat() { - final long now = SystemClock.elapsedRealtime(); - if (now < mLastHeartbeatSendTime + HEARTBEAT_SEND_INTERVAL_IN_MS) return; - try { - mLastHeartbeatSendTime = now; - mSyncContext.sendHeartbeat(); - } catch (RemoteException e) { - // this should never happen - } - } - - public void onFinished(SyncResult result) { - try { - mSyncContext.onFinished(result); - } catch (RemoteException e) { - // this should never happen - } - } - - public ISyncContext getISyncContext() { - return mSyncContext; - } -} diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java deleted file mode 100644 index 96470c3..0000000 --- a/core/java/android/content/SyncManager.java +++ /dev/null @@ -1,2175 +0,0 @@ -/* - * Copyright (C) 2008 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 com.google.android.collect.Maps; - -import com.android.internal.R; -import com.android.internal.util.ArrayUtils; - -import android.accounts.AccountMonitor; -import android.accounts.AccountMonitorListener; -import android.app.AlarmManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageManager; -import android.content.pm.PackageManager; -import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.preference.Preference; -import android.preference.PreferenceGroup; -import android.provider.Sync; -import android.provider.Settings; -import android.provider.Sync.History; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.text.format.Time; -import android.util.Config; -import android.util.EventLog; -import android.util.Log; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.Random; -import java.util.Observer; -import java.util.Observable; - -/** - * @hide - */ -class SyncManager { - private static final String TAG = "SyncManager"; - - // used during dumping of the Sync history - private static final long MILLIS_IN_HOUR = 1000 * 60 * 60; - private static final long MILLIS_IN_DAY = MILLIS_IN_HOUR * 24; - private static final long MILLIS_IN_WEEK = MILLIS_IN_DAY * 7; - private static final long MILLIS_IN_4WEEKS = MILLIS_IN_WEEK * 4; - - /** Delay a sync due to local changes this long. In milliseconds */ - private static final long LOCAL_SYNC_DELAY = 30 * 1000; // 30 seconds - - /** - * If a sync takes longer than this and the sync queue is not empty then we will - * cancel it and add it back to the end of the sync queue. In milliseconds. - */ - private static final long MAX_TIME_PER_SYNC = 5 * 60 * 1000; // 5 minutes - - private static final long SYNC_NOTIFICATION_DELAY = 30 * 1000; // 30 seconds - - /** - * When retrying a sync for the first time use this delay. After that - * the retry time will double until it reached MAX_SYNC_RETRY_TIME. - * In milliseconds. - */ - private static final long INITIAL_SYNC_RETRY_TIME_IN_MS = 30 * 1000; // 30 seconds - - /** - * Default the max sync retry time to this value. - */ - private static final long DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; // one hour - - /** - * An error notification is sent if sync of any of the providers has been failing for this long. - */ - private static final long ERROR_NOTIFICATION_DELAY_MS = 1000 * 60 * 10; // 10 minutes - - private static final String SYNC_WAKE_LOCK = "SyncManagerSyncWakeLock"; - private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarmWakeLock"; - - private Context mContext; - private ContentResolver mContentResolver; - - private String mStatusText = ""; - private long mHeartbeatTime = 0; - - private AccountMonitor mAccountMonitor; - - private volatile String[] mAccounts = null; - - volatile private PowerManager.WakeLock mSyncWakeLock; - volatile private PowerManager.WakeLock mHandleAlarmWakeLock; - volatile private boolean mDataConnectionIsConnected = false; - volatile private boolean mStorageIsLow = false; - private Sync.Settings.QueryMap mSyncSettings; - - private final NotificationManager mNotificationMgr; - private AlarmManager mAlarmService = null; - private HandlerThread mSyncThread; - - private volatile IPackageManager mPackageManager; - - private final SyncStorageEngine mSyncStorageEngine; - private final SyncQueue mSyncQueue; - - private ActiveSyncContext mActiveSyncContext = null; - - // set if the sync error indicator should be reported. - private boolean mNeedSyncErrorNotification = false; - // set if the sync active indicator should be reported - private boolean mNeedSyncActiveNotification = false; - - private volatile boolean mSyncPollInitialized; - private final PendingIntent mSyncAlarmIntent; - private final PendingIntent mSyncPollAlarmIntent; - - private BroadcastReceiver mStorageIntentReceiver = - new BroadcastReceiver() { - public void onReceive(Context context, Intent intent) { - ensureContentResolver(); - String action = intent.getAction(); - if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Internal storage is low."); - } - mStorageIsLow = true; - cancelActiveSync(null /* no url */); - } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Internal storage is ok."); - } - mStorageIsLow = false; - sendCheckAlarmsMessage(); - } - } - }; - - private BroadcastReceiver mConnectivityIntentReceiver = - new BroadcastReceiver() { - public void onReceive(Context context, Intent intent) { - NetworkInfo networkInfo = - intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); - NetworkInfo.State state = (networkInfo == null ? NetworkInfo.State.UNKNOWN : - networkInfo.getState()); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "received connectivity action. network info: " + networkInfo); - } - - // only pay attention to the CONNECTED and DISCONNECTED states. - // if connected, we are connected. - // if disconnected, we may not be connected. in some cases, we may be connected on - // a different network. - // e.g., if switching from GPRS to WiFi, we may receive the CONNECTED to WiFi and - // DISCONNECTED for GPRS in any order. if we receive the CONNECTED first, and then - // a DISCONNECTED, we want to make sure we set mDataConnectionIsConnected to true - // since we still have a WiFi connection. - switch (state) { - case CONNECTED: - mDataConnectionIsConnected = true; - break; - case DISCONNECTED: - if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) { - mDataConnectionIsConnected = false; - } else { - mDataConnectionIsConnected = true; - } - break; - default: - // ignore the rest of the states -- leave our boolean alone. - } - if (mDataConnectionIsConnected) { - initializeSyncPoll(); - sendCheckAlarmsMessage(); - } - } - }; - - private static final String ACTION_SYNC_ALARM = "android.content.syncmanager.SYNC_ALARM"; - private static final String SYNC_POLL_ALARM = "android.content.syncmanager.SYNC_POLL_ALARM"; - private final SyncHandler mSyncHandler; - - private static final String[] SYNC_ACTIVE_PROJECTION = new String[]{ - Sync.Active.ACCOUNT, - Sync.Active.AUTHORITY, - Sync.Active.START_TIME, - }; - - private static final String[] SYNC_PENDING_PROJECTION = new String[]{ - Sync.Pending.ACCOUNT, - Sync.Pending.AUTHORITY - }; - - private static final int MAX_SYNC_POLL_DELAY_SECONDS = 36 * 60 * 60; // 36 hours - private static final int MIN_SYNC_POLL_DELAY_SECONDS = 24 * 60 * 60; // 24 hours - - private static final String SYNCMANAGER_PREFS_FILENAME = "/data/system/syncmanager.prefs"; - - public SyncManager(Context context, boolean factoryTest) { - // Initialize the SyncStorageEngine first, before registering observers - // and creating threads and so on; it may fail if the disk is full. - SyncStorageEngine.init(context); - mSyncStorageEngine = SyncStorageEngine.getSingleton(); - mSyncQueue = new SyncQueue(mSyncStorageEngine); - - mContext = context; - - mSyncThread = new HandlerThread("SyncHandlerThread", Process.THREAD_PRIORITY_BACKGROUND); - mSyncThread.start(); - mSyncHandler = new SyncHandler(mSyncThread.getLooper()); - - mPackageManager = null; - - mSyncAlarmIntent = PendingIntent.getBroadcast( - mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0); - - mSyncPollAlarmIntent = PendingIntent.getBroadcast( - mContext, 0 /* ignored */, new Intent(SYNC_POLL_ALARM), 0); - - IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); - context.registerReceiver(mConnectivityIntentReceiver, intentFilter); - - intentFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); - intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); - context.registerReceiver(mStorageIntentReceiver, intentFilter); - - if (!factoryTest) { - mNotificationMgr = (NotificationManager) - context.getSystemService(Context.NOTIFICATION_SERVICE); - context.registerReceiver(new SyncAlarmIntentReceiver(), - new IntentFilter(ACTION_SYNC_ALARM)); - } else { - mNotificationMgr = null; - } - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - mSyncWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, SYNC_WAKE_LOCK); - mSyncWakeLock.setReferenceCounted(false); - - // This WakeLock is used to ensure that we stay awake between the time that we receive - // a sync alarm notification and when we finish processing it. We need to do this - // because we don't do the work in the alarm handler, rather we do it in a message - // handler. - mHandleAlarmWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - HANDLE_SYNC_ALARM_WAKE_LOCK); - mHandleAlarmWakeLock.setReferenceCounted(false); - - if (!factoryTest) { - AccountMonitorListener listener = new AccountMonitorListener() { - public void onAccountsUpdated(String[] accounts) { - final boolean hadAccountsAlready = mAccounts != null; - // copy the accounts into a new array and change mAccounts to point to it - String[] newAccounts = new String[accounts.length]; - System.arraycopy(accounts, 0, newAccounts, 0, accounts.length); - mAccounts = newAccounts; - - // if a sync is in progress yet it is no longer in the accounts list, cancel it - ActiveSyncContext activeSyncContext = mActiveSyncContext; - if (activeSyncContext != null) { - if (!ArrayUtils.contains(newAccounts, - activeSyncContext.mSyncOperation.account)) { - Log.d(TAG, "canceling sync since the account has been removed"); - sendSyncFinishedOrCanceledMessage(activeSyncContext, - null /* no result since this is a cancel */); - } - } - - // we must do this since we don't bother scheduling alarms when - // the accounts are not set yet - sendCheckAlarmsMessage(); - - mSyncStorageEngine.doDatabaseCleanup(accounts); - - if (hadAccountsAlready && mAccounts.length > 0) { - // request a sync so that if the password was changed we will retry any sync - // that failed when it was wrong - startSync(null /* all providers */, null /* no extras */); - } - } - }; - mAccountMonitor = new AccountMonitor(context, listener); - } - } - - private synchronized void initializeSyncPoll() { - if (mSyncPollInitialized) return; - mSyncPollInitialized = true; - - mContext.registerReceiver(new SyncPollAlarmReceiver(), new IntentFilter(SYNC_POLL_ALARM)); - - // load the next poll time from shared preferences - long absoluteAlarmTime = readSyncPollTime(); - - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "initializeSyncPoll: absoluteAlarmTime is " + absoluteAlarmTime); - } - - // Convert absoluteAlarmTime to elapsed realtime. If this time was in the past then - // schedule the poll immediately, if it is too far in the future then cap it at - // MAX_SYNC_POLL_DELAY_SECONDS. - long absoluteNow = System.currentTimeMillis(); - long relativeNow = SystemClock.elapsedRealtime(); - long relativeAlarmTime = relativeNow; - if (absoluteAlarmTime > absoluteNow) { - long delayInMs = absoluteAlarmTime - absoluteNow; - final int maxDelayInMs = MAX_SYNC_POLL_DELAY_SECONDS * 1000; - if (delayInMs > maxDelayInMs) { - delayInMs = MAX_SYNC_POLL_DELAY_SECONDS * 1000; - } - relativeAlarmTime += delayInMs; - } - - // schedule an alarm for the next poll time - scheduleSyncPollAlarm(relativeAlarmTime); - } - - private void scheduleSyncPollAlarm(long relativeAlarmTime) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "scheduleSyncPollAlarm: relativeAlarmTime is " + relativeAlarmTime - + ", now is " + SystemClock.elapsedRealtime() - + ", delay is " + (relativeAlarmTime - SystemClock.elapsedRealtime())); - } - ensureAlarmService(); - mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, relativeAlarmTime, - mSyncPollAlarmIntent); - } - - /** - * Return a random value v that satisfies minValue <= v < maxValue. The difference between - * maxValue and minValue must be less than Integer.MAX_VALUE. - */ - private long jitterize(long minValue, long maxValue) { - Random random = new Random(SystemClock.elapsedRealtime()); - long spread = maxValue - minValue; - if (spread > Integer.MAX_VALUE) { - throw new IllegalArgumentException("the difference between the maxValue and the " - + "minValue must be less than " + Integer.MAX_VALUE); - } - return minValue + random.nextInt((int)spread); - } - - private void handleSyncPollAlarm() { - // determine the next poll time - long delayMs = jitterize(MIN_SYNC_POLL_DELAY_SECONDS, MAX_SYNC_POLL_DELAY_SECONDS) * 1000; - long nextRelativePollTimeMs = SystemClock.elapsedRealtime() + delayMs; - - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "handleSyncPollAlarm: delay " + delayMs); - - // write the absolute time to shared preferences - writeSyncPollTime(System.currentTimeMillis() + delayMs); - - // schedule an alarm for the next poll time - scheduleSyncPollAlarm(nextRelativePollTimeMs); - - // perform a poll - scheduleSync(null /* sync all syncable providers */, new Bundle(), 0 /* no delay */); - } - - private void writeSyncPollTime(long when) { - File f = new File(SYNCMANAGER_PREFS_FILENAME); - DataOutputStream str = null; - try { - str = new DataOutputStream(new FileOutputStream(f)); - str.writeLong(when); - } catch (FileNotFoundException e) { - Log.w(TAG, "error writing to file " + f, e); - } catch (IOException e) { - Log.w(TAG, "error writing to file " + f, e); - } finally { - if (str != null) { - try { - str.close(); - } catch (IOException e) { - Log.w(TAG, "error closing file " + f, e); - } - } - } - } - - private long readSyncPollTime() { - File f = new File(SYNCMANAGER_PREFS_FILENAME); - - DataInputStream str = null; - try { - str = new DataInputStream(new FileInputStream(f)); - return str.readLong(); - } catch (FileNotFoundException e) { - writeSyncPollTime(0); - } catch (IOException e) { - Log.w(TAG, "error reading file " + f, e); - } finally { - if (str != null) { - try { - str.close(); - } catch (IOException e) { - Log.w(TAG, "error closing file " + f, e); - } - } - } - return 0; - } - - public ActiveSyncContext getActiveSyncContext() { - return mActiveSyncContext; - } - - private Sync.Settings.QueryMap getSyncSettings() { - if (mSyncSettings == null) { - mSyncSettings = new Sync.Settings.QueryMap(mContext.getContentResolver(), true, - new Handler()); - mSyncSettings.addObserver(new Observer(){ - public void update(Observable o, Object arg) { - // force the sync loop to run if the settings change - sendCheckAlarmsMessage(); - } - }); - } - return mSyncSettings; - } - - private void ensureContentResolver() { - if (mContentResolver == null) { - mContentResolver = mContext.getContentResolver(); - } - } - - private void ensureAlarmService() { - if (mAlarmService == null) { - mAlarmService = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); - } - } - - public String getSyncingAccount() { - ActiveSyncContext activeSyncContext = mActiveSyncContext; - return (activeSyncContext != null) ? activeSyncContext.mSyncOperation.account : null; - } - - /** - * Returns whether or not sync is enabled. Sync can be enabled by - * setting the system property "ro.config.sync" to the value "yes". - * This is normally done at boot time on builds that support sync. - * @return true if sync is enabled - */ - private boolean isSyncEnabled() { - // Require the precise value "yes" to discourage accidental activation. - return "yes".equals(SystemProperties.get("ro.config.sync")); - } - - /** - * Initiate a sync. This can start a sync for all providers - * (pass null to url, set onlyTicklable to false), only those - * providers that are marked as ticklable (pass null to url, - * set onlyTicklable to true), or a specific provider (set url - * to the content url of the provider). - * - * <p>If the ContentResolver.SYNC_EXTRAS_UPLOAD boolean in extras is - * true then initiate a sync that just checks for local changes to send - * to the server, otherwise initiate a sync that first gets any - * changes from the server before sending local changes back to - * the server. - * - * <p>If a specific provider is being synced (the url is non-null) - * then the extras can contain SyncAdapter-specific information - * to control what gets synced (e.g. which specific feed to sync). - * - * <p>You'll start getting callbacks after this. - * - * @param url The Uri of a specific provider to be synced, or - * null to sync all providers. - * @param extras a Map of SyncAdapter-specific information to control -* syncs of a specific provider. Can be null. Is ignored -* if the url is null. - * @param delay how many milliseconds in the future to wait before performing this - * sync. -1 means to make this the next sync to perform. - */ - public void scheduleSync(Uri url, Bundle extras, long delay) { - boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); - if (isLoggable) { - Log.v(TAG, "scheduleSync:" - + " delay " + delay - + ", url " + ((url == null) ? "(null)" : url) - + ", extras " + ((extras == null) ? "(null)" : extras)); - } - - if (!isSyncEnabled()) { - if (isLoggable) { - Log.v(TAG, "not syncing because sync is disabled"); - } - setStatusText("Sync is disabled."); - return; - } - - if (mAccounts == null) setStatusText("The accounts aren't known yet."); - if (!mDataConnectionIsConnected) setStatusText("No data connection"); - if (mStorageIsLow) setStatusText("Memory low"); - - if (extras == null) extras = new Bundle(); - - Boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false); - if (expedited) { - delay = -1; // this means schedule at the front of the queue - } - - String[] accounts; - String accountFromExtras = extras.getString(ContentResolver.SYNC_EXTRAS_ACCOUNT); - if (!TextUtils.isEmpty(accountFromExtras)) { - accounts = new String[]{accountFromExtras}; - } else { - // if the accounts aren't configured yet then we can't support an account-less - // sync request - accounts = mAccounts; - if (accounts == null) { - // not ready yet - if (isLoggable) { - Log.v(TAG, "scheduleSync: no accounts yet, dropping"); - } - return; - } - if (accounts.length == 0) { - if (isLoggable) { - Log.v(TAG, "scheduleSync: no accounts configured, dropping"); - } - setStatusText("No accounts are configured."); - return; - } - } - - final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false); - final boolean force = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false); - - int source; - if (uploadOnly) { - source = Sync.History.SOURCE_LOCAL; - } else if (force) { - source = Sync.History.SOURCE_USER; - } else if (url == null) { - source = Sync.History.SOURCE_POLL; - } else { - // this isn't strictly server, since arbitrary callers can (and do) request - // a non-forced two-way sync on a specific url - source = Sync.History.SOURCE_SERVER; - } - - List<String> names = new ArrayList<String>(); - List<ProviderInfo> providers = new ArrayList<ProviderInfo>(); - populateProvidersList(url, names, providers); - - final int numProviders = providers.size(); - for (int i = 0; i < numProviders; i++) { - if (!providers.get(i).isSyncable) continue; - final String name = names.get(i); - for (String account : accounts) { - scheduleSyncOperation(new SyncOperation(account, source, name, extras, delay)); - // TODO: remove this when Calendar supports multiple accounts. Until then - // pretend that only the first account exists when syncing calendar. - if ("calendar".equals(name)) { - break; - } - } - } - } - - private void setStatusText(String message) { - mStatusText = message; - } - - private void populateProvidersList(Uri url, List<String> names, List<ProviderInfo> providers) { - try { - final IPackageManager packageManager = getPackageManager(); - if (url == null) { - packageManager.querySyncProviders(names, providers); - } else { - final String authority = url.getAuthority(); - ProviderInfo info = packageManager.resolveContentProvider(url.getAuthority(), 0); - if (info != null) { - // only set this provider if the requested authority is the primary authority - String[] providerNames = info.authority.split(";"); - if (url.getAuthority().equals(providerNames[0])) { - names.add(authority); - providers.add(info); - } - } - } - } catch (RemoteException ex) { - // we should really never get this, but if we do then clear the lists, which - // will result in the dropping of the sync request - Log.e(TAG, "error trying to get the ProviderInfo for " + url, ex); - names.clear(); - providers.clear(); - } - } - - public void scheduleLocalSync(Uri url) { - final Bundle extras = new Bundle(); - extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true); - scheduleSync(url, extras, LOCAL_SYNC_DELAY); - } - - private IPackageManager getPackageManager() { - // Don't bother synchronizing on this. The worst that can happen is that two threads - // can try to get the package manager at the same time but only one result gets - // used. Since there is only one package manager in the system this doesn't matter. - if (mPackageManager == null) { - IBinder b = ServiceManager.getService("package"); - mPackageManager = IPackageManager.Stub.asInterface(b); - } - return mPackageManager; - } - - /** - * Initiate a sync for this given URL, or pass null for a full sync. - * - * <p>You'll start getting callbacks after this. - * - * @param url The Uri of a specific provider to be synced, or - * null to sync all providers. - * @param extras a Map of SyncAdapter specific information to control - * syncs of a specific provider. Can be null. Is ignored - */ - public void startSync(Uri url, Bundle extras) { - scheduleSync(url, extras, 0 /* no delay */); - } - - public void updateHeartbeatTime() { - mHeartbeatTime = SystemClock.elapsedRealtime(); - ensureContentResolver(); - mContentResolver.notifyChange(Sync.Active.CONTENT_URI, - null /* this change wasn't made through an observer */); - } - - private void sendSyncAlarmMessage() { - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_ALARM"); - mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_SYNC_ALARM); - } - - private void sendCheckAlarmsMessage() { - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_CHECK_ALARMS"); - mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS); - } - - private void sendSyncFinishedOrCanceledMessage(ActiveSyncContext syncContext, - SyncResult syncResult) { - if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_FINISHED"); - Message msg = mSyncHandler.obtainMessage(); - msg.what = SyncHandler.MESSAGE_SYNC_FINISHED; - msg.obj = new SyncHandlerMessagePayload(syncContext, syncResult); - mSyncHandler.sendMessage(msg); - } - - class SyncHandlerMessagePayload { - public final ActiveSyncContext activeSyncContext; - public final SyncResult syncResult; - - SyncHandlerMessagePayload(ActiveSyncContext syncContext, SyncResult syncResult) { - this.activeSyncContext = syncContext; - this.syncResult = syncResult; - } - } - - class SyncAlarmIntentReceiver extends BroadcastReceiver { - public void onReceive(Context context, Intent intent) { - mHandleAlarmWakeLock.acquire(); - sendSyncAlarmMessage(); - } - } - - class SyncPollAlarmReceiver extends BroadcastReceiver { - public void onReceive(Context context, Intent intent) { - handleSyncPollAlarm(); - } - } - - private void rescheduleImmediately(SyncOperation syncOperation) { - SyncOperation rescheduledSyncOperation = new SyncOperation(syncOperation); - rescheduledSyncOperation.setDelay(0); - scheduleSyncOperation(rescheduledSyncOperation); - } - - private long rescheduleWithDelay(SyncOperation syncOperation) { - long newDelayInMs; - - if (syncOperation.delay == 0) { - // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS - newDelayInMs = jitterize(INITIAL_SYNC_RETRY_TIME_IN_MS, - (long)(INITIAL_SYNC_RETRY_TIME_IN_MS * 1.1)); - } else { - // Subsequent delays are the double of the previous delay - newDelayInMs = syncOperation.delay * 2; - } - - // Cap the delay - ensureContentResolver(); - long maxSyncRetryTimeInSeconds = Settings.Gservices.getLong(mContentResolver, - Settings.Gservices.SYNC_MAX_RETRY_DELAY_IN_SECONDS, - DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS); - if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) { - newDelayInMs = maxSyncRetryTimeInSeconds * 1000; - } - - SyncOperation rescheduledSyncOperation = new SyncOperation(syncOperation); - rescheduledSyncOperation.setDelay(newDelayInMs); - scheduleSyncOperation(rescheduledSyncOperation); - return newDelayInMs; - } - - /** - * Cancel the active sync if it matches the uri. The uri corresponds to the one passed - * in to startSync(). - * @param uri If non-null, the active sync is only canceled if it matches the uri. - * If null, any active sync is canceled. - */ - public void cancelActiveSync(Uri uri) { - ActiveSyncContext activeSyncContext = mActiveSyncContext; - if (activeSyncContext != null) { - // if a Uri was specified then only cancel the sync if it matches the the uri - if (uri != null) { - if (!uri.getAuthority().equals(activeSyncContext.mSyncOperation.authority)) { - return; - } - } - sendSyncFinishedOrCanceledMessage(activeSyncContext, - null /* no result since this is a cancel */); - } - } - - /** - * Create and schedule a SyncOperation. - * - * @param syncOperation the SyncOperation to schedule - */ - public void scheduleSyncOperation(SyncOperation syncOperation) { - // If this operation is expedited and there is a sync in progress then - // reschedule the current operation and send a cancel for it. - final boolean expedited = syncOperation.delay < 0; - final ActiveSyncContext activeSyncContext = mActiveSyncContext; - if (expedited && activeSyncContext != null) { - final boolean activeIsExpedited = activeSyncContext.mSyncOperation.delay < 0; - final boolean hasSameKey = - activeSyncContext.mSyncOperation.key.equals(syncOperation.key); - // This request is expedited and there is a sync in progress. - // Interrupt the current sync only if it is not expedited and if it has a different - // key than the one we are scheduling. - if (!activeIsExpedited && !hasSameKey) { - rescheduleImmediately(activeSyncContext.mSyncOperation); - sendSyncFinishedOrCanceledMessage(activeSyncContext, - null /* no result since this is a cancel */); - } - } - - boolean operationEnqueued; - synchronized (mSyncQueue) { - operationEnqueued = mSyncQueue.add(syncOperation); - } - - if (operationEnqueued) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "scheduleSyncOperation: enqueued " + syncOperation); - } - sendCheckAlarmsMessage(); - } else { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "scheduleSyncOperation: dropping duplicate sync operation " - + syncOperation); - } - } - } - - /** - * Remove any scheduled sync operations that match uri. The uri corresponds to the one passed - * in to startSync(). - * @param uri If non-null, only operations that match the uri are cleared. - * If null, all operations are cleared. - */ - public void clearScheduledSyncOperations(Uri uri) { - synchronized (mSyncQueue) { - mSyncQueue.clear(null, uri != null ? uri.getAuthority() : null); - } - } - - void maybeRescheduleSync(SyncResult syncResult, SyncOperation previousSyncOperation) { - boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG); - if (isLoggable) { - Log.d(TAG, "encountered error(s) during the sync: " + syncResult + ", " - + previousSyncOperation); - } - - // If the operation succeeded to some extent then retry immediately. - // If this was a two-way sync then retry soft errors with an exponential backoff. - // If this was an upward sync then schedule a two-way sync immediately. - // Otherwise do not reschedule. - - if (syncResult.madeSomeProgress()) { - if (isLoggable) { - Log.d(TAG, "retrying sync operation immediately because " - + "even though it had an error it achieved some success"); - } - rescheduleImmediately(previousSyncOperation); - } else if (previousSyncOperation.extras.getBoolean( - ContentResolver.SYNC_EXTRAS_UPLOAD, false)) { - final SyncOperation newSyncOperation = new SyncOperation(previousSyncOperation); - newSyncOperation.extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false); - newSyncOperation.setDelay(0); - if (Config.LOGD) { - Log.d(TAG, "retrying sync operation as a two-way sync because an upload-only sync " - + "encountered an error: " + previousSyncOperation); - } - scheduleSyncOperation(newSyncOperation); - } else if (syncResult.hasSoftError()) { - long delay = rescheduleWithDelay(previousSyncOperation); - if (delay >= 0) { - if (isLoggable) { - Log.d(TAG, "retrying sync operation in " + delay + " ms because " - + "it encountered a soft error: " + previousSyncOperation); - } - } - } else { - if (Config.LOGD) { - Log.d(TAG, "not retrying sync operation because the error is a hard error: " - + previousSyncOperation); - } - } - } - - /** - * Value type that represents a sync operation. - */ - static class SyncOperation implements Comparable { - final String account; - int syncSource; - String authority; - Bundle extras; - final String key; - long earliestRunTime; - long delay; - Long rowId = null; - - SyncOperation(String account, int source, String authority, Bundle extras, long delay) { - this.account = account; - this.syncSource = source; - this.authority = authority; - this.extras = new Bundle(extras); - this.setDelay(delay); - this.key = toKey(); - } - - SyncOperation(SyncOperation other) { - this.account = other.account; - this.syncSource = other.syncSource; - this.authority = other.authority; - this.extras = new Bundle(other.extras); - this.delay = other.delay; - this.earliestRunTime = other.earliestRunTime; - this.key = toKey(); - } - - public void setDelay(long delay) { - this.delay = delay; - if (delay >= 0) { - this.earliestRunTime = SystemClock.elapsedRealtime() + delay; - } else { - this.earliestRunTime = 0; - } - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("authority: ").append(authority); - sb.append(" account: ").append(account); - sb.append(" extras: "); - extrasToStringBuilder(extras, sb); - sb.append(" syncSource: ").append(syncSource); - sb.append(" when: ").append(earliestRunTime); - sb.append(" delay: ").append(delay); - sb.append(" key: {").append(key).append("}"); - if (rowId != null) sb.append(" rowId: ").append(rowId); - return sb.toString(); - } - - private String toKey() { - StringBuilder sb = new StringBuilder(); - sb.append("authority: ").append(authority); - sb.append(" account: ").append(account); - sb.append(" extras: "); - extrasToStringBuilder(extras, sb); - return sb.toString(); - } - - private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) { - sb.append("["); - for (String key : bundle.keySet()) { - sb.append(key).append("=").append(bundle.get(key)).append(" "); - } - sb.append("]"); - } - - public int compareTo(Object o) { - SyncOperation other = (SyncOperation)o; - if (earliestRunTime == other.earliestRunTime) { - return 0; - } - return (earliestRunTime < other.earliestRunTime) ? -1 : 1; - } - } - - /** - * @hide - */ - class ActiveSyncContext extends ISyncContext.Stub { - final SyncOperation mSyncOperation; - final long mHistoryRowId; - final IContentProvider mContentProvider; - final ISyncAdapter mSyncAdapter; - final long mStartTime; - long mTimeoutStartTime; - - public ActiveSyncContext(SyncOperation syncOperation, IContentProvider contentProvider, - ISyncAdapter syncAdapter, long historyRowId) { - super(); - mSyncOperation = syncOperation; - mHistoryRowId = historyRowId; - mContentProvider = contentProvider; - mSyncAdapter = syncAdapter; - mStartTime = SystemClock.elapsedRealtime(); - mTimeoutStartTime = mStartTime; - } - - public void sendHeartbeat() { - // ignore this call if it corresponds to an old sync session - if (mActiveSyncContext == this) { - SyncManager.this.updateHeartbeatTime(); - } - } - - public void onFinished(SyncResult result) { - // include "this" in the message so that the handler can ignore it if this - // ActiveSyncContext is no longer the mActiveSyncContext at message handling - // time - sendSyncFinishedOrCanceledMessage(this, result); - } - - public void toString(StringBuilder sb) { - sb.append("startTime ").append(mStartTime) - .append(", mTimeoutStartTime ").append(mTimeoutStartTime) - .append(", mHistoryRowId ").append(mHistoryRowId) - .append(", syncOperation ").append(mSyncOperation); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - toString(sb); - return sb.toString(); - } - } - - protected void dump(FileDescriptor fd, PrintWriter pw) { - StringBuilder sb = new StringBuilder(); - dumpSyncState(sb); - sb.append("\n"); - if (isSyncEnabled()) { - dumpSyncHistory(sb); - } - pw.println(sb.toString()); - } - - protected void dumpSyncState(StringBuilder sb) { - sb.append("sync enabled: ").append(isSyncEnabled()).append("\n"); - sb.append("data connected: ").append(mDataConnectionIsConnected).append("\n"); - sb.append("memory low: ").append(mStorageIsLow).append("\n"); - - final String[] accounts = mAccounts; - sb.append("accounts: "); - if (accounts != null) { - sb.append(accounts.length); - } else { - sb.append("none"); - } - sb.append("\n"); - final long now = SystemClock.elapsedRealtime(); - sb.append("now: ").append(now).append("\n"); - sb.append("uptime: ").append(DateUtils.formatElapsedTime(now/1000)).append(" (HH:MM:SS)\n"); - sb.append("time spent syncing : ") - .append(DateUtils.formatElapsedTime( - mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000)) - .append(" (HH:MM:SS), sync ") - .append(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ") - .append("in progress").append("\n"); - if (mSyncHandler.mAlarmScheduleTime != null) { - sb.append("next alarm time: ").append(mSyncHandler.mAlarmScheduleTime) - .append(" (") - .append(DateUtils.formatElapsedTime((mSyncHandler.mAlarmScheduleTime-now)/1000)) - .append(" (HH:MM:SS) from now)\n"); - } else { - sb.append("no alarm is scheduled (there had better not be any pending syncs)\n"); - } - - sb.append("active sync: ").append(mActiveSyncContext).append("\n"); - - sb.append("notification info: "); - mSyncHandler.mSyncNotificationInfo.toString(sb); - sb.append("\n"); - - synchronized (mSyncQueue) { - sb.append("sync queue: "); - mSyncQueue.dump(sb); - } - - Cursor c = mSyncStorageEngine.query(Sync.Active.CONTENT_URI, - SYNC_ACTIVE_PROJECTION, null, null, null); - sb.append("\n"); - try { - if (c.moveToNext()) { - final long durationInSeconds = (now - c.getLong(2)) / 1000; - sb.append("Active sync: ").append(c.getString(0)) - .append(" ").append(c.getString(1)) - .append(", duration is ") - .append(DateUtils.formatElapsedTime(durationInSeconds)).append(".\n"); - } else { - sb.append("No sync is in progress.\n"); - } - } finally { - c.close(); - } - - c = mSyncStorageEngine.query(Sync.Pending.CONTENT_URI, - SYNC_PENDING_PROJECTION, null, null, "account, authority"); - sb.append("\nPending Syncs\n"); - try { - if (c.getCount() != 0) { - dumpSyncPendingHeader(sb); - while (c.moveToNext()) { - dumpSyncPendingRow(sb, c); - } - dumpSyncPendingFooter(sb); - } else { - sb.append("none\n"); - } - } finally { - c.close(); - } - - String currentAccount = null; - c = mSyncStorageEngine.query(Sync.Status.CONTENT_URI, - STATUS_PROJECTION, null, null, "account, authority"); - sb.append("\nSync history by account and authority\n"); - try { - while (c.moveToNext()) { - if (!TextUtils.equals(currentAccount, c.getString(0))) { - if (currentAccount != null) { - dumpSyncHistoryFooter(sb); - } - currentAccount = c.getString(0); - dumpSyncHistoryHeader(sb, currentAccount); - } - - dumpSyncHistoryRow(sb, c); - } - if (c.getCount() > 0) dumpSyncHistoryFooter(sb); - } finally { - c.close(); - } - } - - private void dumpSyncHistoryHeader(StringBuilder sb, String account) { - sb.append(" Account: ").append(account).append("\n"); - sb.append(" ___________________________________________________________________________________________________________________________\n"); - sb.append(" | | num times synced | total | last success | |\n"); - sb.append(" | authority | local | poll | server | user | total | duration | source | time | result if failing |\n"); - } - - private static String[] STATUS_PROJECTION = new String[]{ - Sync.Status.ACCOUNT, // 0 - Sync.Status.AUTHORITY, // 1 - Sync.Status.NUM_SYNCS, // 2 - Sync.Status.TOTAL_ELAPSED_TIME, // 3 - Sync.Status.NUM_SOURCE_LOCAL, // 4 - Sync.Status.NUM_SOURCE_POLL, // 5 - Sync.Status.NUM_SOURCE_SERVER, // 6 - Sync.Status.NUM_SOURCE_USER, // 7 - Sync.Status.LAST_SUCCESS_SOURCE, // 8 - Sync.Status.LAST_SUCCESS_TIME, // 9 - Sync.Status.LAST_FAILURE_SOURCE, // 10 - Sync.Status.LAST_FAILURE_TIME, // 11 - Sync.Status.LAST_FAILURE_MESG // 12 - }; - - private void dumpSyncHistoryRow(StringBuilder sb, Cursor c) { - boolean hasSuccess = !c.isNull(9); - boolean hasFailure = !c.isNull(11); - Time timeSuccess = new Time(); - if (hasSuccess) timeSuccess.set(c.getLong(9)); - Time timeFailure = new Time(); - if (hasFailure) timeFailure.set(c.getLong(11)); - sb.append(String.format(" | %-15s | %5d | %5d | %6d | %5d | %5d | %8s | %7s | %19s | %19s |\n", - c.getString(1), - c.getLong(4), - c.getLong(5), - c.getLong(6), - c.getLong(7), - c.getLong(2), - DateUtils.formatElapsedTime(c.getLong(3)/1000), - hasSuccess ? Sync.History.SOURCES[c.getInt(8)] : "", - hasSuccess ? timeSuccess.format("%Y-%m-%d %H:%M:%S") : "", - hasFailure ? History.mesgToString(c.getString(12)) : "")); - } - - private void dumpSyncHistoryFooter(StringBuilder sb) { - sb.append(" |___________________________________________________________________________________________________________________________|\n"); - } - - private void dumpSyncPendingHeader(StringBuilder sb) { - sb.append(" ____________________________________________________\n"); - sb.append(" | account | authority |\n"); - } - - private void dumpSyncPendingRow(StringBuilder sb, Cursor c) { - sb.append(String.format(" | %-30s | %-15s |\n", c.getString(0), c.getString(1))); - } - - private void dumpSyncPendingFooter(StringBuilder sb) { - sb.append(" |__________________________________________________|\n"); - } - - protected void dumpSyncHistory(StringBuilder sb) { - Cursor c = mSyncStorageEngine.query(Sync.History.CONTENT_URI, null, "event=?", - new String[]{String.valueOf(Sync.History.EVENT_STOP)}, - Sync.HistoryColumns.EVENT_TIME + " desc"); - try { - long numSyncsLastHour = 0, durationLastHour = 0; - long numSyncsLastDay = 0, durationLastDay = 0; - long numSyncsLastWeek = 0, durationLastWeek = 0; - long numSyncsLast4Weeks = 0, durationLast4Weeks = 0; - long numSyncsTotal = 0, durationTotal = 0; - - long now = System.currentTimeMillis(); - int indexEventTime = c.getColumnIndexOrThrow(Sync.History.EVENT_TIME); - int indexElapsedTime = c.getColumnIndexOrThrow(Sync.History.ELAPSED_TIME); - while (c.moveToNext()) { - long duration = c.getLong(indexElapsedTime); - long endTime = c.getLong(indexEventTime) + duration; - long millisSinceStart = now - endTime; - numSyncsTotal++; - durationTotal += duration; - if (millisSinceStart < MILLIS_IN_HOUR) { - numSyncsLastHour++; - durationLastHour += duration; - } - if (millisSinceStart < MILLIS_IN_DAY) { - numSyncsLastDay++; - durationLastDay += duration; - } - if (millisSinceStart < MILLIS_IN_WEEK) { - numSyncsLastWeek++; - durationLastWeek += duration; - } - if (millisSinceStart < MILLIS_IN_4WEEKS) { - numSyncsLast4Weeks++; - durationLast4Weeks += duration; - } - } - dumpSyncIntervalHeader(sb); - dumpSyncInterval(sb, "hour", MILLIS_IN_HOUR, numSyncsLastHour, durationLastHour); - dumpSyncInterval(sb, "day", MILLIS_IN_DAY, numSyncsLastDay, durationLastDay); - dumpSyncInterval(sb, "week", MILLIS_IN_WEEK, numSyncsLastWeek, durationLastWeek); - dumpSyncInterval(sb, "4 weeks", - MILLIS_IN_4WEEKS, numSyncsLast4Weeks, durationLast4Weeks); - dumpSyncInterval(sb, "total", 0, numSyncsTotal, durationTotal); - dumpSyncIntervalFooter(sb); - } finally { - c.close(); - } - } - - private void dumpSyncIntervalHeader(StringBuilder sb) { - sb.append("Sync Stats\n"); - sb.append(" ___________________________________________________________\n"); - sb.append(" | | | duration in sec | |\n"); - sb.append(" | interval | count | average | total | % of interval |\n"); - } - - private void dumpSyncInterval(StringBuilder sb, String label, - long interval, long numSyncs, long duration) { - sb.append(String.format(" | %-8s | %6d | %8.1f | %8.1f", - label, numSyncs, ((float)duration/numSyncs)/1000, (float)duration/1000)); - if (interval > 0) { - sb.append(String.format(" | %13.2f |\n", ((float)duration/interval)*100.0)); - } else { - sb.append(String.format(" | %13s |\n", "na")); - } - } - - private void dumpSyncIntervalFooter(StringBuilder sb) { - sb.append(" |_________________________________________________________|\n"); - } - - /** - * A helper object to keep track of the time we have spent syncing since the last boot - */ - private class SyncTimeTracker { - /** True if a sync was in progress on the most recent call to update() */ - boolean mLastWasSyncing = false; - /** Used to track when lastWasSyncing was last set */ - long mWhenSyncStarted = 0; - /** The cumulative time we have spent syncing */ - private long mTimeSpentSyncing; - - /** Call to let the tracker know that the sync state may have changed */ - public synchronized void update() { - final boolean isSyncInProgress = mActiveSyncContext != null; - if (isSyncInProgress == mLastWasSyncing) return; - final long now = SystemClock.elapsedRealtime(); - if (isSyncInProgress) { - mWhenSyncStarted = now; - } else { - mTimeSpentSyncing += now - mWhenSyncStarted; - } - mLastWasSyncing = isSyncInProgress; - } - - /** Get how long we have been syncing, in ms */ - public synchronized long timeSpentSyncing() { - if (!mLastWasSyncing) return mTimeSpentSyncing; - - final long now = SystemClock.elapsedRealtime(); - return mTimeSpentSyncing + (now - mWhenSyncStarted); - } - } - - /** - * Handles SyncOperation Messages that are posted to the associated - * HandlerThread. - */ - class SyncHandler extends Handler { - // Messages that can be sent on mHandler - private static final int MESSAGE_SYNC_FINISHED = 1; - private static final int MESSAGE_SYNC_ALARM = 2; - private static final int MESSAGE_CHECK_ALARMS = 3; - - public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo(); - private Long mAlarmScheduleTime = null; - public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker(); - - // used to track if we have installed the error notification so that we don't reinstall - // it if sync is still failing - private boolean mErrorNotificationInstalled = false; - - /** - * Used to keep track of whether a sync notification is active and who it is for. - */ - class SyncNotificationInfo { - // only valid if isActive is true - public String account; - - // only valid if isActive is true - public String authority; - - // true iff the notification manager has been asked to send the notification - public boolean isActive = false; - - // Set when we transition from not running a sync to running a sync, and cleared on - // the opposite transition. - public Long startTime = null; - - public void toString(StringBuilder sb) { - sb.append("account ").append(account) - .append(", authority ").append(authority) - .append(", isActive ").append(isActive) - .append(", startTime ").append(startTime); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - toString(sb); - return sb.toString(); - } - } - - public SyncHandler(Looper looper) { - super(looper); - } - - public void handleMessage(Message msg) { - handleSyncHandlerMessage(msg); - } - - private void handleSyncHandlerMessage(Message msg) { - try { - switch (msg.what) { - case SyncHandler.MESSAGE_SYNC_FINISHED: - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_FINISHED"); - } - SyncHandlerMessagePayload payload = (SyncHandlerMessagePayload)msg.obj; - if (mActiveSyncContext != payload.activeSyncContext) { - if (Config.LOGD) { - Log.d(TAG, "handleSyncHandlerMessage: sync context doesn't match, " - + "dropping: mActiveSyncContext " + mActiveSyncContext - + " != " + payload.activeSyncContext); - } - return; - } - runSyncFinishedOrCanceled(payload.syncResult); - - // since we are no longer syncing, check if it is time to start a new sync - runStateIdle(); - break; - - case SyncHandler.MESSAGE_SYNC_ALARM: { - boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); - if (isLoggable) { - Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_ALARM"); - } - mAlarmScheduleTime = null; - try { - if (mActiveSyncContext != null) { - if (isLoggable) { - Log.v(TAG, "handleSyncHandlerMessage: sync context is active"); - } - runStateSyncing(); - } - - // if the above call to runStateSyncing() resulted in the end of a sync, - // check if it is time to start a new sync - if (mActiveSyncContext == null) { - if (isLoggable) { - Log.v(TAG, "handleSyncHandlerMessage: " - + "sync context is not active"); - } - runStateIdle(); - } - } finally { - mHandleAlarmWakeLock.release(); - } - break; - } - - case SyncHandler.MESSAGE_CHECK_ALARMS: - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_CHECK_ALARMS"); - } - // we do all the work for this case in the finally block - break; - } - } finally { - final boolean isSyncInProgress = mActiveSyncContext != null; - if (!isSyncInProgress) { - mSyncWakeLock.release(); - } - manageSyncNotification(); - manageErrorNotification(); - manageSyncAlarm(); - mSyncTimeTracker.update(); - } - } - - private void runStateSyncing() { - // if the sync timeout has been reached then cancel it - - ActiveSyncContext activeSyncContext = mActiveSyncContext; - - final long now = SystemClock.elapsedRealtime(); - if (now > activeSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC) { - SyncOperation nextSyncOperation; - synchronized (mSyncQueue) { - nextSyncOperation = mSyncQueue.head(); - } - if (nextSyncOperation != null && nextSyncOperation.earliestRunTime <= now) { - if (Config.LOGD) { - Log.d(TAG, "canceling and rescheduling sync because it ran too long: " - + activeSyncContext.mSyncOperation); - } - rescheduleImmediately(activeSyncContext.mSyncOperation); - sendSyncFinishedOrCanceledMessage(activeSyncContext, - null /* no result since this is a cancel */); - } else { - activeSyncContext.mTimeoutStartTime = now + MAX_TIME_PER_SYNC; - } - } - - // no need to schedule an alarm, as that will be done by our caller. - } - - private void runStateIdle() { - boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); - if (isLoggable) Log.v(TAG, "runStateIdle"); - - // If we aren't ready to run (e.g. the data connection is down), get out. - if (!mDataConnectionIsConnected) { - if (isLoggable) { - Log.v(TAG, "runStateIdle: no data connection, skipping"); - } - setStatusText("No data connection"); - return; - } - - if (mStorageIsLow) { - if (isLoggable) { - Log.v(TAG, "runStateIdle: memory low, skipping"); - } - setStatusText("Memory low"); - return; - } - - // If the accounts aren't known yet then we aren't ready to run. We will be kicked - // when the account lookup request does complete. - String[] accounts = mAccounts; - if (accounts == null) { - if (isLoggable) { - Log.v(TAG, "runStateIdle: accounts not known, skipping"); - } - setStatusText("Accounts not known yet"); - return; - } - - // Otherwise consume SyncOperations from the head of the SyncQueue until one is - // found that is runnable (not disabled, etc). If that one is ready to run then - // start it, otherwise just get out. - SyncOperation syncOperation; - final Sync.Settings.QueryMap syncSettings = getSyncSettings(); - final ConnectivityManager connManager = (ConnectivityManager) - mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - final boolean backgroundDataSetting = connManager.getBackgroundDataSetting(); - synchronized (mSyncQueue) { - while (true) { - syncOperation = mSyncQueue.head(); - if (syncOperation == null) { - if (isLoggable) { - Log.v(TAG, "runStateIdle: no more sync operations, returning"); - } - return; - } - - // Sync is disabled, drop this operation. - if (!isSyncEnabled()) { - if (isLoggable) { - Log.v(TAG, "runStateIdle: sync disabled, dropping " + syncOperation); - } - mSyncQueue.popHead(); - continue; - } - - // skip the sync if it isn't a force and the settings are off for this provider - final boolean force = syncOperation.extras.getBoolean( - ContentResolver.SYNC_EXTRAS_FORCE, false); - if (!force && (!backgroundDataSetting - || !syncSettings.getListenForNetworkTickles() - || !syncSettings.getSyncProviderAutomatically( - syncOperation.authority))) { - if (isLoggable) { - Log.v(TAG, "runStateIdle: sync off, dropping " + syncOperation); - } - mSyncQueue.popHead(); - continue; - } - - // skip the sync if the account of this operation no longer exists - if (!ArrayUtils.contains(accounts, syncOperation.account)) { - mSyncQueue.popHead(); - if (isLoggable) { - Log.v(TAG, "runStateIdle: account not present, dropping " - + syncOperation); - } - continue; - } - - // go ahead and try to sync this syncOperation - if (isLoggable) { - Log.v(TAG, "runStateIdle: found sync candidate: " + syncOperation); - } - break; - } - - // If the first SyncOperation isn't ready to run schedule a wakeup and - // get out. - final long now = SystemClock.elapsedRealtime(); - if (syncOperation.earliestRunTime > now) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "runStateIdle: the time is " + now + " yet the next " - + "sync operation is for " + syncOperation.earliestRunTime - + ": " + syncOperation); - } - return; - } - - // We will do this sync. Remove it from the queue and run it outside of the - // synchronized block. - if (isLoggable) { - Log.v(TAG, "runStateIdle: we are going to sync " + syncOperation); - } - mSyncQueue.popHead(); - } - - String providerName = syncOperation.authority; - ensureContentResolver(); - IContentProvider contentProvider; - - // acquire the provider and update the sync history - try { - contentProvider = mContentResolver.acquireProvider(providerName); - if (contentProvider == null) { - Log.e(TAG, "Provider " + providerName + " doesn't exist"); - return; - } - if (contentProvider.getSyncAdapter() == null) { - Log.e(TAG, "Provider " + providerName + " isn't syncable, " + contentProvider); - return; - } - } catch (RemoteException remoteExc) { - Log.e(TAG, "Caught a RemoteException while preparing for sync, rescheduling " - + syncOperation, remoteExc); - rescheduleWithDelay(syncOperation); - return; - } catch (RuntimeException exc) { - Log.e(TAG, "Caught a RuntimeException while validating sync of " + providerName, - exc); - return; - } - - final long historyRowId = insertStartSyncEvent(syncOperation); - - try { - ISyncAdapter syncAdapter = contentProvider.getSyncAdapter(); - ActiveSyncContext activeSyncContext = new ActiveSyncContext(syncOperation, - contentProvider, syncAdapter, historyRowId); - mSyncWakeLock.acquire(); - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "starting sync of " + syncOperation); - } - syncAdapter.startSync(activeSyncContext, syncOperation.account, - syncOperation.extras); - mActiveSyncContext = activeSyncContext; - mSyncStorageEngine.setActiveSync(mActiveSyncContext); - } catch (RemoteException remoteExc) { - if (Config.LOGD) { - Log.d(TAG, "runStateIdle: caught a RemoteException, rescheduling", remoteExc); - } - mActiveSyncContext = null; - mSyncStorageEngine.setActiveSync(mActiveSyncContext); - rescheduleWithDelay(syncOperation); - } catch (RuntimeException exc) { - mActiveSyncContext = null; - mSyncStorageEngine.setActiveSync(mActiveSyncContext); - Log.e(TAG, "Caught a RuntimeException while starting the sync " + syncOperation, - exc); - } - - // no need to schedule an alarm, as that will be done by our caller. - } - - private void runSyncFinishedOrCanceled(SyncResult syncResult) { - boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); - if (isLoggable) Log.v(TAG, "runSyncFinishedOrCanceled"); - ActiveSyncContext activeSyncContext = mActiveSyncContext; - mActiveSyncContext = null; - mSyncStorageEngine.setActiveSync(mActiveSyncContext); - - final SyncOperation syncOperation = activeSyncContext.mSyncOperation; - - final long elapsedTime = SystemClock.elapsedRealtime() - activeSyncContext.mStartTime; - - String historyMessage; - int downstreamActivity; - int upstreamActivity; - if (syncResult != null) { - if (isLoggable) { - Log.v(TAG, "runSyncFinishedOrCanceled: is a finished: operation " - + syncOperation + ", result " + syncResult); - } - - if (!syncResult.hasError()) { - if (isLoggable) { - Log.v(TAG, "finished sync operation " + syncOperation); - } - historyMessage = History.MESG_SUCCESS; - // TODO: set these correctly when the SyncResult is extended to include it - downstreamActivity = 0; - upstreamActivity = 0; - } else { - maybeRescheduleSync(syncResult, syncOperation); - if (Config.LOGD) { - Log.d(TAG, "failed sync operation " + syncOperation); - } - historyMessage = Integer.toString(syncResultToErrorNumber(syncResult)); - // TODO: set these correctly when the SyncResult is extended to include it - downstreamActivity = 0; - upstreamActivity = 0; - } - } else { - if (isLoggable) { - Log.v(TAG, "runSyncFinishedOrCanceled: is a cancel: operation " - + syncOperation); - } - try { - activeSyncContext.mSyncAdapter.cancelSync(); - } catch (RemoteException e) { - // we don't need to retry this in this case - } - historyMessage = History.MESG_CANCELED; - downstreamActivity = 0; - upstreamActivity = 0; - } - - stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage, - upstreamActivity, downstreamActivity, elapsedTime); - - mContentResolver.releaseProvider(activeSyncContext.mContentProvider); - - if (syncResult != null && syncResult.tooManyDeletions) { - installHandleTooManyDeletesNotification(syncOperation.account, - syncOperation.authority, syncResult.stats.numDeletes); - } else { - mNotificationMgr.cancel( - syncOperation.account.hashCode() ^ syncOperation.authority.hashCode()); - } - - if (syncResult != null && syncResult.fullSyncRequested) { - scheduleSyncOperation(new SyncOperation(syncOperation.account, - syncOperation.syncSource, syncOperation.authority, new Bundle(), 0)); - } - // no need to schedule an alarm, as that will be done by our caller. - } - - /** - * Convert the error-containing SyncResult into the Sync.History error number. Since - * the SyncResult may indicate multiple errors at once, this method just returns the - * most "serious" error. - * @param syncResult the SyncResult from which to read - * @return the most "serious" error set in the SyncResult - * @throws IllegalStateException if the SyncResult does not indicate any errors. - * If SyncResult.error() is true then it is safe to call this. - */ - private int syncResultToErrorNumber(SyncResult syncResult) { - if (syncResult.syncAlreadyInProgress) return History.ERROR_SYNC_ALREADY_IN_PROGRESS; - if (syncResult.stats.numAuthExceptions > 0) return History.ERROR_AUTHENTICATION; - if (syncResult.stats.numIoExceptions > 0) return History.ERROR_IO; - if (syncResult.stats.numParseExceptions > 0) return History.ERROR_PARSE; - if (syncResult.stats.numConflictDetectedExceptions > 0) return History.ERROR_CONFLICT; - if (syncResult.tooManyDeletions) return History.ERROR_TOO_MANY_DELETIONS; - if (syncResult.tooManyRetries) return History.ERROR_TOO_MANY_RETRIES; - if (syncResult.databaseError) return History.ERROR_INTERNAL; - throw new IllegalStateException("we are not in an error state, " + syncResult); - } - - private void manageSyncNotification() { - boolean shouldCancel; - boolean shouldInstall; - - if (mActiveSyncContext == null) { - mSyncNotificationInfo.startTime = null; - - // we aren't syncing. if the notification is active then remember that we need - // to cancel it and then clear out the info - shouldCancel = mSyncNotificationInfo.isActive; - shouldInstall = false; - } else { - // we are syncing - final SyncOperation syncOperation = mActiveSyncContext.mSyncOperation; - - final long now = SystemClock.elapsedRealtime(); - if (mSyncNotificationInfo.startTime == null) { - mSyncNotificationInfo.startTime = now; - } - - // cancel the notification if it is up and the authority or account is wrong - shouldCancel = mSyncNotificationInfo.isActive && - (!syncOperation.authority.equals(mSyncNotificationInfo.authority) - || !syncOperation.account.equals(mSyncNotificationInfo.account)); - - // there are four cases: - // - the notification is up and there is no change: do nothing - // - the notification is up but we should cancel since it is stale: - // need to install - // - the notification is not up but it isn't time yet: don't install - // - the notification is not up and it is time: need to install - - if (mSyncNotificationInfo.isActive) { - shouldInstall = shouldCancel; - } else { - final boolean timeToShowNotification = - now > mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY; - final boolean syncIsForced = syncOperation.extras - .getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false); - shouldInstall = timeToShowNotification || syncIsForced; - } - } - - if (shouldCancel && !shouldInstall) { - mNeedSyncActiveNotification = false; - sendSyncStateIntent(); - mSyncNotificationInfo.isActive = false; - } - - if (shouldInstall) { - SyncOperation syncOperation = mActiveSyncContext.mSyncOperation; - mNeedSyncActiveNotification = true; - sendSyncStateIntent(); - mSyncNotificationInfo.isActive = true; - mSyncNotificationInfo.account = syncOperation.account; - mSyncNotificationInfo.authority = syncOperation.authority; - } - } - - /** - * Check if there were any long-lasting errors, if so install the error notification, - * otherwise cancel the error notification. - */ - private void manageErrorNotification() { - // - long when = mSyncStorageEngine.getInitialSyncFailureTime(); - if ((when > 0) && (when + ERROR_NOTIFICATION_DELAY_MS < System.currentTimeMillis())) { - if (!mErrorNotificationInstalled) { - mNeedSyncErrorNotification = true; - sendSyncStateIntent(); - } - mErrorNotificationInstalled = true; - } else { - if (mErrorNotificationInstalled) { - mNeedSyncErrorNotification = false; - sendSyncStateIntent(); - } - mErrorNotificationInstalled = false; - } - } - - private void manageSyncAlarm() { - // in each of these cases the sync loop will be kicked, which will cause this - // method to be called again - if (!mDataConnectionIsConnected) return; - if (mAccounts == null) return; - if (mStorageIsLow) return; - - // Compute the alarm fire time: - // - not syncing: time of the next sync operation - // - syncing, no notification: time from sync start to notification create time - // - syncing, with notification: time till timeout of the active sync operation - Long alarmTime = null; - ActiveSyncContext activeSyncContext = mActiveSyncContext; - if (activeSyncContext == null) { - SyncOperation syncOperation; - synchronized (mSyncQueue) { - syncOperation = mSyncQueue.head(); - } - if (syncOperation != null) { - alarmTime = syncOperation.earliestRunTime; - } - } else { - final long notificationTime = - mSyncHandler.mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY; - final long timeoutTime = - mActiveSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC; - if (mSyncHandler.mSyncNotificationInfo.isActive) { - alarmTime = timeoutTime; - } else { - alarmTime = Math.min(notificationTime, timeoutTime); - } - } - - // adjust the alarmTime so that we will wake up when it is time to - // install the error notification - if (!mErrorNotificationInstalled) { - long when = mSyncStorageEngine.getInitialSyncFailureTime(); - if (when > 0) { - when += ERROR_NOTIFICATION_DELAY_MS; - // convert when fron absolute time to elapsed run time - long delay = when - System.currentTimeMillis(); - when = SystemClock.elapsedRealtime() + delay; - alarmTime = alarmTime != null ? Math.min(alarmTime, when) : when; - } - } - - // determine if we need to set or cancel the alarm - boolean shouldSet = false; - boolean shouldCancel = false; - final boolean alarmIsActive = mAlarmScheduleTime != null; - final boolean needAlarm = alarmTime != null; - if (needAlarm) { - if (!alarmIsActive || alarmTime < mAlarmScheduleTime) { - shouldSet = true; - } - } else { - shouldCancel = alarmIsActive; - } - - // set or cancel the alarm as directed - ensureAlarmService(); - if (shouldSet) { - mAlarmScheduleTime = alarmTime; - mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, - mSyncAlarmIntent); - } else if (shouldCancel) { - mAlarmScheduleTime = null; - mAlarmService.cancel(mSyncAlarmIntent); - } - } - - private void sendSyncStateIntent() { - Intent syncStateIntent = new Intent(Intent.ACTION_SYNC_STATE_CHANGED); - syncStateIntent.putExtra("active", mNeedSyncActiveNotification); - syncStateIntent.putExtra("failing", mNeedSyncErrorNotification); - mContext.sendBroadcast(syncStateIntent); - } - - private void installHandleTooManyDeletesNotification(String account, String authority, - long numDeletes) { - if (mNotificationMgr == null) return; - Intent clickIntent = new Intent(); - clickIntent.setClassName("com.android.providers.subscribedfeeds", - "com.android.settings.SyncActivityTooManyDeletes"); - clickIntent.putExtra("account", account); - clickIntent.putExtra("provider", authority); - clickIntent.putExtra("numDeletes", numDeletes); - - if (!isActivityAvailable(clickIntent)) { - Log.w(TAG, "No activity found to handle too many deletes."); - return; - } - - final PendingIntent pendingIntent = PendingIntent - .getActivity(mContext, 0, clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); - - CharSequence tooManyDeletesDescFormat = mContext.getResources().getText( - R.string.contentServiceTooManyDeletesNotificationDesc); - - String[] authorities = authority.split(";"); - Notification notification = - new Notification(R.drawable.stat_notify_sync_error, - mContext.getString(R.string.contentServiceSync), - System.currentTimeMillis()); - notification.setLatestEventInfo(mContext, - mContext.getString(R.string.contentServiceSyncNotificationTitle), - String.format(tooManyDeletesDescFormat.toString(), authorities[0]), - pendingIntent); - notification.flags |= Notification.FLAG_ONGOING_EVENT; - mNotificationMgr.notify(account.hashCode() ^ authority.hashCode(), notification); - } - - /** - * Checks whether an activity exists on the system image for the given intent. - * - * @param intent The intent for an activity. - * @return Whether or not an activity exists. - */ - private boolean isActivityAvailable(Intent intent) { - PackageManager pm = mContext.getPackageManager(); - List<ResolveInfo> list = pm.queryIntentActivities(intent, 0); - int listSize = list.size(); - for (int i = 0; i < listSize; i++) { - ResolveInfo resolveInfo = list.get(i); - if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) - != 0) { - return true; - } - } - - return false; - } - - public long insertStartSyncEvent(SyncOperation syncOperation) { - final int source = syncOperation.syncSource; - final long now = System.currentTimeMillis(); - - EventLog.writeEvent(2720, syncOperation.authority, Sync.History.EVENT_START, source); - - return mSyncStorageEngine.insertStartSyncEvent( - syncOperation.account, syncOperation.authority, now, source); - } - - public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage, - int upstreamActivity, int downstreamActivity, long elapsedTime) { - EventLog.writeEvent(2720, syncOperation.authority, Sync.History.EVENT_STOP, syncOperation.syncSource); - - mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime, resultMessage, - downstreamActivity, upstreamActivity); - } - } - - static class SyncQueue { - private SyncStorageEngine mSyncStorageEngine; - private final String[] COLUMNS = new String[]{ - "_id", - "authority", - "account", - "extras", - "source" - }; - private static final int COLUMN_ID = 0; - private static final int COLUMN_AUTHORITY = 1; - private static final int COLUMN_ACCOUNT = 2; - private static final int COLUMN_EXTRAS = 3; - private static final int COLUMN_SOURCE = 4; - - private static final boolean DEBUG_CHECK_DATA_CONSISTENCY = false; - - // A priority queue of scheduled SyncOperations that is designed to make it quick - // to find the next SyncOperation that should be considered for running. - private final PriorityQueue<SyncOperation> mOpsByWhen = new PriorityQueue<SyncOperation>(); - - // A Map of SyncOperations operationKey -> SyncOperation that is designed for - // quick lookup of an enqueued SyncOperation. - private final HashMap<String, SyncOperation> mOpsByKey = Maps.newHashMap(); - - public SyncQueue(SyncStorageEngine syncStorageEngine) { - mSyncStorageEngine = syncStorageEngine; - Cursor cursor = mSyncStorageEngine.getPendingSyncsCursor(COLUMNS); - try { - while (cursor.moveToNext()) { - add(cursorToOperation(cursor), - true /* this is being added from the database */); - } - } finally { - cursor.close(); - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - } - } - - public boolean add(SyncOperation operation) { - return add(new SyncOperation(operation), - false /* this is not coming from the database */); - } - - private boolean add(SyncOperation operation, boolean fromDatabase) { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase); - - // If this operation is expedited then set its earliestRunTime to be immediately - // before the head of the list, or not if none are in the list. - if (operation.delay < 0) { - SyncOperation headOperation = head(); - if (headOperation != null) { - operation.earliestRunTime = Math.min(SystemClock.elapsedRealtime(), - headOperation.earliestRunTime - 1); - } else { - operation.earliestRunTime = SystemClock.elapsedRealtime(); - } - } - - // - if an operation with the same key exists and this one should run earlier, - // delete the old one and add the new one - // - if an operation with the same key exists and if this one should run - // later, ignore it - // - if no operation exists then add the new one - final String operationKey = operation.key; - SyncOperation existingOperation = mOpsByKey.get(operationKey); - - // if this operation matches an existing operation that is being retried (delay > 0) - // and this operation isn't forced, ignore this operation - if (existingOperation != null && existingOperation.delay > 0) { - if (!operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)) { - return false; - } - } - - if (existingOperation != null - && operation.earliestRunTime >= existingOperation.earliestRunTime) { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase); - return false; - } - - if (existingOperation != null) { - removeByKey(operationKey); - } - - if (operation.rowId == null) { - byte[] extrasData = null; - Parcel parcel = Parcel.obtain(); - try { - operation.extras.writeToParcel(parcel, 0); - extrasData = parcel.marshall(); - } finally { - parcel.recycle(); - } - ContentValues values = new ContentValues(); - values.put("account", operation.account); - values.put("authority", operation.authority); - values.put("source", operation.syncSource); - values.put("extras", extrasData); - Uri pendingUri = mSyncStorageEngine.insertIntoPending(values); - operation.rowId = pendingUri == null ? null : ContentUris.parseId(pendingUri); - if (operation.rowId == null) { - throw new IllegalStateException("error adding pending sync operation " - + operation); - } - } - - if (DEBUG_CHECK_DATA_CONSISTENCY) { - debugCheckDataStructures( - false /* don't compare with the DB, since we know - it is inconsistent right now */ ); - } - mOpsByKey.put(operationKey, operation); - mOpsByWhen.add(operation); - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase); - return true; - } - - public void removeByKey(String operationKey) { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - SyncOperation operationToRemove = mOpsByKey.remove(operationKey); - if (!mOpsByWhen.remove(operationToRemove)) { - throw new IllegalStateException( - "unable to find " + operationToRemove + " in mOpsByWhen"); - } - - if (mSyncStorageEngine.deleteFromPending(operationToRemove.rowId) != 1) { - throw new IllegalStateException("unable to find pending row for " - + operationToRemove); - } - - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - } - - public SyncOperation head() { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - return mOpsByWhen.peek(); - } - - public void popHead() { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - SyncOperation operation = mOpsByWhen.remove(); - if (mOpsByKey.remove(operation.key) == null) { - throw new IllegalStateException("unable to find " + operation + " in mOpsByKey"); - } - - if (mSyncStorageEngine.deleteFromPending(operation.rowId) != 1) { - throw new IllegalStateException("unable to find pending row for " + operation); - } - - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - } - - public void clear(String account, String authority) { - Iterator<Map.Entry<String, SyncOperation>> entries = mOpsByKey.entrySet().iterator(); - while (entries.hasNext()) { - Map.Entry<String, SyncOperation> entry = entries.next(); - SyncOperation syncOperation = entry.getValue(); - if (account != null && !syncOperation.account.equals(account)) continue; - if (authority != null && !syncOperation.authority.equals(authority)) continue; - - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - entries.remove(); - if (!mOpsByWhen.remove(syncOperation)) { - throw new IllegalStateException( - "unable to find " + syncOperation + " in mOpsByWhen"); - } - - if (mSyncStorageEngine.deleteFromPending(syncOperation.rowId) != 1) { - throw new IllegalStateException("unable to find pending row for " - + syncOperation); - } - - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - } - } - - public void dump(StringBuilder sb) { - sb.append("SyncQueue: ").append(mOpsByWhen.size()).append(" operation(s)\n"); - for (SyncOperation operation : mOpsByWhen) { - sb.append(operation).append("\n"); - } - } - - private void debugCheckDataStructures(boolean checkDatabase) { - if (mOpsByKey.size() != mOpsByWhen.size()) { - throw new IllegalStateException("size mismatch: " - + mOpsByKey .size() + " != " + mOpsByWhen.size()); - } - for (SyncOperation operation : mOpsByWhen) { - if (!mOpsByKey.containsKey(operation.key)) { - throw new IllegalStateException( - "operation " + operation + " is in mOpsByWhen but not mOpsByKey"); - } - } - for (Map.Entry<String, SyncOperation> entry : mOpsByKey.entrySet()) { - final SyncOperation operation = entry.getValue(); - final String key = entry.getKey(); - if (!key.equals(operation.key)) { - throw new IllegalStateException( - "operation " + operation + " in mOpsByKey doesn't match key " + key); - } - if (!mOpsByWhen.contains(operation)) { - throw new IllegalStateException( - "operation " + operation + " is in mOpsByKey but not mOpsByWhen"); - } - } - - if (checkDatabase) { - // check that the DB contains the same rows as the in-memory data structures - Cursor cursor = mSyncStorageEngine.getPendingSyncsCursor(COLUMNS); - try { - if (mOpsByKey.size() != cursor.getCount()) { - StringBuilder sb = new StringBuilder(); - DatabaseUtils.dumpCursor(cursor, sb); - sb.append("\n"); - dump(sb); - throw new IllegalStateException("DB size mismatch: " - + mOpsByKey .size() + " != " + cursor.getCount() + "\n" - + sb.toString()); - } - } finally { - cursor.close(); - } - } - } - - private SyncOperation cursorToOperation(Cursor cursor) { - byte[] extrasData = cursor.getBlob(COLUMN_EXTRAS); - Bundle extras; - Parcel parcel = Parcel.obtain(); - try { - parcel.unmarshall(extrasData, 0, extrasData.length); - parcel.setDataPosition(0); - extras = parcel.readBundle(); - } catch (RuntimeException e) { - // A RuntimeException is thrown if we were unable to parse the parcel. - // Create an empty parcel in this case. - extras = new Bundle(); - } finally { - parcel.recycle(); - } - - SyncOperation syncOperation = new SyncOperation( - cursor.getString(COLUMN_ACCOUNT), - cursor.getInt(COLUMN_SOURCE), - cursor.getString(COLUMN_AUTHORITY), - extras, - 0 /* delay */); - syncOperation.rowId = cursor.getLong(COLUMN_ID); - return syncOperation; - } - } -} diff --git a/core/java/android/content/SyncProvider.java b/core/java/android/content/SyncProvider.java deleted file mode 100644 index 6ddd046..0000000 --- a/core/java/android/content/SyncProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2007 The Android Open Source Project -package android.content; - -import android.database.Cursor; -import android.net.Uri; - -/** - * ContentProvider that tracks the sync data and overall sync - * history on the device. - * - * @hide - */ -public class SyncProvider extends ContentProvider { - public SyncProvider() { - } - - private SyncStorageEngine mSyncStorageEngine; - - @Override - public boolean onCreate() { - mSyncStorageEngine = SyncStorageEngine.getSingleton(); - return true; - } - - @Override - public Cursor query(Uri url, String[] projectionIn, - String selection, String[] selectionArgs, String sort) { - return mSyncStorageEngine.query(url, projectionIn, selection, selectionArgs, sort); - } - - @Override - public Uri insert(Uri url, ContentValues initialValues) { - return mSyncStorageEngine.insert(true /* the caller is the provider */, - url, initialValues); - } - - @Override - public int delete(Uri url, String where, String[] whereArgs) { - return mSyncStorageEngine.delete(true /* the caller is the provider */, - url, where, whereArgs); - } - - @Override - public int update(Uri url, ContentValues initialValues, String where, String[] whereArgs) { - return mSyncStorageEngine.update(true /* the caller is the provider */, - url, initialValues, where, whereArgs); - } - - @Override - public String getType(Uri url) { - return mSyncStorageEngine.getType(url); - } -} diff --git a/core/java/android/content/SyncResult.aidl b/core/java/android/content/SyncResult.aidl deleted file mode 100644 index 061b81c..0000000 --- a/core/java/android/content/SyncResult.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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; - -parcelable SyncResult; diff --git a/core/java/android/content/SyncResult.java b/core/java/android/content/SyncResult.java deleted file mode 100644 index f3260f3..0000000 --- a/core/java/android/content/SyncResult.java +++ /dev/null @@ -1,178 +0,0 @@ -package android.content; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * This class is used to store information about the result of a sync - * - * @hide - */ -public final class SyncResult implements Parcelable { - public final boolean syncAlreadyInProgress; - public boolean tooManyDeletions; - public boolean tooManyRetries; - public boolean databaseError; - public boolean fullSyncRequested; - public boolean partialSyncUnavailable; - public boolean moreRecordsToGet; - public final SyncStats stats; - public static final SyncResult ALREADY_IN_PROGRESS; - - static { - ALREADY_IN_PROGRESS = new SyncResult(true); - } - - public SyncResult() { - this(false); - } - - private SyncResult(boolean syncAlreadyInProgress) { - this.syncAlreadyInProgress = syncAlreadyInProgress; - this.tooManyDeletions = false; - this.tooManyRetries = false; - this.fullSyncRequested = false; - this.partialSyncUnavailable = false; - this.moreRecordsToGet = false; - this.stats = new SyncStats(); - } - - private SyncResult(Parcel parcel) { - syncAlreadyInProgress = parcel.readInt() != 0; - tooManyDeletions = parcel.readInt() != 0; - tooManyRetries = parcel.readInt() != 0; - databaseError = parcel.readInt() != 0; - fullSyncRequested = parcel.readInt() != 0; - partialSyncUnavailable = parcel.readInt() != 0; - moreRecordsToGet = parcel.readInt() != 0; - stats = new SyncStats(parcel); - } - - public boolean hasHardError() { - return stats.numParseExceptions > 0 - || stats.numConflictDetectedExceptions > 0 - || stats.numAuthExceptions > 0 - || tooManyDeletions - || tooManyRetries - || databaseError; - } - - public boolean hasSoftError() { - return syncAlreadyInProgress || stats.numIoExceptions > 0; - } - - public boolean hasError() { - return hasSoftError() || hasHardError(); - } - - public boolean madeSomeProgress() { - return ((stats.numDeletes > 0) && !tooManyDeletions) - || stats.numInserts > 0 - || stats.numUpdates > 0; - } - - public void clear() { - if (syncAlreadyInProgress) { - throw new UnsupportedOperationException( - "you are not allowed to clear the ALREADY_IN_PROGRESS SyncStats"); - } - tooManyDeletions = false; - tooManyRetries = false; - databaseError = false; - fullSyncRequested = false; - partialSyncUnavailable = false; - moreRecordsToGet = false; - stats.clear(); - } - - public static final Creator<SyncResult> CREATOR = new Creator<SyncResult>() { - public SyncResult createFromParcel(Parcel in) { - return new SyncResult(in); - } - - public SyncResult[] newArray(int size) { - return new SyncResult[size]; - } - }; - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeInt(syncAlreadyInProgress ? 1 : 0); - parcel.writeInt(tooManyDeletions ? 1 : 0); - parcel.writeInt(tooManyRetries ? 1 : 0); - parcel.writeInt(databaseError ? 1 : 0); - parcel.writeInt(fullSyncRequested ? 1 : 0); - parcel.writeInt(partialSyncUnavailable ? 1 : 0); - parcel.writeInt(moreRecordsToGet ? 1 : 0); - stats.writeToParcel(parcel, flags); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(" syncAlreadyInProgress: ").append(syncAlreadyInProgress); - sb.append(" tooManyDeletions: ").append(tooManyDeletions); - sb.append(" tooManyRetries: ").append(tooManyRetries); - sb.append(" databaseError: ").append(databaseError); - sb.append(" fullSyncRequested: ").append(fullSyncRequested); - sb.append(" partialSyncUnavailable: ").append(partialSyncUnavailable); - sb.append(" moreRecordsToGet: ").append(moreRecordsToGet); - sb.append(" stats: ").append(stats); - return sb.toString(); - } - - /** - * Generates a debugging string indicating the status. - * The string consist of a sequence of code letter followed by the count. - * Code letters are f - fullSyncRequested, r - partialSyncUnavailable, - * X - hardError, e - numParseExceptions, c - numConflictDetectedExceptions, - * a - numAuthExceptions, D - tooManyDeletions, R - tooManyRetries, - * b - databaseError, x - softError, l - syncAlreadyInProgress, - * I - numIoExceptions - * @return debugging string. - */ - public String toDebugString() { - StringBuffer sb = new StringBuffer(); - - if (fullSyncRequested) { - sb.append("f1"); - } - if (partialSyncUnavailable) { - sb.append("r1"); - } - if (hasHardError()) { - sb.append("X1"); - } - if (stats.numParseExceptions > 0) { - sb.append("e").append(stats.numParseExceptions); - } - if (stats.numConflictDetectedExceptions > 0) { - sb.append("c").append(stats.numConflictDetectedExceptions); - } - if (stats.numAuthExceptions > 0) { - sb.append("a").append(stats.numAuthExceptions); - } - if (tooManyDeletions) { - sb.append("D1"); - } - if (tooManyRetries) { - sb.append("R1"); - } - if (databaseError) { - sb.append("b1"); - } - if (hasSoftError()) { - sb.append("x1"); - } - if (syncAlreadyInProgress) { - sb.append("l1"); - } - if (stats.numIoExceptions > 0) { - sb.append("I").append(stats.numIoExceptions); - } - return sb.toString(); - } -} diff --git a/core/java/android/content/SyncStateContentProviderHelper.java b/core/java/android/content/SyncStateContentProviderHelper.java deleted file mode 100644 index f503e6f..0000000 --- a/core/java/android/content/SyncStateContentProviderHelper.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 com.android.internal.util.ArrayUtils; - -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.net.Uri; - -/** - * Extends the schema of a ContentProvider to include the _sync_state table - * and implements query/insert/update/delete to access that table using the - * authority "syncstate". This can be used to store the sync state for a - * set of accounts. - * - * @hide - */ -public class SyncStateContentProviderHelper { - final SQLiteOpenHelper mOpenHelper; - - private static final String SYNC_STATE_AUTHORITY = "syncstate"; - private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); - - private static final int STATE = 0; - - private static final Uri CONTENT_URI = - Uri.parse("content://" + SYNC_STATE_AUTHORITY + "/state"); - - private static final String ACCOUNT_WHERE = "_sync_account = ?"; - - private final Provider mInternalProviderInterface; - - private static final String SYNC_STATE_TABLE = "_sync_state"; - private static long DB_VERSION = 2; - - private static final String[] ACCOUNT_PROJECTION = new String[]{"_sync_account"}; - - static { - sURIMatcher.addURI(SYNC_STATE_AUTHORITY, "state", STATE); - } - - public SyncStateContentProviderHelper(SQLiteOpenHelper openHelper) { - mOpenHelper = openHelper; - mInternalProviderInterface = new Provider(); - } - - public ContentProvider asContentProvider() { - return mInternalProviderInterface; - } - - public void createDatabase(SQLiteDatabase db) { - db.execSQL("DROP TABLE IF EXISTS _sync_state"); - db.execSQL("CREATE TABLE _sync_state (" + - "_id INTEGER PRIMARY KEY," + - "_sync_account TEXT," + - "data TEXT," + - "UNIQUE(_sync_account)" + - ");"); - - db.execSQL("DROP TABLE IF EXISTS _sync_state_metadata"); - db.execSQL("CREATE TABLE _sync_state_metadata (" + - "version INTEGER" + - ");"); - ContentValues values = new ContentValues(); - values.put("version", DB_VERSION); - db.insert("_sync_state_metadata", "version", values); - } - - protected void onDatabaseOpened(SQLiteDatabase db) { - long version = DatabaseUtils.longForQuery(db, - "select version from _sync_state_metadata", null); - if (version != DB_VERSION) { - createDatabase(db); - } - } - - class Provider extends ContentProvider { - public boolean onCreate() { - throw new UnsupportedOperationException("not implemented"); - } - - public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - int match = sURIMatcher.match(url); - switch (match) { - case STATE: - return db.query(SYNC_STATE_TABLE, projection, selection, selectionArgs, - null, null, sortOrder); - default: - throw new UnsupportedOperationException("Cannot query URL: " + url); - } - } - - public String getType(Uri uri) { - throw new UnsupportedOperationException("not implemented"); - } - - public Uri insert(Uri url, ContentValues values) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int match = sURIMatcher.match(url); - switch (match) { - case STATE: { - long id = db.insert(SYNC_STATE_TABLE, "feed", values); - return CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build(); - } - default: - throw new UnsupportedOperationException("Cannot insert into URL: " + url); - } - } - - public int delete(Uri url, String userWhere, String[] whereArgs) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - switch (sURIMatcher.match(url)) { - case STATE: - return db.delete(SYNC_STATE_TABLE, userWhere, whereArgs); - default: - throw new IllegalArgumentException("Unknown URL " + url); - } - - } - - public int update(Uri url, ContentValues values, String selection, String[] selectionArgs) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - switch (sURIMatcher.match(url)) { - case STATE: - return db.update(SYNC_STATE_TABLE, values, selection, selectionArgs); - default: - throw new UnsupportedOperationException("Cannot update URL: " + url); - } - - } - } - - /** - * Check if the url matches content that this ContentProvider manages. - * @param url the Uri to check - * @return true if this ContentProvider can handle that Uri. - */ - public boolean matches(Uri url) { - return (SYNC_STATE_AUTHORITY.equals(url.getAuthority())); - } - - /** - * Replaces the contents of the _sync_state table in the destination ContentProvider - * with the row that matches account, if any, in the source ContentProvider. - * <p> - * The ContentProviders must expose the _sync_state table as URI content://syncstate/state. - * @param dbSrc the database to read from - * @param dbDest the database to write to - * @param account the account of the row that should be copied over. - */ - public void copySyncState(SQLiteDatabase dbSrc, SQLiteDatabase dbDest, - String account) { - final String[] whereArgs = new String[]{account}; - Cursor c = dbSrc.query(SYNC_STATE_TABLE, new String[]{"_sync_account", "data"}, - ACCOUNT_WHERE, whereArgs, null, null, null); - try { - if (c.moveToNext()) { - ContentValues values = new ContentValues(); - values.put("_sync_account", c.getString(0)); - values.put("data", c.getBlob(1)); - dbDest.replace(SYNC_STATE_TABLE, "_sync_account", values); - } - } finally { - c.close(); - } - } - - public void onAccountsChanged(String[] accounts) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - Cursor c = db.query(SYNC_STATE_TABLE, ACCOUNT_PROJECTION, null, null, null, null, null); - try { - while (c.moveToNext()) { - final String account = c.getString(0); - if (!ArrayUtils.contains(accounts, account)) { - db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account}); - } - } - } finally { - c.close(); - } - } - - public void discardSyncData(SQLiteDatabase db, String account) { - if (account != null) { - db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account}); - } else { - db.delete(SYNC_STATE_TABLE, null, null); - } - } - - /** - * Retrieves the SyncData bytes for the given account. The byte array returned may be null. - */ - public byte[] readSyncDataBytes(SQLiteDatabase db, String account) { - Cursor c = db.query(SYNC_STATE_TABLE, null, ACCOUNT_WHERE, - new String[]{account}, null, null, null); - try { - if (c.moveToFirst()) { - return c.getBlob(c.getColumnIndexOrThrow("data")); - } - } finally { - c.close(); - } - return null; - } - - /** - * Sets the SyncData bytes for the given account. The bytes array may be null. - */ - public void writeSyncDataBytes(SQLiteDatabase db, String account, byte[] data) { - ContentValues values = new ContentValues(); - values.put("data", data); - db.update(SYNC_STATE_TABLE, values, ACCOUNT_WHERE, new String[]{account}); - } -} diff --git a/core/java/android/content/SyncStats.aidl b/core/java/android/content/SyncStats.aidl deleted file mode 100644 index dff0ebf..0000000 --- a/core/java/android/content/SyncStats.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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; - -parcelable SyncStats; diff --git a/core/java/android/content/SyncStats.java b/core/java/android/content/SyncStats.java deleted file mode 100644 index b561b05..0000000 --- a/core/java/android/content/SyncStats.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.os.Parcelable; -import android.os.Parcel; - -/** - * @hide - */ -public class SyncStats implements Parcelable { - public long numAuthExceptions; - public long numIoExceptions; - public long numParseExceptions; - public long numConflictDetectedExceptions; - public long numInserts; - public long numUpdates; - public long numDeletes; - public long numEntries; - public long numSkippedEntries; - - public SyncStats() { - numAuthExceptions = 0; - numIoExceptions = 0; - numParseExceptions = 0; - numConflictDetectedExceptions = 0; - numInserts = 0; - numUpdates = 0; - numDeletes = 0; - numEntries = 0; - numSkippedEntries = 0; - } - - public SyncStats(Parcel in) { - numAuthExceptions = in.readLong(); - numIoExceptions = in.readLong(); - numParseExceptions = in.readLong(); - numConflictDetectedExceptions = in.readLong(); - numInserts = in.readLong(); - numUpdates = in.readLong(); - numDeletes = in.readLong(); - numEntries = in.readLong(); - numSkippedEntries = in.readLong(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("numAuthExceptions: ").append(numAuthExceptions); - sb.append(" numIoExceptions: ").append(numIoExceptions); - sb.append(" numParseExceptions: ").append(numParseExceptions); - sb.append(" numConflictDetectedExceptions: ").append(numConflictDetectedExceptions); - sb.append(" numInserts: ").append(numInserts); - sb.append(" numUpdates: ").append(numUpdates); - sb.append(" numDeletes: ").append(numDeletes); - sb.append(" numEntries: ").append(numEntries); - sb.append(" numSkippedEntries: ").append(numSkippedEntries); - return sb.toString(); - } - - public void clear() { - numAuthExceptions = 0; - numIoExceptions = 0; - numParseExceptions = 0; - numConflictDetectedExceptions = 0; - numInserts = 0; - numUpdates = 0; - numDeletes = 0; - numEntries = 0; - numSkippedEntries = 0; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(numAuthExceptions); - dest.writeLong(numIoExceptions); - dest.writeLong(numParseExceptions); - dest.writeLong(numConflictDetectedExceptions); - dest.writeLong(numInserts); - dest.writeLong(numUpdates); - dest.writeLong(numDeletes); - dest.writeLong(numEntries); - dest.writeLong(numSkippedEntries); - } - - public static final Creator<SyncStats> CREATOR = new Creator<SyncStats>() { - public SyncStats createFromParcel(Parcel in) { - return new SyncStats(in); - } - - public SyncStats[] newArray(int size) { - return new SyncStats[size]; - } - }; -} diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java deleted file mode 100644 index 282f6e7..0000000 --- a/core/java/android/content/SyncStorageEngine.java +++ /dev/null @@ -1,758 +0,0 @@ -package android.content; - -import android.Manifest; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteQueryBuilder; -import android.net.Uri; -import android.provider.Sync; -import android.text.TextUtils; -import android.util.Config; -import android.util.Log; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; - -/** - * ContentProvider that tracks the sync data and overall sync - * history on the device. - * - * @hide - */ -public class SyncStorageEngine { - private static final String TAG = "SyncManager"; - - private static final String DATABASE_NAME = "syncmanager.db"; - private static final int DATABASE_VERSION = 10; - - private static final int STATS = 1; - private static final int STATS_ID = 2; - private static final int HISTORY = 3; - private static final int HISTORY_ID = 4; - private static final int SETTINGS = 5; - private static final int PENDING = 7; - private static final int ACTIVE = 8; - private static final int STATUS = 9; - - private static final UriMatcher sURLMatcher = - new UriMatcher(UriMatcher.NO_MATCH); - - private static final HashMap<String,String> HISTORY_PROJECTION_MAP; - private static final HashMap<String,String> PENDING_PROJECTION_MAP; - private static final HashMap<String,String> ACTIVE_PROJECTION_MAP; - private static final HashMap<String,String> STATUS_PROJECTION_MAP; - - private final Context mContext; - private final SQLiteOpenHelper mOpenHelper; - private static SyncStorageEngine sSyncStorageEngine = null; - - static { - sURLMatcher.addURI("sync", "stats", STATS); - sURLMatcher.addURI("sync", "stats/#", STATS_ID); - sURLMatcher.addURI("sync", "history", HISTORY); - sURLMatcher.addURI("sync", "history/#", HISTORY_ID); - sURLMatcher.addURI("sync", "settings", SETTINGS); - sURLMatcher.addURI("sync", "status", STATUS); - sURLMatcher.addURI("sync", "active", ACTIVE); - sURLMatcher.addURI("sync", "pending", PENDING); - - HashMap<String,String> map; - PENDING_PROJECTION_MAP = map = new HashMap<String,String>(); - map.put(Sync.History._ID, Sync.History._ID); - map.put(Sync.History.ACCOUNT, Sync.History.ACCOUNT); - map.put(Sync.History.AUTHORITY, Sync.History.AUTHORITY); - - ACTIVE_PROJECTION_MAP = map = new HashMap<String,String>(); - map.put(Sync.History._ID, Sync.History._ID); - map.put(Sync.History.ACCOUNT, Sync.History.ACCOUNT); - map.put(Sync.History.AUTHORITY, Sync.History.AUTHORITY); - map.put("startTime", "startTime"); - - HISTORY_PROJECTION_MAP = map = new HashMap<String,String>(); - map.put(Sync.History._ID, "history._id as _id"); - map.put(Sync.History.ACCOUNT, "stats.account as account"); - map.put(Sync.History.AUTHORITY, "stats.authority as authority"); - map.put(Sync.History.EVENT, Sync.History.EVENT); - map.put(Sync.History.EVENT_TIME, Sync.History.EVENT_TIME); - map.put(Sync.History.ELAPSED_TIME, Sync.History.ELAPSED_TIME); - map.put(Sync.History.SOURCE, Sync.History.SOURCE); - map.put(Sync.History.UPSTREAM_ACTIVITY, Sync.History.UPSTREAM_ACTIVITY); - map.put(Sync.History.DOWNSTREAM_ACTIVITY, Sync.History.DOWNSTREAM_ACTIVITY); - map.put(Sync.History.MESG, Sync.History.MESG); - - STATUS_PROJECTION_MAP = map = new HashMap<String,String>(); - map.put(Sync.Status._ID, "status._id as _id"); - map.put(Sync.Status.ACCOUNT, "stats.account as account"); - map.put(Sync.Status.AUTHORITY, "stats.authority as authority"); - map.put(Sync.Status.TOTAL_ELAPSED_TIME, Sync.Status.TOTAL_ELAPSED_TIME); - map.put(Sync.Status.NUM_SYNCS, Sync.Status.NUM_SYNCS); - map.put(Sync.Status.NUM_SOURCE_LOCAL, Sync.Status.NUM_SOURCE_LOCAL); - map.put(Sync.Status.NUM_SOURCE_POLL, Sync.Status.NUM_SOURCE_POLL); - map.put(Sync.Status.NUM_SOURCE_SERVER, Sync.Status.NUM_SOURCE_SERVER); - map.put(Sync.Status.NUM_SOURCE_USER, Sync.Status.NUM_SOURCE_USER); - map.put(Sync.Status.LAST_SUCCESS_SOURCE, Sync.Status.LAST_SUCCESS_SOURCE); - map.put(Sync.Status.LAST_SUCCESS_TIME, Sync.Status.LAST_SUCCESS_TIME); - map.put(Sync.Status.LAST_FAILURE_SOURCE, Sync.Status.LAST_FAILURE_SOURCE); - map.put(Sync.Status.LAST_FAILURE_TIME, Sync.Status.LAST_FAILURE_TIME); - map.put(Sync.Status.LAST_FAILURE_MESG, Sync.Status.LAST_FAILURE_MESG); - map.put(Sync.Status.PENDING, Sync.Status.PENDING); - } - - private static final String[] STATS_ACCOUNT_PROJECTION = - new String[] { Sync.Stats.ACCOUNT }; - - private static final int MAX_HISTORY_EVENTS_TO_KEEP = 5000; - - private static final String SELECT_INITIAL_FAILURE_TIME_QUERY_STRING = "" - + "SELECT min(a) " - + "FROM (" - + " SELECT initialFailureTime AS a " - + " FROM status " - + " WHERE stats_id=? AND a IS NOT NULL " - + " UNION " - + " SELECT ? AS a" - + " )"; - - private SyncStorageEngine(Context context) { - mContext = context; - mOpenHelper = new SyncStorageEngine.DatabaseHelper(context); - sSyncStorageEngine = this; - } - - public static SyncStorageEngine newTestInstance(Context context) { - return new SyncStorageEngine(context); - } - - public static void init(Context context) { - if (sSyncStorageEngine != null) { - throw new IllegalStateException("already initialized"); - } - sSyncStorageEngine = new SyncStorageEngine(context); - } - - public static SyncStorageEngine getSingleton() { - if (sSyncStorageEngine == null) { - throw new IllegalStateException("not initialized"); - } - return sSyncStorageEngine; - } - - private class DatabaseHelper extends SQLiteOpenHelper { - DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE pending (" - + "_id INTEGER PRIMARY KEY," - + "authority TEXT NOT NULL," - + "account TEXT NOT NULL," - + "extras BLOB NOT NULL," - + "source INTEGER NOT NULL" - + ");"); - - db.execSQL("CREATE TABLE stats (" + - "_id INTEGER PRIMARY KEY," + - "account TEXT, " + - "authority TEXT, " + - "syncdata TEXT, " + - "UNIQUE (account, authority)" + - ");"); - - db.execSQL("CREATE TABLE history (" + - "_id INTEGER PRIMARY KEY," + - "stats_id INTEGER," + - "eventTime INTEGER," + - "elapsedTime INTEGER," + - "source INTEGER," + - "event INTEGER," + - "upstreamActivity INTEGER," + - "downstreamActivity INTEGER," + - "mesg TEXT);"); - - db.execSQL("CREATE TABLE status (" - + "_id INTEGER PRIMARY KEY," - + "stats_id INTEGER NOT NULL," - + "totalElapsedTime INTEGER NOT NULL DEFAULT 0," - + "numSyncs INTEGER NOT NULL DEFAULT 0," - + "numSourcePoll INTEGER NOT NULL DEFAULT 0," - + "numSourceServer INTEGER NOT NULL DEFAULT 0," - + "numSourceLocal INTEGER NOT NULL DEFAULT 0," - + "numSourceUser INTEGER NOT NULL DEFAULT 0," - + "lastSuccessTime INTEGER," - + "lastSuccessSource INTEGER," - + "lastFailureTime INTEGER," - + "lastFailureSource INTEGER," - + "lastFailureMesg STRING," - + "initialFailureTime INTEGER," - + "pending INTEGER NOT NULL DEFAULT 0);"); - - db.execSQL("CREATE TABLE active (" - + "_id INTEGER PRIMARY KEY," - + "authority TEXT," - + "account TEXT," - + "startTime INTEGER);"); - - db.execSQL("CREATE INDEX historyEventTime ON history (eventTime)"); - - db.execSQL("CREATE TABLE settings (" + - "name TEXT PRIMARY KEY," + - "value TEXT);"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion == 9 && newVersion == 10) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will preserve old data"); - db.execSQL("ALTER TABLE status ADD COLUMN initialFailureTime INTEGER"); - return; - } - - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS pending"); - db.execSQL("DROP TABLE IF EXISTS stats"); - db.execSQL("DROP TABLE IF EXISTS history"); - db.execSQL("DROP TABLE IF EXISTS settings"); - db.execSQL("DROP TABLE IF EXISTS active"); - db.execSQL("DROP TABLE IF EXISTS status"); - onCreate(db); - } - - @Override - public void onOpen(SQLiteDatabase db) { - if (!db.isReadOnly()) { - db.delete("active", null, null); - db.insert("active", "account", null); - } - } - } - - protected void doDatabaseCleanup(String[] accounts) { - HashSet<String> currentAccounts = new HashSet<String>(); - for (String account : accounts) currentAccounts.add(account); - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - Cursor cursor = db.query("stats", STATS_ACCOUNT_PROJECTION, - null /* where */, null /* where args */, Sync.Stats.ACCOUNT, - null /* having */, null /* order by */); - try { - while (cursor.moveToNext()) { - String account = cursor.getString(0); - if (TextUtils.isEmpty(account)) { - continue; - } - if (!currentAccounts.contains(account)) { - String where = Sync.Stats.ACCOUNT + "=?"; - int numDeleted; - numDeleted = db.delete("stats", where, new String[]{account}); - if (Config.LOGD) { - Log.d(TAG, "deleted " + numDeleted - + " records from stats table" - + " for account " + account); - } - } - } - } finally { - cursor.close(); - } - } - - protected void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) { - if (activeSyncContext != null) { - updateActiveSync(activeSyncContext.mSyncOperation.account, - activeSyncContext.mSyncOperation.authority, activeSyncContext.mStartTime); - } else { - // we indicate that the sync is not active by passing null for all the parameters - updateActiveSync(null, null, null); - } - } - - private int updateActiveSync(String account, String authority, Long startTime) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put("account", account); - values.put("authority", authority); - values.put("startTime", startTime); - int numChanges = db.update("active", values, null, null); - if (numChanges > 0) { - mContext.getContentResolver().notifyChange(Sync.Active.CONTENT_URI, - null /* this change wasn't made through an observer */); - } - return numChanges; - } - - /** - * Implements the {@link ContentProvider#query} method - */ - public Cursor query(Uri url, String[] projectionIn, - String selection, String[] selectionArgs, String sort) { - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - // Generate the body of the query - int match = sURLMatcher.match(url); - String groupBy = null; - switch (match) { - case STATS: - qb.setTables("stats"); - break; - case STATS_ID: - qb.setTables("stats"); - qb.appendWhere("_id="); - qb.appendWhere(url.getPathSegments().get(1)); - break; - case HISTORY: - // join the stats and history tables, so the caller can get - // the account and authority information as part of this query. - qb.setTables("stats, history"); - qb.setProjectionMap(HISTORY_PROJECTION_MAP); - qb.appendWhere("stats._id = history.stats_id"); - break; - case ACTIVE: - qb.setTables("active"); - qb.setProjectionMap(ACTIVE_PROJECTION_MAP); - qb.appendWhere("account is not null"); - break; - case PENDING: - qb.setTables("pending"); - qb.setProjectionMap(PENDING_PROJECTION_MAP); - groupBy = "account, authority"; - break; - case STATUS: - // join the stats and status tables, so the caller can get - // the account and authority information as part of this query. - qb.setTables("stats, status"); - qb.setProjectionMap(STATUS_PROJECTION_MAP); - qb.appendWhere("stats._id = status.stats_id"); - break; - case HISTORY_ID: - // join the stats and history tables, so the caller can get - // the account and authority information as part of this query. - qb.setTables("stats, history"); - qb.setProjectionMap(HISTORY_PROJECTION_MAP); - qb.appendWhere("stats._id = history.stats_id"); - qb.appendWhere("AND history._id="); - qb.appendWhere(url.getPathSegments().get(1)); - break; - case SETTINGS: - qb.setTables("settings"); - break; - default: - throw new IllegalArgumentException("Unknown URL " + url); - } - - if (match == SETTINGS) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS, - "no permission to read the sync settings"); - } else { - mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, - "no permission to read the sync stats"); - } - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - Cursor c = qb.query(db, projectionIn, selection, selectionArgs, groupBy, null, sort); - c.setNotificationUri(mContext.getContentResolver(), url); - return c; - } - - /** - * Implements the {@link ContentProvider#insert} method - * @param callerIsTheProvider true if this is being called via the - * {@link ContentProvider#insert} in method rather than directly. - * @throws UnsupportedOperationException if callerIsTheProvider is true and the url isn't - * for the Settings table. - */ - public Uri insert(boolean callerIsTheProvider, Uri url, ContentValues values) { - String table; - long rowID; - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - final int match = sURLMatcher.match(url); - checkCaller(callerIsTheProvider, match); - switch (match) { - case SETTINGS: - mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, - "no permission to write the sync settings"); - table = "settings"; - rowID = db.replace(table, null, values); - break; - default: - throw new IllegalArgumentException("Unknown URL " + url); - } - - - if (rowID > 0) { - mContext.getContentResolver().notifyChange(url, null /* observer */); - return Uri.parse("content://sync/" + table + "/" + rowID); - } - - return null; - } - - private static void checkCaller(boolean callerIsTheProvider, int match) { - if (callerIsTheProvider && match != SETTINGS) { - throw new UnsupportedOperationException( - "only the settings are modifiable via the ContentProvider interface"); - } - } - - /** - * Implements the {@link ContentProvider#delete} method - * @param callerIsTheProvider true if this is being called via the - * {@link ContentProvider#delete} in method rather than directly. - * @throws UnsupportedOperationException if callerIsTheProvider is true and the url isn't - * for the Settings table. - */ - public int delete(boolean callerIsTheProvider, Uri url, String where, String[] whereArgs) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int match = sURLMatcher.match(url); - - int numRows; - switch (match) { - case SETTINGS: - mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, - "no permission to write the sync settings"); - numRows = db.delete("settings", where, whereArgs); - break; - default: - throw new UnsupportedOperationException("Cannot delete URL: " + url); - } - - if (numRows > 0) { - mContext.getContentResolver().notifyChange(url, null /* observer */); - } - return numRows; - } - - /** - * Implements the {@link ContentProvider#update} method - * @param callerIsTheProvider true if this is being called via the - * {@link ContentProvider#update} in method rather than directly. - * @throws UnsupportedOperationException if callerIsTheProvider is true and the url isn't - * for the Settings table. - */ - public int update(boolean callerIsTheProvider, Uri url, ContentValues initialValues, - String where, String[] whereArgs) { - switch (sURLMatcher.match(url)) { - case SETTINGS: - throw new UnsupportedOperationException("updating url " + url - + " is not allowed, use insert instead"); - default: - throw new UnsupportedOperationException("Cannot update URL: " + url); - } - } - - /** - * Implements the {@link ContentProvider#getType} method - */ - public String getType(Uri url) { - int match = sURLMatcher.match(url); - switch (match) { - case SETTINGS: - return "vnd.android.cursor.dir/sync-settings"; - default: - throw new IllegalArgumentException("Unknown URL"); - } - } - - protected Uri insertIntoPending(ContentValues values) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - try { - db.beginTransaction(); - long rowId = db.insert("pending", Sync.Pending.ACCOUNT, values); - if (rowId < 0) return null; - String account = values.getAsString(Sync.Pending.ACCOUNT); - String authority = values.getAsString(Sync.Pending.AUTHORITY); - - long statsId = createStatsRowIfNecessary(account, authority); - createStatusRowIfNecessary(statsId); - - values.clear(); - values.put(Sync.Status.PENDING, 1); - int numUpdatesStatus = db.update("status", values, "stats_id=" + statsId, null); - - db.setTransactionSuccessful(); - - mContext.getContentResolver().notifyChange(Sync.Pending.CONTENT_URI, - null /* no observer initiated this change */); - if (numUpdatesStatus > 0) { - mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI, - null /* no observer initiated this change */); - } - return ContentUris.withAppendedId(Sync.Pending.CONTENT_URI, rowId); - } finally { - db.endTransaction(); - } - } - - int deleteFromPending(long rowId) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - String account; - String authority; - Cursor c = db.query("pending", - new String[]{Sync.Pending.ACCOUNT, Sync.Pending.AUTHORITY}, - "_id=" + rowId, null, null, null, null); - try { - if (c.getCount() != 1) { - return 0; - } - c.moveToNext(); - account = c.getString(0); - authority = c.getString(1); - } finally { - c.close(); - } - db.delete("pending", "_id=" + rowId, null /* no where args */); - final String[] accountAuthorityWhereArgs = new String[]{account, authority}; - boolean isPending = 0 < DatabaseUtils.longForQuery(db, - "SELECT COUNT(*) FROM PENDING WHERE account=? AND authority=?", - accountAuthorityWhereArgs); - if (!isPending) { - long statsId = createStatsRowIfNecessary(account, authority); - db.execSQL("UPDATE status SET pending=0 WHERE stats_id=" + statsId); - } - db.setTransactionSuccessful(); - - mContext.getContentResolver().notifyChange(Sync.Pending.CONTENT_URI, - null /* no observer initiated this change */); - if (!isPending) { - mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI, - null /* no observer initiated this change */); - } - return 1; - } finally { - db.endTransaction(); - } - } - - int clearPending() { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - int numChanges = db.delete("pending", null, null /* no where args */); - if (numChanges > 0) { - db.execSQL("UPDATE status SET pending=0"); - mContext.getContentResolver().notifyChange(Sync.Pending.CONTENT_URI, - null /* no observer initiated this change */); - mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI, - null /* no observer initiated this change */); - } - db.setTransactionSuccessful(); - return numChanges; - } finally { - db.endTransaction(); - } - } - - /** - * Returns a cursor over all the pending syncs in no particular order. This cursor is not - * "live", in that if changes are made to the pending table any observers on this cursor - * will not be notified. - * @param projection Return only these columns. If null then all columns are returned. - * @return the cursor of pending syncs - */ - public Cursor getPendingSyncsCursor(String[] projection) { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - return db.query("pending", projection, null, null, null, null, null); - } - - // @VisibleForTesting - static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4; - - private boolean purgeOldHistoryEvents(long now) { - // remove events that are older than MILLIS_IN_4WEEKS - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int numDeletes = db.delete("history", "eventTime<" + (now - MILLIS_IN_4WEEKS), null); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - if (numDeletes > 0) { - Log.v(TAG, "deleted " + numDeletes + " old event(s) from the sync history"); - } - } - - // keep only the last MAX_HISTORY_EVENTS_TO_KEEP history events - numDeletes += db.delete("history", "eventTime < (select min(eventTime) from " - + "(select eventTime from history order by eventTime desc limit ?))", - new String[]{String.valueOf(MAX_HISTORY_EVENTS_TO_KEEP)}); - - return numDeletes > 0; - } - - public long insertStartSyncEvent(String account, String authority, long now, int source) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - long statsId = createStatsRowIfNecessary(account, authority); - - purgeOldHistoryEvents(now); - ContentValues values = new ContentValues(); - values.put(Sync.History.STATS_ID, statsId); - values.put(Sync.History.EVENT_TIME, now); - values.put(Sync.History.SOURCE, source); - values.put(Sync.History.EVENT, Sync.History.EVENT_START); - long rowId = db.insert("history", null, values); - mContext.getContentResolver().notifyChange(Sync.History.CONTENT_URI, null /* observer */); - mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI, null /* observer */); - return rowId; - } - - public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage, - long downstreamActivity, long upstreamActivity) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - ContentValues values = new ContentValues(); - values.put(Sync.History.ELAPSED_TIME, elapsedTime); - values.put(Sync.History.EVENT, Sync.History.EVENT_STOP); - values.put(Sync.History.MESG, resultMessage); - values.put(Sync.History.DOWNSTREAM_ACTIVITY, downstreamActivity); - values.put(Sync.History.UPSTREAM_ACTIVITY, upstreamActivity); - - int count = db.update("history", values, "_id=?", - new String[]{Long.toString(historyId)}); - // We think that count should always be 1 but don't want to change this until after - // launch. - if (count > 0) { - int source = (int) DatabaseUtils.longForQuery(db, - "SELECT source FROM history WHERE _id=" + historyId, null); - long eventTime = DatabaseUtils.longForQuery(db, - "SELECT eventTime FROM history WHERE _id=" + historyId, null); - long statsId = DatabaseUtils.longForQuery(db, - "SELECT stats_id FROM history WHERE _id=" + historyId, null); - - createStatusRowIfNecessary(statsId); - - // update the status table to reflect this sync - StringBuilder sb = new StringBuilder(); - ArrayList<String> bindArgs = new ArrayList<String>(); - sb.append("UPDATE status SET"); - sb.append(" numSyncs=numSyncs+1"); - sb.append(", totalElapsedTime=totalElapsedTime+" + elapsedTime); - switch (source) { - case Sync.History.SOURCE_LOCAL: - sb.append(", numSourceLocal=numSourceLocal+1"); - break; - case Sync.History.SOURCE_POLL: - sb.append(", numSourcePoll=numSourcePoll+1"); - break; - case Sync.History.SOURCE_USER: - sb.append(", numSourceUser=numSourceUser+1"); - break; - case Sync.History.SOURCE_SERVER: - sb.append(", numSourceServer=numSourceServer+1"); - break; - } - - final String statsIdString = String.valueOf(statsId); - final long lastSyncTime = (eventTime + elapsedTime); - if (Sync.History.MESG_SUCCESS.equals(resultMessage)) { - // - if successful, update the successful columns - sb.append(", lastSuccessTime=" + lastSyncTime); - sb.append(", lastSuccessSource=" + source); - sb.append(", lastFailureTime=null"); - sb.append(", lastFailureSource=null"); - sb.append(", lastFailureMesg=null"); - sb.append(", initialFailureTime=null"); - } else if (!Sync.History.MESG_CANCELED.equals(resultMessage)) { - sb.append(", lastFailureTime=" + lastSyncTime); - sb.append(", lastFailureSource=" + source); - sb.append(", lastFailureMesg=?"); - bindArgs.add(resultMessage); - long initialFailureTime = DatabaseUtils.longForQuery(db, - SELECT_INITIAL_FAILURE_TIME_QUERY_STRING, - new String[]{statsIdString, String.valueOf(lastSyncTime)}); - sb.append(", initialFailureTime=" + initialFailureTime); - } - sb.append(" WHERE stats_id=?"); - bindArgs.add(statsIdString); - db.execSQL(sb.toString(), bindArgs.toArray()); - db.setTransactionSuccessful(); - mContext.getContentResolver().notifyChange(Sync.History.CONTENT_URI, - null /* observer */); - mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI, - null /* observer */); - } - } finally { - db.endTransaction(); - } - } - - /** - * If sync is failing for any of the provider/accounts then determine the time at which it - * started failing and return the earliest time over all the provider/accounts. If none are - * failing then return 0. - */ - public long getInitialSyncFailureTime() { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - // Join the settings for a provider with the status so that we can easily - // check if each provider is enabled for syncing. We also join in the overall - // enabled flag ("listen_for_tickles") to each row so that we don't need to - // make a separate DB lookup to access it. - Cursor c = db.rawQuery("" - + "SELECT initialFailureTime, s1.value, s2.value " - + "FROM status " - + "LEFT JOIN stats ON status.stats_id=stats._id " - + "LEFT JOIN settings as s1 ON 'sync_provider_' || authority=s1.name " - + "LEFT JOIN settings as s2 ON s2.name='listen_for_tickles' " - + "where initialFailureTime is not null " - + " AND lastFailureMesg!=" + Sync.History.ERROR_TOO_MANY_DELETIONS - + " AND lastFailureMesg!=" + Sync.History.ERROR_AUTHENTICATION - + " AND lastFailureMesg!=" + Sync.History.ERROR_SYNC_ALREADY_IN_PROGRESS - + " AND authority!='subscribedfeeds' " - + " ORDER BY initialFailureTime", null); - try { - while (c.moveToNext()) { - // these settings default to true, so if they are null treat them as enabled - final String providerEnabledString = c.getString(1); - if (providerEnabledString != null && !Boolean.parseBoolean(providerEnabledString)) { - continue; - } - final String allEnabledString = c.getString(2); - if (allEnabledString != null && !Boolean.parseBoolean(allEnabledString)) { - continue; - } - return c.getLong(0); - } - } finally { - c.close(); - } - return 0; - } - - private void createStatusRowIfNecessary(long statsId) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - boolean statusExists = 0 != DatabaseUtils.longForQuery(db, - "SELECT count(*) FROM status WHERE stats_id=" + statsId, null); - if (!statusExists) { - ContentValues values = new ContentValues(); - values.put("stats_id", statsId); - db.insert("status", null, values); - } - } - - private long createStatsRowIfNecessary(String account, String authority) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - StringBuilder where = new StringBuilder(); - where.append(Sync.Stats.ACCOUNT + "= ?"); - where.append(" and " + Sync.Stats.AUTHORITY + "= ?"); - Cursor cursor = query(Sync.Stats.CONTENT_URI, - Sync.Stats.SYNC_STATS_PROJECTION, - where.toString(), new String[] { account, authority }, - null /* order */); - try { - long id; - if (cursor.moveToFirst()) { - id = cursor.getLong(cursor.getColumnIndexOrThrow(Sync.Stats._ID)); - } else { - ContentValues values = new ContentValues(); - values.put(Sync.Stats.ACCOUNT, account); - values.put(Sync.Stats.AUTHORITY, authority); - id = db.insert("stats", null, values); - } - return id; - } finally { - cursor.close(); - } - } -} diff --git a/core/java/android/content/SyncUIContext.java b/core/java/android/content/SyncUIContext.java deleted file mode 100644 index 6dde004..0000000 --- a/core/java/android/content/SyncUIContext.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2006 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; - -/** - * Class with callback methods for SyncAdapters and ContentProviders - * that are called in response to the calls on SyncContext. This class - * is really only meant to be used by the Sync UI activities. - * - * <p>All of the onXXX callback methods here are called from a handler - * on the thread this object was created in. - * - * <p>This interface is unused. It should be removed. - * - * @hide - */ -@Deprecated -public interface SyncUIContext { - - void setStatusText(String text); - - Context context(); -} diff --git a/core/java/android/content/SyncableContentProvider.java b/core/java/android/content/SyncableContentProvider.java deleted file mode 100644 index e0cd786..0000000 --- a/core/java/android/content/SyncableContentProvider.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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 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(); - - /** - * 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, String 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 String 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(String[] 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 - * @param accountColumnName the name of the column that is expected - * to hold the account. - */ - protected abstract void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts, - String table, String accountColumnName); - - /** - * Called when the sync system determines that this provider should no longer - * contain records for the specified account. - */ - public abstract void wipeAccount(String account); - - /** - * Retrieves the SyncData bytes for the given account. The byte array returned may be null. - */ - public abstract byte[] readSyncDataBytes(String account); - - /** - * Sets the SyncData bytes for the given account. The bytes array may be null. - */ - public abstract void writeSyncDataBytes(String account, byte[] data); -} - diff --git a/core/java/android/content/TempProviderSyncAdapter.java b/core/java/android/content/TempProviderSyncAdapter.java deleted file mode 100644 index eb3a5da..0000000 --- a/core/java/android/content/TempProviderSyncAdapter.java +++ /dev/null @@ -1,550 +0,0 @@ -package android.content; - -import android.database.SQLException; -import android.os.Bundle; -import android.os.Debug; -import android.os.NetStat; -import android.os.Parcelable; -import android.os.Process; -import android.os.SystemProperties; -import android.text.TextUtils; -import android.util.Config; -import android.util.EventLog; -import android.util.Log; -import android.util.TimingLogger; - -/** - * @hide - */ -public abstract class TempProviderSyncAdapter extends SyncAdapter { - private static final String TAG = "Sync"; - - private static final int MAX_GET_SERVER_DIFFS_LOOP_COUNT = 20; - private static final int MAX_UPLOAD_CHANGES_LOOP_COUNT = 10; - private static final int NUM_ALLOWED_SIMULTANEOUS_DELETIONS = 5; - private static final long PERCENT_ALLOWED_SIMULTANEOUS_DELETIONS = 20; - - private volatile SyncableContentProvider mProvider; - private volatile SyncThread mSyncThread = null; - private volatile boolean mProviderSyncStarted; - private volatile boolean mAdapterSyncStarted; - - public TempProviderSyncAdapter(SyncableContentProvider provider) { - super(); - mProvider = provider; - } - - /** - * Used by getServerDiffs() to track the sync progress for a given - * sync adapter. Implementations of SyncAdapter generally specialize - * this class in order to track specific data about that SyncAdapter's - * sync. If an implementation of SyncAdapter doesn't need to store - * any data for a sync it may use TrivialSyncData. - */ - public static abstract class SyncData implements Parcelable { - - } - - public final void setContext(Context context) { - mContext = context; - } - - /** - * Retrieve the Context this adapter is running in. Only available - * once onSyncStarting() is called (not available from constructor). - */ - final public Context getContext() { - return mContext; - } - - /** - * Called right before a sync is started. - * - * @param context allows you to publish status and interact with the - * @param account the account to sync - * @param forced if true then the sync was forced - * @param result information to track what happened during this sync attempt - * @return true, if the sync was successfully started. One reason it can - * fail to start is if there is no user configured on the device. - */ - public abstract void onSyncStarting(SyncContext context, String account, boolean forced, - SyncResult result); - - /** - * Called right after a sync is completed - * - * @param context allows you to publish status and interact with the - * user during interactive syncs. - * @param success true if the sync suceeded, false if an error occured - */ - public abstract void onSyncEnding(SyncContext context, boolean success); - - /** - * Implement this to return true if the data in your content provider - * is read only. - */ - public abstract boolean isReadOnly(); - - /** - * Get diffs from the server since the last completed sync and put them - * into a temporary provider. - * - * @param context allows you to publish status and interact with the - * user during interactive syncs. - * @param syncData used to track the progress this client has made in syncing data - * from the server - * @param tempProvider this is where the diffs should be stored - * @param extras any extra data describing the sync that is desired - * @param syncInfo sync adapter-specific data that is used during a single sync operation - * @param syncResult information to track what happened during this sync attempt - */ - public abstract void getServerDiffs(SyncContext context, - SyncData syncData, SyncableContentProvider tempProvider, - Bundle extras, Object syncInfo, SyncResult syncResult); - - /** - * Send client diffs to the server, optionally receiving more diffs from the server - * - * @param context allows you to publish status and interact with the - * user during interactive syncs. - * @param clientDiffs the diffs from the client - * @param serverDiffs the SyncableContentProvider that should be populated with -* the entries that were returned in response to an insert/update/delete request -* to the server - * @param syncResult information to track what happened during this sync attempt - * @param dontActuallySendDeletes - */ - public abstract void sendClientDiffs(SyncContext context, - SyncableContentProvider clientDiffs, - SyncableContentProvider serverDiffs, SyncResult syncResult, - boolean dontActuallySendDeletes); - - /** - * Reads the sync data from the ContentProvider - * @param contentProvider the ContentProvider to read from - * @return the SyncData for the provider. This may be null. - */ - public SyncData readSyncData(SyncableContentProvider contentProvider) { - return null; - } - - /** - * Create and return a new, empty SyncData object - */ - public SyncData newSyncData() { - return null; - } - - /** - * Stores the sync data in the Sync Stats database, keying it by - * the account that was set in the last call to onSyncStarting() - */ - public void writeSyncData(SyncData syncData, SyncableContentProvider contentProvider) {} - - /** - * Indicate to the SyncAdapter that the last sync that was started has - * been cancelled. - */ - public abstract void onSyncCanceled(); - - /** - * Initializes the temporary content providers used during - * {@link TempProviderSyncAdapter#sendClientDiffs}. - * May copy relevant data from the underlying db into this provider so - * joins, etc., can work. - * - * @param cp The ContentProvider to initialize. - */ - protected void initTempProvider(SyncableContentProvider cp) {} - - protected Object createSyncInfo() { - return null; - } - - /** - * Called when the accounts list possibly changed, to give the - * SyncAdapter a chance to do any necessary bookkeeping, e.g. - * to make sure that any required SubscribedFeeds subscriptions - * exist. - * @param accounts the list of accounts - */ - public abstract void onAccountsChanged(String[] accounts); - - private Context mContext; - - private class SyncThread extends Thread { - private final String mAccount; - private final Bundle mExtras; - private final SyncContext mSyncContext; - private volatile boolean mIsCanceled = false; - private long mInitialTxBytes; - private long mInitialRxBytes; - private final SyncResult mResult; - - SyncThread(SyncContext syncContext, String account, Bundle extras) { - super("SyncThread"); - mAccount = account; - mExtras = extras; - mSyncContext = syncContext; - mResult = new SyncResult(); - } - - void cancelSync() { - mIsCanceled = true; - if (mAdapterSyncStarted) onSyncCanceled(); - if (mProviderSyncStarted) mProvider.onSyncCanceled(); - // We may lose the last few sync events when canceling. Oh well. - int uid = Process.myUid(); - logSyncDetails(NetStat.getUidTxBytes(uid) - mInitialTxBytes, - NetStat.getUidRxBytes(uid) - mInitialRxBytes, mResult); - } - - @Override - public void run() { - Process.setThreadPriority(Process.myTid(), - Process.THREAD_PRIORITY_BACKGROUND); - int uid = Process.myUid(); - mInitialTxBytes = NetStat.getUidTxBytes(uid); - mInitialRxBytes = NetStat.getUidRxBytes(uid); - try { - sync(mSyncContext, mAccount, mExtras); - } catch (SQLException e) { - Log.e(TAG, "Sync failed", e); - mResult.databaseError = true; - } finally { - mSyncThread = null; - if (!mIsCanceled) { - logSyncDetails(NetStat.getUidTxBytes(uid) - mInitialTxBytes, - NetStat.getUidRxBytes(uid) - mInitialRxBytes, mResult); - mSyncContext.onFinished(mResult); - } - } - } - - private void sync(SyncContext syncContext, String account, Bundle extras) { - mIsCanceled = false; - - mProviderSyncStarted = false; - mAdapterSyncStarted = false; - String message = null; - - boolean syncForced = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false); - - try { - mProvider.onSyncStart(syncContext, account); - mProviderSyncStarted = true; - onSyncStarting(syncContext, account, syncForced, mResult); - if (mResult.hasError()) { - message = "SyncAdapter failed while trying to start sync"; - return; - } - mAdapterSyncStarted = true; - if (mIsCanceled) { - return; - } - final String syncTracingEnabledValue = SystemProperties.get(TAG + "Tracing"); - final boolean syncTracingEnabled = !TextUtils.isEmpty(syncTracingEnabledValue); - try { - if (syncTracingEnabled) { - System.gc(); - System.gc(); - Debug.startMethodTracing("synctrace." + System.currentTimeMillis()); - } - runSyncLoop(syncContext, account, extras); - } finally { - if (syncTracingEnabled) Debug.stopMethodTracing(); - } - onSyncEnding(syncContext, !mResult.hasError()); - mAdapterSyncStarted = false; - mProvider.onSyncStop(syncContext, true); - mProviderSyncStarted = false; - } finally { - if (mAdapterSyncStarted) { - mAdapterSyncStarted = false; - onSyncEnding(syncContext, false); - } - if (mProviderSyncStarted) { - mProviderSyncStarted = false; - mProvider.onSyncStop(syncContext, false); - } - if (!mIsCanceled) { - if (message != null) syncContext.setStatusText(message); - } - } - } - - private void runSyncLoop(SyncContext syncContext, String account, Bundle extras) { - TimingLogger syncTimer = new TimingLogger(TAG + "Profiling", "sync"); - syncTimer.addSplit("start"); - int loopCount = 0; - boolean tooManyGetServerDiffsAttempts = false; - - final boolean overrideTooManyDeletions = - extras.getBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS, - false); - final boolean discardLocalDeletions = - extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS, false); - boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, - false /* default this flag to false */); - SyncableContentProvider serverDiffs = null; - TempProviderSyncResult result = new TempProviderSyncResult(); - try { - if (!uploadOnly) { - /** - * This loop repeatedly calls SyncAdapter.getServerDiffs() - * (to get changes from the feed) followed by - * ContentProvider.merge() (to incorporate these changes - * into the provider), stopping when the SyncData returned - * from getServerDiffs() indicates that all the data was - * fetched. - */ - while (!mIsCanceled) { - // Don't let a bad sync go forever - if (loopCount++ == MAX_GET_SERVER_DIFFS_LOOP_COUNT) { - Log.e(TAG, "runSyncLoop: Hit max loop count while getting server diffs " - + getClass().getName()); - // TODO: change the structure here to schedule a new sync - // with a backoff time, keeping track to be sure - // we don't keep doing this forever (due to some bug or - // mismatch between the client and the server) - tooManyGetServerDiffsAttempts = true; - break; - } - - // Get an empty content provider to put the diffs into - if (serverDiffs != null) serverDiffs.close(); - serverDiffs = mProvider.getTemporaryInstance(); - - // Get records from the server which will be put into the serverDiffs - initTempProvider(serverDiffs); - Object syncInfo = createSyncInfo(); - SyncData syncData = readSyncData(serverDiffs); - // syncData will only be null if there was a demarshalling error - // while reading the sync data. - if (syncData == null) { - mProvider.wipeAccount(account); - syncData = newSyncData(); - } - mResult.clear(); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: running getServerDiffs using syncData " - + syncData.toString()); - } - getServerDiffs(syncContext, syncData, serverDiffs, extras, syncInfo, - mResult); - - if (mIsCanceled) return; - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: result: " + mResult); - } - if (mResult.hasError()) return; - if (mResult.partialSyncUnavailable) { - if (Config.LOGD) { - Log.d(TAG, "partialSyncUnavailable is set, setting " - + "ignoreSyncData and retrying"); - } - mProvider.wipeAccount(account); - continue; - } - - // write the updated syncData back into the temp provider - writeSyncData(syncData, serverDiffs); - - // apply the downloaded changes to the provider - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: running merge"); - } - mProvider.merge(syncContext, serverDiffs, - null /* don't return client diffs */, mResult); - if (mIsCanceled) return; - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: result: " + mResult); - } - - // if the server has no more changes then break out of the loop - if (!mResult.moreRecordsToGet) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: fetched all data, moving on"); - } - break; - } - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: more data to fetch, looping"); - } - } - } - - /** - * This loop repeatedly calls ContentProvider.merge() followed - * by SyncAdapter.merge() until either indicate that there is - * no more work to do by returning null. - * <p> - * The initial ContentProvider.merge() returns a temporary - * ContentProvider that contains any local changes that need - * to be committed to the server. - * <p> - * The SyncAdapter.merge() calls upload the changes to the server - * and populates temporary provider (the serverDiffs) with the - * result. - * <p> - * Subsequent calls to ContentProvider.merge() incoporate the - * result of previous SyncAdapter.merge() calls into the - * real ContentProvider and again return a temporary - * ContentProvider that contains any local changes that need - * to be committed to the server. - */ - loopCount = 0; - boolean readOnly = isReadOnly(); - long previousNumModifications = 0; - if (serverDiffs != null) { - serverDiffs.close(); - serverDiffs = null; - } - - // If we are discarding local deletions then we need to redownload all the items - // again (since some of them might have been deleted). We do this by deleting the - // sync data for the current account by writing in a null one. - if (discardLocalDeletions) { - serverDiffs = mProvider.getTemporaryInstance(); - initTempProvider(serverDiffs); - writeSyncData(null, serverDiffs); - } - - while (!mIsCanceled) { - if (Config.LOGV) { - Log.v(TAG, "runSyncLoop: Merging diffs from server to client"); - } - if (result.tempContentProvider != null) { - result.tempContentProvider.close(); - result.tempContentProvider = null; - } - mResult.clear(); - mProvider.merge(syncContext, serverDiffs, readOnly ? null : result, - mResult); - if (mIsCanceled) return; - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: result: " + mResult); - } - - SyncableContentProvider clientDiffs = - readOnly ? null : result.tempContentProvider; - if (clientDiffs == null) { - // Nothing to commit back to the server - if (Config.LOGV) Log.v(TAG, "runSyncLoop: No client diffs"); - break; - } - - long numModifications = mResult.stats.numUpdates - + mResult.stats.numDeletes - + mResult.stats.numInserts; - - // as long as we are making progress keep resetting the loop count - if (numModifications < previousNumModifications) { - loopCount = 0; - } - previousNumModifications = numModifications; - - // Don't let a bad sync go forever - if (loopCount++ >= MAX_UPLOAD_CHANGES_LOOP_COUNT) { - Log.e(TAG, "runSyncLoop: Hit max loop count while syncing " - + getClass().getName()); - mResult.tooManyRetries = true; - break; - } - - if (!overrideTooManyDeletions && !discardLocalDeletions - && hasTooManyDeletions(mResult.stats)) { - if (Config.LOGD) { - Log.d(TAG, "runSyncLoop: Too many deletions were found in provider " - + getClass().getName() + ", not doing any more updates"); - } - long numDeletes = mResult.stats.numDeletes; - mResult.stats.clear(); - mResult.tooManyDeletions = true; - mResult.stats.numDeletes = numDeletes; - break; - } - - if (Config.LOGV) Log.v(TAG, "runSyncLoop: Merging diffs from client to server"); - if (serverDiffs != null) serverDiffs.close(); - serverDiffs = clientDiffs.getTemporaryInstance(); - initTempProvider(serverDiffs); - mResult.clear(); - sendClientDiffs(syncContext, clientDiffs, serverDiffs, mResult, - discardLocalDeletions); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: result: " + mResult); - } - - if (!mResult.madeSomeProgress()) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: No data from client diffs merge"); - } - break; - } - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: made some progress, looping"); - } - } - - // add in any status codes that we saved from earlier - mResult.tooManyRetries |= tooManyGetServerDiffsAttempts; - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "runSyncLoop: final result: " + mResult); - } - } finally { - // do this in the finally block to guarantee that is is set and not overwritten - if (discardLocalDeletions) { - mResult.fullSyncRequested = true; - } - if (serverDiffs != null) serverDiffs.close(); - if (result.tempContentProvider != null) result.tempContentProvider.close(); - syncTimer.addSplit("stop"); - syncTimer.dumpToLog(); - } - } - } - - /** - * Logs details on the sync. - * Normally this will be overridden by a subclass that will provide - * provider-specific details. - * - * @param bytesSent number of bytes the sync sent over the network - * @param bytesReceived number of bytes the sync received over the network - * @param result The SyncResult object holding info on the sync - */ - protected void logSyncDetails(long bytesSent, long bytesReceived, SyncResult result) { - EventLog.writeEvent(SyncAdapter.LOG_SYNC_DETAILS, TAG, bytesSent, bytesReceived, ""); - } - - public void startSync(SyncContext syncContext, String account, Bundle extras) { - if (mSyncThread != null) { - syncContext.onFinished(SyncResult.ALREADY_IN_PROGRESS); - return; - } - - mSyncThread = new SyncThread(syncContext, account, extras); - mSyncThread.start(); - } - - public void cancelSync() { - if (mSyncThread != null) { - mSyncThread.cancelSync(); - } - } - - protected boolean hasTooManyDeletions(SyncStats stats) { - long numEntries = stats.numEntries; - long numDeletedEntries = stats.numDeletes; - - long percentDeleted = (numDeletedEntries == 0) - ? 0 - : (100 * numDeletedEntries / - (numEntries + numDeletedEntries)); - boolean tooManyDeletions = - (numDeletedEntries > NUM_ALLOWED_SIMULTANEOUS_DELETIONS) - && (percentDeleted > PERCENT_ALLOWED_SIMULTANEOUS_DELETIONS); - return tooManyDeletions; - } -} diff --git a/core/java/android/content/TempProviderSyncResult.java b/core/java/android/content/TempProviderSyncResult.java deleted file mode 100644 index 81f6f79..0000000 --- a/core/java/android/content/TempProviderSyncResult.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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; - -/** - * Used to hold data returned from a given phase of a TempProviderSync. - * @hide - */ -public class TempProviderSyncResult { - /** - * An interface to a temporary content provider that contains - * the result of updates that were sent to the server. This - * provider must be merged into the permanent content provider. - * This may be null, which indicates that there is nothing to - * merge back into the content provider. - */ - public SyncableContentProvider tempContentProvider; - - public TempProviderSyncResult() { - tempContentProvider = null; - } -} diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java deleted file mode 100644 index a98e6d5..0000000 --- a/core/java/android/content/UriMatcher.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2006 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.net.Uri; - -import java.util.ArrayList; -import java.util.regex.Pattern; - -/** -Utility class to aid in matching URIs in content providers. - -<p>To use this class, build up a tree of UriMatcher objects. -Typically, it looks something like this: -<pre> - private static final int PEOPLE = 1; - private static final int PEOPLE_ID = 2; - private static final int PEOPLE_PHONES = 3; - private static final int PEOPLE_PHONES_ID = 4; - private static final int PEOPLE_CONTACTMETHODS = 7; - private static final int PEOPLE_CONTACTMETHODS_ID = 8; - - private static final int DELETED_PEOPLE = 20; - - private static final int PHONES = 9; - private static final int PHONES_ID = 10; - private static final int PHONES_FILTER = 14; - - private static final int CONTACTMETHODS = 18; - private static final int CONTACTMETHODS_ID = 19; - - private static final int CALLS = 11; - private static final int CALLS_ID = 12; - private static final int CALLS_FILTER = 15; - - private static final UriMatcher sURIMatcher = new UriMatcher(); - - static - { - sURIMatcher.addURI("contacts", "/people", PEOPLE); - sURIMatcher.addURI("contacts", "/people/#", PEOPLE_ID); - sURIMatcher.addURI("contacts", "/people/#/phones", PEOPLE_PHONES); - sURIMatcher.addURI("contacts", "/people/#/phones/#", PEOPLE_PHONES_ID); - sURIMatcher.addURI("contacts", "/people/#/contact_methods", PEOPLE_CONTACTMETHODS); - sURIMatcher.addURI("contacts", "/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID); - sURIMatcher.addURI("contacts", "/deleted_people", DELETED_PEOPLE); - sURIMatcher.addURI("contacts", "/phones", PHONES); - sURIMatcher.addURI("contacts", "/phones/filter/*", PHONES_FILTER); - sURIMatcher.addURI("contacts", "/phones/#", PHONES_ID); - sURIMatcher.addURI("contacts", "/contact_methods", CONTACTMETHODS); - sURIMatcher.addURI("contacts", "/contact_methods/#", CONTACTMETHODS_ID); - sURIMatcher.addURI("call_log", "/calls", CALLS); - sURIMatcher.addURI("call_log", "/calls/filter/*", CALLS_FILTER); - sURIMatcher.addURI("call_log", "/calls/#", CALLS_ID); - } -</pre> -<p>Then when you need to match match against a URI, call {@link #match}, providing -the tokenized url you've been given, and the value you want if there isn't -a match. You can use the result to build a query, return a type, insert or -delete a row, or whatever you need, without duplicating all of the if-else -logic you'd otherwise need. Like this: -<pre> - public String getType(String[] url) - { - int match = sURIMatcher.match(url, NO_MATCH); - switch (match) - { - case PEOPLE: - return "vnd.android.cursor.dir/person"; - case PEOPLE_ID: - return "vnd.android.cursor.item/person"; -... snip ... - return "vnd.android.cursor.dir/snail-mail"; - case PEOPLE_ADDRESS_ID: - return "vnd.android.cursor.item/snail-mail"; - default: - return null; - } - } -</pre> -instead of -<pre> - public String getType(String[] url) - { - if (url.length >= 2) { - if (url[1].equals("people")) { - if (url.length == 2) { - return "vnd.android.cursor.dir/person"; - } else if (url.length == 3) { - return "vnd.android.cursor.item/person"; -... snip ... - return "vnd.android.cursor.dir/snail-mail"; - } else if (url.length == 3) { - return "vnd.android.cursor.item/snail-mail"; - } - } - } - return null; - } -</pre> -*/ -public class UriMatcher -{ - public static final int NO_MATCH = -1; - /** - * Creates the root node of the URI tree. - * - * @param code the code to match for the root URI - */ - public UriMatcher(int code) - { - mCode = code; - mWhich = -1; - mChildren = new ArrayList<UriMatcher>(); - mText = null; - } - - private UriMatcher() - { - mCode = NO_MATCH; - mWhich = -1; - mChildren = new ArrayList<UriMatcher>(); - mText = null; - } - - /** - * Add a URI to match, and the code to return when this URI is - * matched. URI nodes may be exact match string, the token "*" - * that matches any text, or the token "#" that matches only - * numbers. - * - * @param authority the authority to match - * @param path the path to match. * may be used as a wild card for - * any text, and # may be used as a wild card for numbers. - * @param code the code that is returned when a URI is matched - * against the given components. Must be positive. - */ - public void addURI(String authority, String path, int code) - { - if (code < 0) { - throw new IllegalArgumentException("code " + code + " is invalid: it must be positive"); - } - String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null; - int numTokens = tokens != null ? tokens.length : 0; - UriMatcher node = this; - for (int i = -1; i < numTokens; i++) { - String token = i < 0 ? authority : tokens[i]; - ArrayList<UriMatcher> children = node.mChildren; - int numChildren = children.size(); - UriMatcher child; - int j; - for (j = 0; j < numChildren; j++) { - child = children.get(j); - if (token.equals(child.mText)) { - node = child; - break; - } - } - if (j == numChildren) { - // Child not found, create it - child = new UriMatcher(); - if (token.equals("#")) { - child.mWhich = NUMBER; - } else if (token.equals("*")) { - child.mWhich = TEXT; - } else { - child.mWhich = EXACT; - } - child.mText = token; - node.mChildren.add(child); - node = child; - } - } - node.mCode = code; - } - - static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/"); - - /** - * Try to match against the path in a url. - * - * @param uri The url whose path we will match against. - * - * @return The code for the matched node (added using addURI), - * or -1 if there is no matched node. - */ - public int match(Uri uri) - { - final int li = uri.getPathSegments().size(); - - UriMatcher node = this; - - if (li == 0 && uri.getAuthority() == null) { - return this.mCode; - } - - for (int i=-1; i<li; i++) { - String u = i < 0 ? uri.getAuthority() : uri.getPathSegments().get(i); - ArrayList<UriMatcher> list = node.mChildren; - if (list == null) { - break; - } - node = null; - int lj = list.size(); - for (int j=0; j<lj; j++) { - UriMatcher n = list.get(j); - which_switch: - switch (n.mWhich) { - case EXACT: - if (n.mText.equals(u)) { - node = n; - } - break; - case NUMBER: - int lk = u.length(); - for (int k=0; k<lk; k++) { - char c = u.charAt(k); - if (c < '0' || c > '9') { - break which_switch; - } - } - node = n; - break; - case TEXT: - node = n; - break; - } - if (node != null) { - break; - } - } - if (node == null) { - return NO_MATCH; - } - } - - return node.mCode; - } - - private static final int EXACT = 0; - private static final int NUMBER = 1; - private static final int TEXT = 2; - - private int mCode; - private int mWhich; - private String mText; - private ArrayList<UriMatcher> mChildren; -} diff --git a/core/java/android/content/package.html b/core/java/android/content/package.html deleted file mode 100644 index dd5360f..0000000 --- a/core/java/android/content/package.html +++ /dev/null @@ -1,650 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="http://www.corp.google.com/style/prettify.js"></script> -<script src="http://www.corp.google.com/eng/techpubs/include/navbar.js" type="text/javascript"></script> -</head> - -<body> - -<p>Contains classes for accessing and publishing data -on the device. It includes three main categories of APIs: -the {@link android.content.res.Resources Resources} for -retrieving resource data associated with an application; -{@link android.content.ContentProvider Content Providers} and -{@link android.content.ContentResolver ContentResolver} for managing and -publishing persistent data associated with an application; and -the {@link android.content.pm.PackageManager Package Manager} -for finding out information about the application packages installed -on the device.</p> - -<p>In addition, the {@link android.content.Context Context} abstract class -is a base API for pulling these pieces together, allowing you to access -an application's resources and transfer data between applications.</p> - -<p>This package builds on top of the lower-level Android packages -{@link android.database}, {@link android.text}, -{@link android.graphics.drawable}, {@link android.graphics}, -{@link android.os}, and {@link android.util}.</p> - -<ol> - <li> <a href="#Resources">Resources</a> - <ol> - <li> <a href="#ResourcesTerminology">Terminology</a> - <li> <a href="#ResourcesQuickStart">Examples</a> - <ol> - <li> <a href="#UsingSystemResources">Using System Resources</a> - <li> <a href="#StringResources">String Resources</a> - <li> <a href="#ColorResources">Color Resources</a> - <li> <a href="#DrawableResources">Drawable Resources</a> - <li> <a href="#LayoutResources">Layout Resources</a> - <li> <a href="#ReferencesToResources">References to Resources</a> - <li> <a href="#ReferencesToThemeAttributes">References to Theme Attributes</a> - <li> <a href="#StyleResources">Style Resources</a> - <li> <a href="#StylesInLayoutResources">Styles in Layout Resources</a> - </ol> - </ol> -</ol> - -<a name="Resources"></a> -<h2>Resources</h2> - -<p>This topic includes a terminology list associated with resources, and a series - of examples of using resources in code. For a complete guide on creating and - using resources, see the document on <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources - and Internationalization</a>. For a reference on the supported Android resource types, - see <a href="{@docRoot}guide/topics/resources/available-resources.html">Available Resource Types</a>.</p> -<p>The Android resource system keeps track of all non-code - assets associated with an application. You use the - {@link android.content.res.Resources Resources} class to access your - application's resources; the Resources instance associated with your - application can generally be found through - {@link android.content.Context#getResources Context.getResources()}.</p> -<p>An application's resources are compiled into the application -binary at build time for you by the build system. To use a resource, -you must install it correctly in the source tree and build your -application. As part of the build process, Java symbols for each -of the resources are generated that you can use in your source -code -- this allows the compiler to verify that your application code matches -up with the resources you defined.</p> - -<p>The rest of this section is organized as a tutorial on how to -use resources in an application.</p> - -<a name="ResourcesTerminology"></a> -<h3>Terminology</h3> - -<p>The resource system brings a number of different pieces together to -form the final complete resource functionality. To help understand the -overall system, here are some brief definitions of the core concepts and -components you will encounter in using it:</p> - -<p><b>Asset</b>: A single blob of data associated with an application. This -includes Java object files, graphics (such as PNG images), XML files, etc. -These files are organized in a directory hierarchy that, during final packaging -of the application, is bundled together into a single ZIP file.</p> - -<p><b>aapt</b>: The tool that generates the final ZIP file of application -assets. In addition to collecting raw assets together, it also parses -resource definitions into binary asset data.</p> - -<p><b>Resource Table</b>: A special asset that aapt generates for you, -describing all of the resources contained in an application/package. -This file is accessed for you by the Resources class; it is not touched -directly by applications.</p> - -<p><b>Resource</b>: An entry in the Resource Table describing a single -named value. Broadly, there are two types of resources: primitives and -bags.</p> - -<p><b>Resource Identifier</b>: In the Resource Table all resources are -identified by a unique integer number. In source code (resource descriptions, -XML files, Java code) you can use symbolic names that stand as constants for -the actual resource identifier integer.</p> - -<p><b>Primitive Resource</b>: All primitive resources can be written as a -simple string, using formatting to describe a variety of primitive types -included in the resource system: integers, colors, strings, references to -other resources, etc. Complex resources, such as bitmaps and XML -describes, are stored as a primitive string resource whose value is the path -of the underlying Asset holding its actual data.</p> - -<p><b>Bag Resource</b>: A special kind of resource entry that, instead of a -simple string, holds an arbitrary list of name/value pairs. Each name is -itself a resource identifier, and each value can hold -the same kinds of string formatted data as a normal resource. Bags also -support inheritance: a bag can inherit the values from another bag, selectively -replacing or extending them to generate its own contents.</p> - -<p><b>Kind</b>: The resource kind is a way to organize resource identifiers -for various purposes. For example, drawable resources are used to -instantiate Drawable objects, so their data is a primitive resource containing -either a color constant or string path to a bitmap or XML asset. Other -common resource kinds are string (localized string primitives), color -(color primitives), layout (a string path to an XML asset describing a view -layout), and style (a bag resource describing user interface attributes). -There is also a standard "attr" resource kind, which defines the resource -identifiers to be used for naming bag items and XML attributes</p> - -<p><b>Style</b>: The name of the resource kind containing bags that are used -to supply a set of user interface attributes. For example, a TextView class may -be given a style resource that defines its text size, color, and alignment. -In a layout XML file, you associate a style with a bag using the "style" -attribute, whose value is the name of the style resource.</p> - -<p><b>Style Class</b>: Specifies a related set of attribute resources. -This data is not placed in the resource table itself, but used to generate -Java constants that make it easier for you to retrieve values out of -a style resource and/or XML tag's attributes. For example, the -Android platform defines a "View" style class that -contains all of the standard view attributes: padding, visibility, -background, etc.; when View is inflated it uses this style class to -retrieve those values from the XML file (at which point style and theme -information is applied as approriate) and load them into its instance.</p> - -<p><b>Configuration</b>: For any particular resource identifier, there may be -multiple different available values depending on the current configuration. -The configuration includes the locale (language and country), screen -orientation, screen density, etc. The current configuration is used to -select which resource values are in effect when the resource table is -loaded.</p> - -<p><b>Theme</b>: A standard style resource that supplies global -attribute values for a particular context. For example, when writing a -Activity the application developer can select a standard theme to use, such -as the Theme.White or Theme.Black styles; this style supplies information -such as the screen background image/color, default text color, button style, -text editor style, text size, etc. When inflating a layout resource, most -values for widgets (the text color, selector, background) if not explicitly -set will come from the current theme; style and attribute -values supplied in the layout can also assign their value from explicitly -named values in the theme attributes if desired.</p> - -<p><b>Overlay</b>: A resource table that does not define a new set of resources, -but instead replaces the values of resources that are in another resource table. -Like a configuration, this is applied at load time -to the resource data; it can add new configuration values (for example -strings in a new locale), replace existing values (for example change -the standard white background image to a "Hello Kitty" background image), -and modify resource bags (for example change the font size of the Theme.White -style to have an 18 pt font size). This is the facility that allows the -user to select between different global appearances of their device, or -download files with new appearances.</p> - -<a name="ResourcesQuickStart"></a> -<h3>Examples</h3> - -<p>This section gives a few quick examples you can use to make your own resources. - For more details on how to define and use resources, see <a - href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources and - Internationalization</a>. </p> - -<a name="UsingSystemResources"></a> -<h4>Using System Resources</h4> - -<p>Many resources included with the system are available to applications. -All such resources are defined under the class "android.R". For example, -you can display the standard application icon in a screen with the following -code:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - requestScreenFeatures(FEATURE_BADGE_IMAGE); - - super.onStart(); - - setBadgeResource(android.R.drawable.sym_def_app_icon); - } -} -</pre> - -<p>In a similar way, this code will apply to your screen the standard -"green background" visual treatment defined by the system:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - super.onStart(); - - setTheme(android.R.style.Theme_Black); - } -} -</pre> - -<a name="StringResources"></a> -<h4>String Resources</h4> - -<p>String resources are defined using an XML resource description syntax. -The file or multiple files containing these resources can be given any name -(as long as it has a .xml suffix) and placed at an appropriate location in -the source tree for the desired configuration (locale/orientation/density). - -<p>Here is a simple resource file describing a few strings:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <string id="mainLabel">Hello <u>th<ignore>e</ignore>re</u>, <i>you</i> <b>Activity</b>!</string> - <string id="back">Back</string> - <string id="clear">Clear</string> -</resources> -</pre> - -<p>Typically this file will be called "strings.xml", and must be placed -in the <code>values</code> directory:</p> - -<pre> -MyApp/res/values/strings.xml -</pre> - -<p>The strings can now be retrieved by your application through the -symbol specified in the "id" attribute:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - super.onStart(); - - String back = getResources().getString(R.string.back).toString(); - back = getString(R.string.back).toString(); // synonym - } -} -</pre> - -<p>Unlike system resources, the resource symbol (the R class) we are using -here comes from our own application's package, not android.R.</p> - -<p>Note that the "mainLabel" string is complex, including style information. -To support this, the <code>getString()</code> method returns a -<code>CharSequence</code> object that you can pass to a -<code>TextView</code> to retain those style. This is why code -must call <code>toString()</code> on the returned resource if it wants -a raw string.</p> - -<a name="ColorResources"></a> -<h4>Color Resources</h4> - -<p>Color resources are created in a way very similar to string resources, -but with the <color> resource tag. The data for these resources -must be a hex color constant of the form "#rgb", "#argb", "#rrggbb", or -"#aarrggbb". The alpha channel is 0xff (or 0xf) for opaque and 0 -for transparent.</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <color id="opaque_red">#ffff0000</color> - <color id="transparent_red">#80ff0000</color> - <color id="opaque_blue">#0000ff</color> - <color id="opaque_green">#0f0</color> -</resources> -</pre> - -<p>While color definitions could be placed in the same resource file -as the previously shown string data, usually you will place the colors in -their own file:</p> - -<pre> -MyApp/res/values/colors.xml -</pre> - -<p>The colors can now be retrieved by your application through the -symbol specified in the "id" attribute:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - super.onStart(); - - int red = getResources().getColor(R.color.opaque_red); - } -} -</pre> - -<a name="DrawableResources"></a> -<h4>Drawable Resources</h4> - -<p>For simple drawable resources, all you need to do is place your -image in a special resource sub-directory called "drawable". Files here -are things that can be handled by an implementation of the -{@link android.graphics.drawable.Drawable Drawable} class, often bitmaps -(such as PNG images) but also various kinds of XML descriptions -for selectors, gradients, etc.</p> - -<p>The drawable files will be scanned by the -resource tool, automatically generating a resource entry for each found. -For example the file <code>res/drawable/<myimage>.<ext></code> -will result in a resource symbol named "myimage" (without the extension). Note -that these file names <em>must</em> be valid Java identifiers, and should -have only lower-case letters.</p> - -<p>For example, to use your own custom image as a badge in a screen, -you can place the image here:</p> - -<pre> -MyApp/res/drawable/my_badge.png -</pre> - -<p>The image can then be used in your code like this:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - requestScreenFeatures(FEATURE_BADGE_IMAGE); - - super.onStart(); - - setBadgeResource(R.drawable.my_badge); - } -} -</pre> - -<p>For drawables that are a single solid color, you can also define them -in a resource file very much like colors shown previously. The only -difference is that here we use the <drawable> tag to create a -drawable resource.</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <drawable id="opaque_red">#ffff0000</drawable> - <drawable id="transparent_red">#80ff0000</drawable> - <drawable id="opaque_blue">#0000ff</drawable> - <drawable id="opaque_green">#0f0</drawable> -</resources> -</pre> - -<p>These resource entries are often placed in the same resource file -as color definitions:</p> - -<pre> -MyApp/res/values/colors.xml -</pre> - -<a name="LayoutResources"></a> -<h4>Layout Resources</h4> - -<p>Layout resources describe a view hierarchy configuration that is -generated at runtime. These resources are XML files placed in the -resource directory "layout", and are how you should create the content -views inside of your screen (instead of creating them by hand) so that -they can be themed, styled, configured, and overlayed.</p> - -<p>Here is a simple layout resource consisting of a single view, a text -editor:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text" - android:layout_width="fill-parent" android:layout_height="fill-parent" - android:text="Hello, World!" /> -</root> -</pre> - -<p>To use this layout, it can be placed in a file like this:</p> - -<pre> -MyApp/res/layout/my_layout.xml -</pre> - -<p>The layout can then be instantiated in your screen like this:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - super.onStart(); - setContentView(R.layout.my_layout); - } -} -</pre> - -<p>Note that there are a number of visual attributes that can be supplied -to TextView (including textSize, textColor, and textStyle) that we did -not define in the previous example; in such a sitation, the default values for -those attributes come from the theme. If we want to customize them, we -can supply them explicitly in the XML file:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" - <b>android:textSize="18" android:textColor="#008"</b> - android:text="Hello, World!" /> -</root> -</pre> - -<p>However, usually these kinds of attributes (those being attributes that -usually make sense to vary with theme or overlay) should be defined through -the theme or separate style resource. Later we will see how this is done.</p> - -<a name="ReferencesToResources"></a> -<h4>References to Resources</h4> - -<p>A value supplied in an attribute (or resource) can also be a reference to -a resource. This is often used in layout files to supply strings (so they -can be localized) and images (which exist in another file), though a reference -can be do any resource type including colors and integers.</p> - -<p>For example, if we have the previously defined color resources, we can -write a layout file that sets the text color size to be the value contained in -one of those resources:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" - <b>android:textColor="@color/opaque_red"</b> - android:text="Hello, World!" /> -</root> -</pre> - -<p>Note here the use of the '@' prefix to introduce a resource reference -- the -text following that is the name of a resource in the form -of <code>@[package:]type/name</code>. In this case we didn't need to specify -the package because we are referencing a resource in our own package. To -reference a system resource, you would need to write:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" - android:textColor="@<b>android:</b>color/opaque_red" - android:text="Hello, World!" /> -</root> -</pre> - -<p>As another example, you should always use resource references when supplying -strings in a layout file so that they can be localized:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" - android:textColor="@android:color/opaque_red" - android:text="@string/hello_world" /> -</root> -</pre> - -<p>This facility can also be used to create references between resources. -For example, we can create new drawable resources that are aliases for -existing images:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <drawable id="my_background">@android:drawable/theme2_background</drawable> -</resources> -</pre> - -<a name="ReferencesToThemeAttributes"></a> -<h4>References to Theme Attributes</h4> - -<p>Another kind of resource value allows you to reference the value of an -attribute in the current theme. This attribute reference can <em>only</em> -be used in style resources and XML attributes; it allows you to customize the -look of UI elements by changing them to standard variations supplied by the -current theme, instead of supplying more concrete values.</p> - -<p>As an example, we can use this in our layout to set the text color to -one of the standard colors defined in the base system theme:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" - <b>android:textColor="?android:textDisabledColor"</b> - android:text="@string/hello_world" /> -</root> -</pre> - -<p>Note that this is very similar to a resource reference, except we are using -an '?' prefix instead of '@'. When you use this markup, you are supplying -the name of an attribute resource that will be looked up in the theme -- -because the resource tool knows that an attribute resource is expected, -you do not need to explicitly state the type (which would be -<code>?android:attr/android:textDisabledColor</code>).</p> - -<p>Other than using this resource identifier to find the value in the -theme instead of raw resources, the name syntax is identical to the '@' format: -<code>?[package:]type/name</code> with the type here being optional.</p> - -<a name="StyleResources"></a> -<h4>Style Resources</h4> - -<p>A style resource is a set of name/value pairs describing a group -of related attributes. There are two main uses for these resources: -defining overall visual themes, and describing a set of visual attributes -to apply to a class in a layout resource. In this section we will look -at their use to describe themes; later we will look at using them in -conjunction with layouts.</p> - -<p>Like strings, styles are defined through a resource XML file. In the -situation where we want to define a new theme, we can create a custom theme -style that inherits from one of the standard system themes:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <style id="Theme" parent="android:Theme.White"> - <item id="android:foregroundColor">#FFF8D96F</item> - <item id="android:textColor">@color/opaque_blue</item> - <item id="android:textSelectedColor">?android:textColor</item> - </style> -</resources> -</pre> - -<p>Typically these resource definitions will be placed in a file -called "styles.xml" , and must be placed in the <code>values</code> -directory:</p> - -<pre> -MyApp/res/values/styles.xml -</pre> - -<p>Similar to how we previously used a system style for an Activity theme, -you can apply this style to your Activity:</p> - -<pre class="prettyprint"> -public class MyActivity extends Activity -{ - public void onStart() - { - super.onStart(); - - setTheme(R.style.Theme); - } -} -</pre> - -<p>In the style resource shown here, we used the <code>parent</code> -attribute to specify another style resource from which it inherits -its values -- in this case the <code>Theme.White</code> system resource:</p> - -<pre> - <style id="Home" parent="android:Theme.White"> - ... - </style> -</pre> - -<p>Note, when doing this, that you must use the "android" prefix in front -to tell the compiler the namespace to look in for the resource -- -the resources you are specifying here are in your application's namespace, -not the system. This explicit namespace specification ensures that names -the application uses will not accidentally conflict with those defined by -the system.</p> - -<p>If you don't specify an explicit parent style, it will be inferred -from the style name -- everything before the final '.' in the name of the -style being defined is taken as the parent style name. Thus, to make -another style in your application that inherits from this base Theme style, -you can write:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <style id="Theme.WhiteText"> - <item id="android:foregroundColor">#FFFFFFFF</item> - <item id="android:textColor">?android:foregroundColor</item> - </style> -</resources> -</pre> - -<p>This results in the symbol <code>R.style.Theme_WhiteText</code> that -can be used in Java just like we did with <code>R.style.Theme</code> -above.</p> - -<a name="StylesInLayoutResources"></a> -<h4>Styles in Layout Resources</h4> - -<p>Often you will have a number fo views in a layout that all use the same -set of attributes, or want to allow resource overlays to modify the values of -attributes. Style resources can be used for both of these purposes, to put -attribute definitions in a single place that can be references by multiple -XML tags and modified by overlays. To do this, you simply define a -new style resource with the desired values:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<resources> - <style id="SpecialText"> - <item id="android:textSize">18</item> - <item id="android:textColor">#008</item> - </style> -</resources> -</pre> - -<p>You can now apply this style to your TextView in the XML file:</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<root> - <EditText id="text1" <b>style="@style/SpecialText"</b> - android:layout_width="fill_parent" android:layout_height="wrap_content" - android:text="Hello, World!" /> - <EditText id="text2" <b>style="@style/SpecialText"</b> - android:layout_width="fill_parent" android:layout_height="wrap_content" - android:text="I love you all." /> -</root></pre> -<h4> </h4> - -</body> -</html> - diff --git a/core/java/android/content/pm/ActivityInfo.aidl b/core/java/android/content/pm/ActivityInfo.aidl deleted file mode 100755 index dd90302..0000000 --- a/core/java/android/content/pm/ActivityInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable ActivityInfo; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java deleted file mode 100644 index 85d877a..0000000 --- a/core/java/android/content/pm/ActivityInfo.java +++ /dev/null @@ -1,353 +0,0 @@ -package android.content.pm; - -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Printer; - -/** - * Information you can retrieve about a particular application - * activity or receiver. This corresponds to information collected - * from the AndroidManifest.xml's <activity> and - * <receiver> tags. - */ -public class ActivityInfo extends ComponentInfo - implements Parcelable { - /** - * A style resource identifier (in the package's resources) of this - * activity's theme. From the "theme" attribute or, if not set, 0. - */ - public int theme; - - /** - * Constant corresponding to <code>standard</code> in - * the {@link android.R.attr#launchMode} attribute. - */ - public static final int LAUNCH_MULTIPLE = 0; - /** - * Constant corresponding to <code>singleTop</code> in - * the {@link android.R.attr#launchMode} attribute. - */ - public static final int LAUNCH_SINGLE_TOP = 1; - /** - * Constant corresponding to <code>singleTask</code> in - * the {@link android.R.attr#launchMode} attribute. - */ - public static final int LAUNCH_SINGLE_TASK = 2; - /** - * Constant corresponding to <code>singleInstance</code> in - * the {@link android.R.attr#launchMode} attribute. - */ - public static final int LAUNCH_SINGLE_INSTANCE = 3; - /** - * The launch mode style requested by the activity. From the - * {@link android.R.attr#launchMode} attribute, one of - * {@link #LAUNCH_MULTIPLE}, - * {@link #LAUNCH_SINGLE_TOP}, {@link #LAUNCH_SINGLE_TASK}, or - * {@link #LAUNCH_SINGLE_INSTANCE}. - */ - public int launchMode; - - /** - * Optional name of a permission required to be able to access this - * Activity. From the "permission" attribute. - */ - public String permission; - - /** - * The affinity this activity has for another task in the system. The - * string here is the name of the task, often the package name of the - * overall package. If null, the activity has no affinity. Set from the - * {@link android.R.attr#taskAffinity} attribute. - */ - public String taskAffinity; - - /** - * If this is an activity alias, this is the real activity class to run - * for it. Otherwise, this is null. - */ - public String targetActivity; - - /** - * Bit in {@link #flags} indicating whether this activity is able to - * run in multiple processes. If - * true, the system may instantiate it in the some process as the - * process starting it in order to conserve resources. If false, the - * default, it always runs in {@link #processName}. Set from the - * {@link android.R.attr#multiprocess} attribute. - */ - public static final int FLAG_MULTIPROCESS = 0x0001; - /** - * Bit in {@link #flags} indicating that, when the activity's task is - * relaunched from home, this activity should be finished. - * Set from the - * {@link android.R.attr#finishOnTaskLaunch} attribute. - */ - public static final int FLAG_FINISH_ON_TASK_LAUNCH = 0x0002; - /** - * Bit in {@link #flags} indicating that, when the activity is the root - * of a task, that task's stack should be cleared each time the user - * re-launches it from home. As a result, the user will always - * return to the original activity at the top of the task. - * This flag only applies to activities that - * are used to start the root of a new task. Set from the - * {@link android.R.attr#clearTaskOnLaunch} attribute. - */ - public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 0x0004; - /** - * Bit in {@link #flags} indicating that, when the activity is the root - * of a task, that task's stack should never be cleared when it is - * relaunched from home. Set from the - * {@link android.R.attr#alwaysRetainTaskState} attribute. - */ - public static final int FLAG_ALWAYS_RETAIN_TASK_STATE = 0x0008; - /** - * Bit in {@link #flags} indicating that the activity's state - * is not required to be saved, so that if there is a failure the - * activity will not be removed from the activity stack. Set from the - * {@link android.R.attr#stateNotNeeded} attribute. - */ - public static final int FLAG_STATE_NOT_NEEDED = 0x0010; - /** - * Bit in {@link #flags} that indicates that the activity should not - * appear in the list of recently launched activities. Set from the - * {@link android.R.attr#excludeFromRecents} attribute. - */ - public static final int FLAG_EXCLUDE_FROM_RECENTS = 0x0020; - /** - * Bit in {@link #flags} that indicates that the activity can be moved - * between tasks based on its task affinity. Set from the - * {@link android.R.attr#allowTaskReparenting} attribute. - */ - public static final int FLAG_ALLOW_TASK_REPARENTING = 0x0040; - /** - * Bit in {@link #flags} indicating that, when the user navigates away - * from an activity, it should be finished. - * Set from the - * {@link android.R.attr#noHistory} attribute. - */ - public static final int FLAG_NO_HISTORY = 0x0080; - /** - * Options that have been set in the activity declaration in the - * manifest: {@link #FLAG_MULTIPROCESS}, - * {@link #FLAG_FINISH_ON_TASK_LAUNCH}, {@link #FLAG_CLEAR_TASK_ON_LAUNCH}, - * {@link #FLAG_ALWAYS_RETAIN_TASK_STATE}, - * {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS}, - * {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY}. - */ - public int flags; - - /** - * Constant corresponding to <code>unspecified</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_UNSPECIFIED = -1; - /** - * Constant corresponding to <code>landscape</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_LANDSCAPE = 0; - /** - * Constant corresponding to <code>portrait</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_PORTRAIT = 1; - /** - * Constant corresponding to <code>user</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_USER = 2; - /** - * Constant corresponding to <code>behind</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_BEHIND = 3; - /** - * Constant corresponding to <code>sensor</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_SENSOR = 4; - - /** - * Constant corresponding to <code>sensor</code> in - * the {@link android.R.attr#screenOrientation} attribute. - */ - public static final int SCREEN_ORIENTATION_NOSENSOR = 5; - /** - * The preferred screen orientation this activity would like to run in. - * From the {@link android.R.attr#screenOrientation} attribute, one of - * {@link #SCREEN_ORIENTATION_UNSPECIFIED}, - * {@link #SCREEN_ORIENTATION_LANDSCAPE}, - * {@link #SCREEN_ORIENTATION_PORTRAIT}, - * {@link #SCREEN_ORIENTATION_USER}, - * {@link #SCREEN_ORIENTATION_BEHIND}, - * {@link #SCREEN_ORIENTATION_SENSOR}, - * {@link #SCREEN_ORIENTATION_NOSENSOR}. - */ - public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; - - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the IMSI MCC. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_MCC = 0x0001; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the IMSI MNC. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_MNC = 0x0002; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the locale. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_LOCALE = 0x0004; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the touchscreen type. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_TOUCHSCREEN = 0x0008; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the keyboard type. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_KEYBOARD = 0x0010; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the keyboard being hidden/exposed. - * Set from the {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_KEYBOARD_HIDDEN = 0x0020; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the navigation type. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_NAVIGATION = 0x0040; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the screen orientation. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_ORIENTATION = 0x0080; - /** - * Bit in {@link #configChanges} that indicates that the activity - * can itself handle changes to the font scaling factor. Set from the - * {@link android.R.attr#configChanges} attribute. This is - * not a core resource configutation, but a higher-level value, so its - * constant starts at the high bits. - */ - public static final int CONFIG_FONT_SCALE = 0x40000000; - - /** - * Bit mask of kinds of configuration changes that this activity - * can handle itself (without being restarted by the system). - * Contains any combination of {@link #CONFIG_FONT_SCALE}, - * {@link #CONFIG_MCC}, {@link #CONFIG_MNC}, - * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN}, - * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, and - * {@link #CONFIG_ORIENTATION}. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public int configChanges; - - /** - * The desired soft input mode for this activity's main window. - * Set from the {@link android.R.attr#windowSoftInputMode} attribute - * in the activity's manifest. May be any of the same values allowed - * for {@link android.view.WindowManager.LayoutParams#softInputMode - * WindowManager.LayoutParams.softInputMode}. If 0 (unspecified), - * the mode from the theme will be used. - */ - public int softInputMode; - - public ActivityInfo() { - } - - public ActivityInfo(ActivityInfo orig) { - super(orig); - theme = orig.theme; - launchMode = orig.launchMode; - permission = orig.permission; - taskAffinity = orig.taskAffinity; - targetActivity = orig.targetActivity; - flags = orig.flags; - screenOrientation = orig.screenOrientation; - configChanges = orig.configChanges; - softInputMode = orig.softInputMode; - } - - /** - * Return the theme resource identifier to use for this activity. If - * the activity defines a theme, that is used; else, the application - * theme is used. - * - * @return The theme associated with this activity. - */ - public final int getThemeResource() { - return theme != 0 ? theme : applicationInfo.theme; - } - - public void dump(Printer pw, String prefix) { - super.dumpFront(pw, prefix); - pw.println(prefix + "permission=" + permission); - pw.println(prefix + "taskAffinity=" + taskAffinity - + " targetActivity=" + targetActivity); - pw.println(prefix + "launchMode=" + launchMode - + " flags=0x" + Integer.toHexString(flags) - + " theme=0x" + Integer.toHexString(theme)); - pw.println(prefix + "screenOrientation=" + screenOrientation - + " configChanges=0x" + Integer.toHexString(configChanges) - + " softInputMode=0x" + Integer.toHexString(softInputMode)); - super.dumpBack(pw, prefix); - } - - public String toString() { - return "ActivityInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - dest.writeInt(theme); - dest.writeInt(launchMode); - dest.writeString(permission); - dest.writeString(taskAffinity); - dest.writeString(targetActivity); - dest.writeInt(flags); - dest.writeInt(screenOrientation); - dest.writeInt(configChanges); - dest.writeInt(softInputMode); - } - - public static final Parcelable.Creator<ActivityInfo> CREATOR - = new Parcelable.Creator<ActivityInfo>() { - public ActivityInfo createFromParcel(Parcel source) { - return new ActivityInfo(source); - } - public ActivityInfo[] newArray(int size) { - return new ActivityInfo[size]; - } - }; - - private ActivityInfo(Parcel source) { - super(source); - theme = source.readInt(); - launchMode = source.readInt(); - permission = source.readString(); - taskAffinity = source.readString(); - targetActivity = source.readString(); - flags = source.readInt(); - screenOrientation = source.readInt(); - configChanges = source.readInt(); - softInputMode = source.readInt(); - } -} diff --git a/core/java/android/content/pm/ApplicationInfo.aidl b/core/java/android/content/pm/ApplicationInfo.aidl deleted file mode 100755 index 006d1bd..0000000 --- a/core/java/android/content/pm/ApplicationInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable ApplicationInfo; diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java deleted file mode 100644 index 8d727ed..0000000 --- a/core/java/android/content/pm/ApplicationInfo.java +++ /dev/null @@ -1,310 +0,0 @@ -package android.content.pm; - -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Printer; - -import java.text.Collator; -import java.util.Comparator; - -/** - * Information you can retrieve about a particular application. This - * corresponds to information collected from the AndroidManifest.xml's - * <application> tag. - */ -public class ApplicationInfo extends PackageItemInfo implements Parcelable { - - /** - * Default task affinity of all activities in this application. See - * {@link ActivityInfo#taskAffinity} for more information. This comes - * from the "taskAffinity" attribute. - */ - public String taskAffinity; - - /** - * Optional name of a permission required to be able to access this - * application's components. From the "permission" attribute. - */ - public String permission; - - /** - * The name of the process this application should run in. From the - * "process" attribute or, if not set, the same as - * <var>packageName</var>. - */ - public String processName; - - /** - * Class implementing the Application object. From the "class" - * attribute. - */ - public String className; - - /** - * A style resource identifier (in the package's resources) of the - * description of an application. From the "description" attribute - * or, if not set, 0. - */ - public int descriptionRes; - - /** - * A style resource identifier (in the package's resources) of the - * default visual theme of the application. From the "theme" attribute - * or, if not set, 0. - */ - public int theme; - - /** - * Class implementing the Application's manage space - * functionality. From the "manageSpaceActivity" - * attribute. This is an optional attribute and will be null if - * application's dont specify it in their manifest - */ - public String manageSpaceActivityName; - - /** - * Value for {@link #flags}: if set, this application is installed in the - * device's system image. - */ - public static final int FLAG_SYSTEM = 1<<0; - - /** - * Value for {@link #flags}: set to true if this application would like to - * allow debugging of its - * code, even when installed on a non-development system. Comes - * from {@link android.R.styleable#AndroidManifestApplication_debuggable - * android:debuggable} of the <application> tag. - */ - public static final int FLAG_DEBUGGABLE = 1<<1; - - /** - * Value for {@link #flags}: set to true if this application has code - * associated with it. Comes - * from {@link android.R.styleable#AndroidManifestApplication_hasCode - * android:hasCode} of the <application> tag. - */ - public static final int FLAG_HAS_CODE = 1<<2; - - /** - * Value for {@link #flags}: set to true if this application is persistent. - * Comes from {@link android.R.styleable#AndroidManifestApplication_persistent - * android:persistent} of the <application> tag. - */ - public static final int FLAG_PERSISTENT = 1<<3; - - /** - * Value for {@link #flags}: set to true iif this application holds the - * {@link android.Manifest.permission#FACTORY_TEST} permission and the - * device is running in factory test mode. - */ - public static final int FLAG_FACTORY_TEST = 1<<4; - - /** - * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. - * Comes from {@link android.R.styleable#AndroidManifestApplication_allowTaskReparenting - * android:allowTaskReparenting} of the <application> tag. - */ - public static final int FLAG_ALLOW_TASK_REPARENTING = 1<<5; - - /** - * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. - * Comes from {@link android.R.styleable#AndroidManifestApplication_allowClearUserData - * android:allowClearUserData} of the <application> tag. - */ - public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6; - - - /** - * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. - * {@hide} - */ - public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7; - - /** - * Flags associated with the application. Any combination of - * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE}, - * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and - * {@link #FLAG_ALLOW_TASK_REPARENTING} - * {@link #FLAG_ALLOW_CLEAR_USER_DATA}. - */ - public int flags = 0; - - /** - * Full path to the location of this package. - */ - public String sourceDir; - - /** - * Full path to the location of the publicly available parts of this package (i.e. the resources - * and manifest). For non-forward-locked apps this will be the same as {@link #sourceDir). - */ - public String publicSourceDir; - - /** - * Paths to all shared libraries this application is linked against. This - * field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES - * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving - * the structure. - */ - public String[] sharedLibraryFiles; - - /** - * Full path to a directory assigned to the package for its persistent - * data. - */ - public String dataDir; - - /** - * The kernel user-ID that has been assigned to this application; - * currently this is not a unique ID (multiple applications can have - * the same uid). - */ - public int uid; - - /** - * When false, indicates that all components within this application are - * considered disabled, regardless of their individually set enabled status. - */ - public boolean enabled = true; - - public void dump(Printer pw, String prefix) { - super.dumpFront(pw, prefix); - pw.println(prefix + "className=" + className); - pw.println(prefix + "permission=" + permission - + " uid=" + uid); - pw.println(prefix + "taskAffinity=" + taskAffinity); - pw.println(prefix + "theme=0x" + Integer.toHexString(theme)); - pw.println(prefix + "flags=0x" + Integer.toHexString(flags) - + " processName=" + processName); - pw.println(prefix + "sourceDir=" + sourceDir); - pw.println(prefix + "publicSourceDir=" + publicSourceDir); - pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles); - pw.println(prefix + "dataDir=" + dataDir); - pw.println(prefix + "enabled=" + enabled); - pw.println(prefix+"manageSpaceActivityName="+manageSpaceActivityName); - pw.println(prefix+"description=0x"+Integer.toHexString(descriptionRes)); - super.dumpBack(pw, prefix); - } - - public static class DisplayNameComparator - implements Comparator<ApplicationInfo> { - public DisplayNameComparator(PackageManager pm) { - mPM = pm; - } - - public final int compare(ApplicationInfo aa, ApplicationInfo ab) { - CharSequence sa = mPM.getApplicationLabel(aa); - if (sa == null) { - sa = aa.packageName; - } - CharSequence sb = mPM.getApplicationLabel(ab); - if (sb == null) { - sb = ab.packageName; - } - - return sCollator.compare(sa.toString(), sb.toString()); - } - - private final Collator sCollator = Collator.getInstance(); - private PackageManager mPM; - } - - public ApplicationInfo() { - } - - public ApplicationInfo(ApplicationInfo orig) { - super(orig); - taskAffinity = orig.taskAffinity; - permission = orig.permission; - processName = orig.processName; - className = orig.className; - theme = orig.theme; - flags = orig.flags; - sourceDir = orig.sourceDir; - publicSourceDir = orig.publicSourceDir; - sharedLibraryFiles = orig.sharedLibraryFiles; - dataDir = orig.dataDir; - uid = orig.uid; - enabled = orig.enabled; - manageSpaceActivityName = orig.manageSpaceActivityName; - descriptionRes = orig.descriptionRes; - } - - - public String toString() { - return "ApplicationInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - dest.writeString(taskAffinity); - dest.writeString(permission); - dest.writeString(processName); - dest.writeString(className); - dest.writeInt(theme); - dest.writeInt(flags); - dest.writeString(sourceDir); - dest.writeString(publicSourceDir); - dest.writeStringArray(sharedLibraryFiles); - dest.writeString(dataDir); - dest.writeInt(uid); - dest.writeInt(enabled ? 1 : 0); - dest.writeString(manageSpaceActivityName); - dest.writeInt(descriptionRes); - } - - public static final Parcelable.Creator<ApplicationInfo> CREATOR - = new Parcelable.Creator<ApplicationInfo>() { - public ApplicationInfo createFromParcel(Parcel source) { - return new ApplicationInfo(source); - } - public ApplicationInfo[] newArray(int size) { - return new ApplicationInfo[size]; - } - }; - - private ApplicationInfo(Parcel source) { - super(source); - taskAffinity = source.readString(); - permission = source.readString(); - processName = source.readString(); - className = source.readString(); - theme = source.readInt(); - flags = source.readInt(); - sourceDir = source.readString(); - publicSourceDir = source.readString(); - sharedLibraryFiles = source.readStringArray(); - dataDir = source.readString(); - uid = source.readInt(); - enabled = source.readInt() != 0; - manageSpaceActivityName = source.readString(); - descriptionRes = source.readInt(); - } - - /** - * Retrieve the textual description of the application. This - * will call back on the given PackageManager to load the description from - * the application. - * - * @param pm A PackageManager from which the label can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a CharSequence containing the application's description. - * If there is no description, null is returned. - */ - public CharSequence loadDescription(PackageManager pm) { - if (descriptionRes != 0) { - CharSequence label = pm.getText(packageName, descriptionRes, null); - if (label != null) { - return label; - } - } - return null; - } -} diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java deleted file mode 100644 index 73c9244..0000000 --- a/core/java/android/content/pm/ComponentInfo.java +++ /dev/null @@ -1,138 +0,0 @@ -package android.content.pm; - -import android.graphics.drawable.Drawable; -import android.os.Parcel; -import android.util.Printer; - -/** - * Base class containing information common to all application components - * ({@link ActivityInfo}, {@link ServiceInfo}). This class is not intended - * to be used by itself; it is simply here to share common definitions - * between all application components. As such, it does not itself - * implement Parcelable, but does provide convenience methods to assist - * in the implementation of Parcelable in subclasses. - */ -public class ComponentInfo extends PackageItemInfo { - /** - * Global information about the application/package this component is a - * part of. - */ - public ApplicationInfo applicationInfo; - - /** - * The name of the process this component should run in. - * From the "android:process" attribute or, if not set, the same - * as <var>applicationInfo.processName</var>. - */ - public String processName; - - /** - * Indicates whether or not this component may be instantiated. Note that this value can be - * overriden by the one in its parent {@link ApplicationInfo}. - */ - public boolean enabled = true; - - /** - * Set to true if this component is available for use by other applications. - * Comes from {@link android.R.attr#exported android:exported} of the - * <activity>, <receiver>, <service>, or - * <provider> tag. - */ - public boolean exported = false; - - public ComponentInfo() { - } - - public ComponentInfo(ComponentInfo orig) { - super(orig); - applicationInfo = orig.applicationInfo; - processName = orig.processName; - enabled = orig.enabled; - exported = orig.exported; - } - - @Override public CharSequence loadLabel(PackageManager pm) { - if (nonLocalizedLabel != null) { - return nonLocalizedLabel; - } - ApplicationInfo ai = applicationInfo; - CharSequence label; - if (labelRes != 0) { - label = pm.getText(packageName, labelRes, ai); - if (label != null) { - return label; - } - } - if (ai.nonLocalizedLabel != null) { - return ai.nonLocalizedLabel; - } - if (ai.labelRes != 0) { - label = pm.getText(packageName, ai.labelRes, ai); - if (label != null) { - return label; - } - } - return name; - } - - @Override public Drawable loadIcon(PackageManager pm) { - ApplicationInfo ai = applicationInfo; - Drawable dr; - if (icon != 0) { - dr = pm.getDrawable(packageName, icon, ai); - if (dr != null) { - return dr; - } - } - if (ai.icon != 0) { - dr = pm.getDrawable(packageName, ai.icon, ai); - if (dr != null) { - return dr; - } - } - return pm.getDefaultActivityIcon(); - } - - /** - * Return the icon resource identifier to use for this component. If - * the component defines an icon, that is used; else, the application - * icon is used. - * - * @return The icon associated with this component. - */ - public final int getIconResource() { - return icon != 0 ? icon : applicationInfo.icon; - } - - protected void dumpFront(Printer pw, String prefix) { - super.dumpFront(pw, prefix); - pw.println(prefix + "enabled=" + enabled + " exported=" + exported - + " processName=" + processName); - } - - protected void dumpBack(Printer pw, String prefix) { - if (applicationInfo != null) { - pw.println(prefix + "ApplicationInfo:"); - applicationInfo.dump(pw, prefix + " "); - } else { - pw.println(prefix + "ApplicationInfo: null"); - } - super.dumpBack(pw, prefix); - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - applicationInfo.writeToParcel(dest, parcelableFlags); - dest.writeString(processName); - dest.writeInt(enabled ? 1 : 0); - dest.writeInt(exported ? 1 : 0); - } - - protected ComponentInfo(Parcel source) { - super(source); - applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source); - processName = source.readString(); - enabled = (source.readInt() != 0); - exported = (source.readInt() != 0); - } -} diff --git a/core/java/android/content/pm/ConfigurationInfo.java b/core/java/android/content/pm/ConfigurationInfo.java deleted file mode 100755 index dcc7463..0000000 --- a/core/java/android/content/pm/ConfigurationInfo.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008 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.pm; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Information you can retrieve about hardware configuration preferences - * declared by an application. This corresponds to information collected from the - * AndroidManifest.xml's <uses-configuration> tags. - */ -public class ConfigurationInfo implements Parcelable { - /** - * The kind of touch screen attached to the device. - * One of: {@link android.content.res.Configuration#TOUCHSCREEN_NOTOUCH}, - * {@link android.content.res.Configuration#TOUCHSCREEN_STYLUS}, - * {@link android.content.res.Configuration#TOUCHSCREEN_FINGER}. - */ - public int reqTouchScreen; - - /** - * Application's input method preference. - * One of: {@link android.content.res.Configuration#KEYBOARD_UNDEFINED}, - * {@link android.content.res.Configuration#KEYBOARD_NOKEYS}, - * {@link android.content.res.Configuration#KEYBOARD_QWERTY}, - * {@link android.content.res.Configuration#KEYBOARD_12KEY} - */ - public int reqKeyboardType; - - /** - * A flag indicating whether any keyboard is available. - * one of: {@link android.content.res.Configuration#NAVIGATION_UNDEFINED}, - * {@link android.content.res.Configuration#NAVIGATION_DPAD}, - * {@link android.content.res.Configuration#NAVIGATION_TRACKBALL}, - * {@link android.content.res.Configuration#NAVIGATION_WHEEL} - */ - public int reqNavigation; - - /** - * Value for {@link #reqInputFeatures}: if set, indicates that the application - * requires a hard keyboard - */ - public static final int INPUT_FEATURE_HARD_KEYBOARD = 0x00000001; - - /** - * Value for {@link #reqInputFeatures}: if set, indicates that the application - * requires a five way navigation device - */ - public static final int INPUT_FEATURE_FIVE_WAY_NAV = 0x00000002; - - /** - * Flags associated with the input features. Any combination of - * {@link #INPUT_FEATURE_HARD_KEYBOARD}, - * {@link #INPUT_FEATURE_FIVE_WAY_NAV} - */ - public int reqInputFeatures = 0; - - public ConfigurationInfo() { - } - - public ConfigurationInfo(ConfigurationInfo orig) { - reqTouchScreen = orig.reqTouchScreen; - reqKeyboardType = orig.reqKeyboardType; - reqNavigation = orig.reqNavigation; - reqInputFeatures = orig.reqInputFeatures; - } - - public String toString() { - return "ApplicationHardwarePreferences{" - + Integer.toHexString(System.identityHashCode(this)) - + ", touchscreen = " + reqTouchScreen + "}" - + ", inputMethod = " + reqKeyboardType + "}" - + ", navigation = " + reqNavigation + "}" - + ", reqInputFeatures = " + reqInputFeatures + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - dest.writeInt(reqTouchScreen); - dest.writeInt(reqKeyboardType); - dest.writeInt(reqNavigation); - dest.writeInt(reqInputFeatures); - } - - public static final Creator<ConfigurationInfo> CREATOR = - new Creator<ConfigurationInfo>() { - public ConfigurationInfo createFromParcel(Parcel source) { - return new ConfigurationInfo(source); - } - public ConfigurationInfo[] newArray(int size) { - return new ConfigurationInfo[size]; - } - }; - - private ConfigurationInfo(Parcel source) { - reqTouchScreen = source.readInt(); - reqKeyboardType = source.readInt(); - reqNavigation = source.readInt(); - reqInputFeatures = source.readInt(); - } -} diff --git a/core/java/android/content/pm/IPackageDataObserver.aidl b/core/java/android/content/pm/IPackageDataObserver.aidl deleted file mode 100755 index d010ee4..0000000 --- a/core/java/android/content/pm/IPackageDataObserver.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* -** -** Copyright 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.pm; - -/** - * API for package data change related callbacks from the Package Manager. - * Some usage scenarios include deletion of cache directory, generate - * statistics related to code, data, cache usage(TODO) - * {@hide} - */ -oneway interface IPackageDataObserver { - void onRemoveCompleted(in String packageName, boolean succeeded); -} diff --git a/core/java/android/content/pm/IPackageDeleteObserver.aidl b/core/java/android/content/pm/IPackageDeleteObserver.aidl deleted file mode 100644 index bc16b3e..0000000 --- a/core/java/android/content/pm/IPackageDeleteObserver.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* -** -** Copyright 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.pm; - -/** - * API for deletion callbacks from the Package Manager. - * - * {@hide} - */ -oneway interface IPackageDeleteObserver { - void packageDeleted(in boolean succeeded); -} - diff --git a/core/java/android/content/pm/IPackageInstallObserver.aidl b/core/java/android/content/pm/IPackageInstallObserver.aidl deleted file mode 100644 index e83bbc6..0000000 --- a/core/java/android/content/pm/IPackageInstallObserver.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/* -** -** Copyright 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.pm; - -/** - * API for installation callbacks from the Package Manager. - * - */ -oneway interface IPackageInstallObserver { - void packageInstalled(in String packageName, int returnCode); -} - diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl deleted file mode 100644 index d3f6f3c..0000000 --- a/core/java/android/content/pm/IPackageManager.aidl +++ /dev/null @@ -1,269 +0,0 @@ -/* -** -** Copyright 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.pm; - -import android.content.ComponentName; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageInstallObserver; -import android.content.pm.IPackageDeleteObserver; -import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageStatsObserver; -import android.content.pm.InstrumentationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.ProviderInfo; -import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.net.Uri; -import android.app.PendingIntent; - -/** - * See {@link PackageManager} for documentation on most of the APIs - * here. - * - * {@hide} - */ -interface IPackageManager { - PackageInfo getPackageInfo(String packageName, int flags); - int getPackageUid(String packageName); - int[] getPackageGids(String packageName); - - PermissionInfo getPermissionInfo(String name, int flags); - - List<PermissionInfo> queryPermissionsByGroup(String group, int flags); - - PermissionGroupInfo getPermissionGroupInfo(String name, int flags); - - List<PermissionGroupInfo> getAllPermissionGroups(int flags); - - ApplicationInfo getApplicationInfo(String packageName, int flags); - - ActivityInfo getActivityInfo(in ComponentName className, int flags); - - ActivityInfo getReceiverInfo(in ComponentName className, int flags); - - ServiceInfo getServiceInfo(in ComponentName className, int flags); - - int checkPermission(String permName, String pkgName); - - int checkUidPermission(String permName, int uid); - - boolean addPermission(in PermissionInfo info); - - void removePermission(String name); - - int checkSignatures(String pkg1, String pkg2); - - String[] getPackagesForUid(int uid); - - String getNameForUid(int uid); - - int getUidForSharedUser(String sharedUserName); - - ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags); - - List<ResolveInfo> queryIntentActivities(in Intent intent, - String resolvedType, int flags); - - List<ResolveInfo> queryIntentActivityOptions( - in ComponentName caller, in Intent[] specifics, - in String[] specificTypes, in Intent intent, - String resolvedType, int flags); - - List<ResolveInfo> queryIntentReceivers(in Intent intent, - String resolvedType, int flags); - - ResolveInfo resolveService(in Intent intent, - String resolvedType, int flags); - - List<ResolveInfo> queryIntentServices(in Intent intent, - String resolvedType, int flags); - - List<PackageInfo> getInstalledPackages(int flags); - - List<ApplicationInfo> getInstalledApplications(int flags); - - /** - * Retrieve all applications that are marked as persistent. - * - * @return A List<applicationInfo> containing one entry for each persistent - * application. - */ - List<ApplicationInfo> getPersistentApplications(int flags); - - ProviderInfo resolveContentProvider(String name, int flags); - - /** - * Retrieve sync information for all content providers. - * - * @param outNames Filled in with a list of the root names of the content - * providers that can sync. - * @param outInfo Filled in with a list of the ProviderInfo for each - * name in 'outNames'. - */ - void querySyncProviders(inout List<String> outNames, - inout List<ProviderInfo> outInfo); - - List<ProviderInfo> queryContentProviders( - String processName, int uid, int flags); - - InstrumentationInfo getInstrumentationInfo( - in ComponentName className, int flags); - - List<InstrumentationInfo> queryInstrumentation( - String targetPackage, int flags); - - /** - * Install a package. - * - * @param packageURI The location of the package file to install. - * @param observer a callback to use to notify when the package installation in finished. - * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, - * {@link #REPLACE_EXISITING_PACKAGE} - */ - void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags); - - /** - * Delete a package. - * - * @param packageName The fully qualified name of the package to delete. - * @param observer a callback to use to notify when the package deletion in finished. - * @param flags - possible values: {@link #DONT_DELETE_DATA} - */ - void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags); - - void addPackageToPreferred(String packageName); - - void removePackageFromPreferred(String packageName); - - List<PackageInfo> getPreferredPackages(int flags); - - void addPreferredActivity(in IntentFilter filter, int match, - in ComponentName[] set, in ComponentName activity); - void clearPackagePreferredActivities(String packageName); - int getPreferredActivities(out List<IntentFilter> outFilters, - out List<ComponentName> outActivities, String packageName); - - /** - * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}. - */ - void setComponentEnabledSetting(in ComponentName componentName, - in int newState, in int flags); - - /** - * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}. - */ - int getComponentEnabledSetting(in ComponentName componentName); - - /** - * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}. - */ - void setApplicationEnabledSetting(in String packageName, in int newState, int flags); - - /** - * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}. - */ - int getApplicationEnabledSetting(in String packageName); - - /** - * Free storage by deleting LRU sorted list of cache files across - * all applications. If the currently available free storage - * on the device is greater than or equal to the requested - * free storage, no cache files are cleared. If the currently - * available storage on the device is less than the requested - * free storage, some or all of the cache files across - * all applications are deleted (based on last accessed time) - * to increase the free storage space on the device to - * the requested value. There is no guarantee that clearing all - * the cache files from all applications will clear up - * enough storage to achieve the desired value. - * @param freeStorageSize The number of bytes of storage to be - * freed by the system. Say if freeStorageSize is XX, - * and the current free storage is YY, - * if XX is less than YY, just return. if not free XX-YY number - * of bytes if possible. - * @param observer call back used to notify when - * the operation is completed - */ - void freeStorageAndNotify(in long freeStorageSize, - IPackageDataObserver observer); - - /** - * Free storage by deleting LRU sorted list of cache files across - * all applications. If the currently available free storage - * on the device is greater than or equal to the requested - * free storage, no cache files are cleared. If the currently - * available storage on the device is less than the requested - * free storage, some or all of the cache files across - * all applications are deleted (based on last accessed time) - * to increase the free storage space on the device to - * the requested value. There is no guarantee that clearing all - * the cache files from all applications will clear up - * enough storage to achieve the desired value. - * @param freeStorageSize The number of bytes of storage to be - * freed by the system. Say if freeStorageSize is XX, - * and the current free storage is YY, - * if XX is less than YY, just return. if not free XX-YY number - * of bytes if possible. - * @param opFinishedIntent PendingIntent call back used to - * notify when the operation is completed.May be null - * to indicate that no call back is desired. - */ - void freeStorage(in long freeStorageSize, - in PendingIntent opFinishedIntent); - - /** - * Delete all the cache files in an applications cache directory - * @param packageName The package name of the application whose cache - * files need to be deleted - * @param observer a callback used to notify when the deletion is finished. - */ - void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer); - - /** - * Clear the user data directory of an application. - * @param packageName The package name of the application whose cache - * files need to be deleted - * @param observer a callback used to notify when the operation is completed. - */ - void clearApplicationUserData(in String packageName, IPackageDataObserver observer); - - /** - * Get package statistics including the code, data and cache size for - * an already installed package - * @param packageName The package name of the application - * @param observer a callback to use to notify when the asynchronous - * retrieval of information is complete. - */ - void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer); - - /** - * Get a list of shared libraries that are available on the - * system. - */ - String[] getSystemSharedLibraryNames(); - - void enterSafeMode(); - boolean isSafeMode(); - void systemReady(); - boolean hasSystemUidErrors(); -} diff --git a/core/java/android/content/pm/IPackageStatsObserver.aidl b/core/java/android/content/pm/IPackageStatsObserver.aidl deleted file mode 100755 index ede4d1d..0000000 --- a/core/java/android/content/pm/IPackageStatsObserver.aidl +++ /dev/null @@ -1,30 +0,0 @@ -/* -** -** Copyright 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.pm; - -import android.content.pm.PackageStats; -/** - * API for package data change related callbacks from the Package Manager. - * Some usage scenarios include deletion of cache directory, generate - * statistics related to code, data, cache usage(TODO) - * {@hide} - */ -oneway interface IPackageStatsObserver { - - void onGetStatsCompleted(in PackageStats pStats, boolean succeeded); -} diff --git a/core/java/android/content/pm/InstrumentationInfo.aidl b/core/java/android/content/pm/InstrumentationInfo.aidl deleted file mode 100755 index 3d847ae..0000000 --- a/core/java/android/content/pm/InstrumentationInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable InstrumentationInfo; diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java deleted file mode 100644 index 30ca002..0000000 --- a/core/java/android/content/pm/InstrumentationInfo.java +++ /dev/null @@ -1,98 +0,0 @@ -package android.content.pm; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import java.text.Collator; -import java.util.Comparator; - -/** - * Information you can retrieve about a particular piece of test - * instrumentation. This corresponds to information collected - * from the AndroidManifest.xml's <instrumentation> tag. - */ -public class InstrumentationInfo extends PackageItemInfo implements Parcelable { - /** - * The name of the application package being instrumented. From the - * "package" attribute. - */ - public String targetPackage; - - /** - * Full path to the location of this package. - */ - public String sourceDir; - - /** - * Full path to the location of the publicly available parts of this package (i.e. the resources - * and manifest). For non-forward-locked apps this will be the same as {@link #sourceDir). - */ - public String publicSourceDir; - /** - * Full path to a directory assigned to the package for its persistent - * data. - */ - public String dataDir; - - /** - * Specifies whether or not this instrumentation will handle profiling. - */ - public boolean handleProfiling; - - /** Specifies whether or not to run this instrumentation as a functional test */ - public boolean functionalTest; - - public InstrumentationInfo() { - } - - public InstrumentationInfo(InstrumentationInfo orig) { - super(orig); - targetPackage = orig.targetPackage; - sourceDir = orig.sourceDir; - publicSourceDir = orig.publicSourceDir; - dataDir = orig.dataDir; - handleProfiling = orig.handleProfiling; - functionalTest = orig.functionalTest; - } - - public String toString() { - return "InstrumentationInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - dest.writeString(targetPackage); - dest.writeString(sourceDir); - dest.writeString(publicSourceDir); - dest.writeString(dataDir); - dest.writeInt((handleProfiling == false) ? 0 : 1); - dest.writeInt((functionalTest == false) ? 0 : 1); - } - - public static final Parcelable.Creator<InstrumentationInfo> CREATOR - = new Parcelable.Creator<InstrumentationInfo>() { - public InstrumentationInfo createFromParcel(Parcel source) { - return new InstrumentationInfo(source); - } - public InstrumentationInfo[] newArray(int size) { - return new InstrumentationInfo[size]; - } - }; - - private InstrumentationInfo(Parcel source) { - super(source); - targetPackage = source.readString(); - sourceDir = source.readString(); - publicSourceDir = source.readString(); - dataDir = source.readString(); - handleProfiling = source.readInt() != 0; - functionalTest = source.readInt() != 0; - } -} diff --git a/core/java/android/content/pm/PackageInfo.aidl b/core/java/android/content/pm/PackageInfo.aidl deleted file mode 100755 index 35e2322..0000000 --- a/core/java/android/content/pm/PackageInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable PackageInfo; diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java deleted file mode 100644 index d9326f2..0000000 --- a/core/java/android/content/pm/PackageInfo.java +++ /dev/null @@ -1,199 +0,0 @@ -package android.content.pm; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Overall information about the contents of a package. This corresponds - * to all of the information collected from AndroidManifest.xml. - */ -public class PackageInfo implements Parcelable { - /** - * The name of this package. From the <manifest> tag's "name" - * attribute. - */ - public String packageName; - - /** - * The version number of this package, as specified by the <manifest> - * tag's {@link android.R.styleable#AndroidManifest_versionCode versionCode} - * attribute. - */ - public int versionCode; - - /** - * The version name of this package, as specified by the <manifest> - * tag's {@link android.R.styleable#AndroidManifest_versionName versionName} - * attribute. - */ - public String versionName; - - /** - * The shared user ID name of this package, as specified by the <manifest> - * tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId} - * attribute. - */ - public String sharedUserId; - - /** - * The shared user ID label of this package, as specified by the <manifest> - * tag's {@link android.R.styleable#AndroidManifest_sharedUserLabel sharedUserLabel} - * attribute. - */ - public int sharedUserLabel; - - /** - * Information collected from the <application> tag, or null if - * there was none. - */ - public ApplicationInfo applicationInfo; - - /** - * All kernel group-IDs that have been assigned to this package. - * This is only filled in if the flag {@link PackageManager#GET_GIDS} was set. - */ - public int[] gids; - - /** - * Array of all {@link android.R.styleable#AndroidManifestActivity - * <activity>} tags included under <application>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_ACTIVITIES} was set. - */ - public ActivityInfo[] activities; - - /** - * Array of all {@link android.R.styleable#AndroidManifestReceiver - * <receiver>} tags included under <application>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_RECEIVERS} was set. - */ - public ActivityInfo[] receivers; - - /** - * Array of all {@link android.R.styleable#AndroidManifestService - * <service>} tags included under <application>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_SERVICES} was set. - */ - public ServiceInfo[] services; - - /** - * Array of all {@link android.R.styleable#AndroidManifestProvider - * <provider>} tags included under <application>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_PROVIDERS} was set. - */ - public ProviderInfo[] providers; - - /** - * Array of all {@link android.R.styleable#AndroidManifestInstrumentation - * <instrumentation>} tags included under <manifest>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_INSTRUMENTATION} was set. - */ - public InstrumentationInfo[] instrumentation; - - /** - * Array of all {@link android.R.styleable#AndroidManifestPermission - * <permission>} tags included under <manifest>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_PERMISSIONS} was set. - */ - public PermissionInfo[] permissions; - - /** - * Array of all {@link android.R.styleable#AndroidManifestUsesPermission - * <uses-permission>} tags included under <manifest>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_PERMISSIONS} was set. This list includes - * all permissions requested, even those that were not granted or known - * by the system at install time. - */ - public String[] requestedPermissions; - - /** - * Array of all signatures read from the package file. This is only filled - * in if the flag {@link PackageManager#GET_SIGNATURES} was set. - */ - public Signature[] signatures; - - /** - * Application specified preferred configuration - * {@link android.R.styleable#AndroidManifestUsesConfiguration - * <uses-configuration>} tags included under <manifest>, - * or null if there were none. This is only filled in if the flag - * {@link PackageManager#GET_CONFIGURATIONS} was set. - */ - public ConfigurationInfo[] configPreferences; - - public PackageInfo() { - } - - public String toString() { - return "PackageInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - dest.writeString(packageName); - dest.writeInt(versionCode); - dest.writeString(versionName); - dest.writeString(sharedUserId); - dest.writeInt(sharedUserLabel); - if (applicationInfo != null) { - dest.writeInt(1); - applicationInfo.writeToParcel(dest, parcelableFlags); - } else { - dest.writeInt(0); - } - dest.writeIntArray(gids); - dest.writeTypedArray(activities, parcelableFlags); - dest.writeTypedArray(receivers, parcelableFlags); - dest.writeTypedArray(services, parcelableFlags); - dest.writeTypedArray(providers, parcelableFlags); - dest.writeTypedArray(instrumentation, parcelableFlags); - dest.writeTypedArray(permissions, parcelableFlags); - dest.writeStringArray(requestedPermissions); - dest.writeTypedArray(signatures, parcelableFlags); - dest.writeTypedArray(configPreferences, parcelableFlags); - } - - public static final Parcelable.Creator<PackageInfo> CREATOR - = new Parcelable.Creator<PackageInfo>() { - public PackageInfo createFromParcel(Parcel source) { - return new PackageInfo(source); - } - - public PackageInfo[] newArray(int size) { - return new PackageInfo[size]; - } - }; - - private PackageInfo(Parcel source) { - packageName = source.readString(); - versionCode = source.readInt(); - versionName = source.readString(); - sharedUserId = source.readString(); - sharedUserLabel = source.readInt(); - int hasApp = source.readInt(); - if (hasApp != 0) { - applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source); - } - gids = source.createIntArray(); - activities = source.createTypedArray(ActivityInfo.CREATOR); - receivers = source.createTypedArray(ActivityInfo.CREATOR); - services = source.createTypedArray(ServiceInfo.CREATOR); - providers = source.createTypedArray(ProviderInfo.CREATOR); - instrumentation = source.createTypedArray(InstrumentationInfo.CREATOR); - permissions = source.createTypedArray(PermissionInfo.CREATOR); - requestedPermissions = source.createStringArray(); - signatures = source.createTypedArray(Signature.CREATOR); - configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR); - } -} diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java deleted file mode 100644 index 46e7ca4..0000000 --- a/core/java/android/content/pm/PackageItemInfo.java +++ /dev/null @@ -1,191 +0,0 @@ -package android.content.pm; - -import android.content.res.XmlResourceParser; - -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Parcel; -import android.text.TextUtils; -import android.util.Printer; - -import java.text.Collator; -import java.util.Comparator; - -/** - * Base class containing information common to all package items held by - * the package manager. This provides a very common basic set of attributes: - * a label, icon, and meta-data. This class is not intended - * to be used by itself; it is simply here to share common definitions - * between all items returned by the package manager. As such, it does not - * itself implement Parcelable, but does provide convenience methods to assist - * in the implementation of Parcelable in subclasses. - */ -public class PackageItemInfo { - /** - * Public name of this item. From the "android:name" attribute. - */ - public String name; - - /** - * Name of the package that this item is in. - */ - public String packageName; - - /** - * A string resource identifier (in the package's resources) of this - * component's label. From the "label" attribute or, if not set, 0. - */ - public int labelRes; - - /** - * The string provided in the AndroidManifest file, if any. You - * probably don't want to use this. You probably want - * {@link PackageManager#getApplicationLabel} - */ - public CharSequence nonLocalizedLabel; - - /** - * A drawable resource identifier (in the package's resources) of this - * component's icon. From the "icon" attribute or, if not set, 0. - */ - public int icon; - - /** - * Additional meta-data associated with this component. This field - * will only be filled in if you set the - * {@link PackageManager#GET_META_DATA} flag when requesting the info. - */ - public Bundle metaData; - - public PackageItemInfo() { - } - - public PackageItemInfo(PackageItemInfo orig) { - name = orig.name; - packageName = orig.packageName; - labelRes = orig.labelRes; - nonLocalizedLabel = orig.nonLocalizedLabel; - icon = orig.icon; - metaData = orig.metaData; - } - - /** - * Retrieve the current textual label associated with this item. This - * will call back on the given PackageManager to load the label from - * the application. - * - * @param pm A PackageManager from which the label can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a CharSequence containing the item's label. If the - * item does not have a label, its name is returned. - */ - public CharSequence loadLabel(PackageManager pm) { - if (nonLocalizedLabel != null) { - return nonLocalizedLabel; - } - if (labelRes != 0) { - CharSequence label = pm.getText(packageName, labelRes, null); - if (label != null) { - return label; - } - } - if(name != null) { - return name; - } - return packageName; - } - - /** - * Retrieve the current graphical icon associated with this item. This - * will call back on the given PackageManager to load the icon from - * the application. - * - * @param pm A PackageManager from which the icon can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a Drawable containing the item's icon. If the - * item does not have an icon, the default activity icon is returned. - */ - public Drawable loadIcon(PackageManager pm) { - if (icon != 0) { - Drawable dr = pm.getDrawable(packageName, icon, null); - if (dr != null) { - return dr; - } - } - return pm.getDefaultActivityIcon(); - } - - /** - * Load an XML resource attached to the meta-data of this item. This will - * retrieved the name meta-data entry, and if defined call back on the - * given PackageManager to load its XML file from the application. - * - * @param pm A PackageManager from which the XML can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * @param name Name of the meta-date you would like to load. - * - * @return Returns an XmlPullParser you can use to parse the XML file - * assigned as the given meta-data. If the meta-data name is not defined - * or the XML resource could not be found, null is returned. - */ - public XmlResourceParser loadXmlMetaData(PackageManager pm, String name) { - if (metaData != null) { - int resid = metaData.getInt(name); - if (resid != 0) { - return pm.getXml(packageName, resid, null); - } - } - return null; - } - - protected void dumpFront(Printer pw, String prefix) { - pw.println(prefix + "name=" + name); - pw.println(prefix + "packageName=" + packageName); - pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) - + " nonLocalizedLabel=" + nonLocalizedLabel - + " icon=0x" + Integer.toHexString(icon)); - } - - protected void dumpBack(Printer pw, String prefix) { - // no back here - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - dest.writeString(name); - dest.writeString(packageName); - dest.writeInt(labelRes); - TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); - dest.writeInt(icon); - dest.writeBundle(metaData); - } - - protected PackageItemInfo(Parcel source) { - name = source.readString(); - packageName = source.readString(); - labelRes = source.readInt(); - nonLocalizedLabel - = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - icon = source.readInt(); - metaData = source.readBundle(); - } - - public static class DisplayNameComparator - implements Comparator<PackageItemInfo> { - public DisplayNameComparator(PackageManager pm) { - mPM = pm; - } - - public final int compare(PackageItemInfo aa, PackageItemInfo ab) { - CharSequence sa = aa.loadLabel(mPM); - if (sa == null) sa = aa.name; - CharSequence sb = ab.loadLabel(mPM); - if (sb == null) sb = ab.name; - return sCollator.compare(sa.toString(), sb.toString()); - } - - private final Collator sCollator = Collator.getInstance(); - private PackageManager mPM; - } -} diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java deleted file mode 100644 index 698f27f..0000000 --- a/core/java/android/content/pm/PackageManager.java +++ /dev/null @@ -1,1626 +0,0 @@ -/* - * Copyright (C) 2006 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.pm; - - -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Resources; -import android.content.res.XmlResourceParser; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.util.AndroidException; -import android.util.DisplayMetrics; - -import java.io.File; -import java.util.List; - -/** - * Class for retrieving various kinds of information related to the application - * packages that are currently installed on the device. - * - * You can find this class through {@link Context#getPackageManager}. - */ -public abstract class PackageManager { - - /** - * This exception is thrown when a given package, application, or component - * name can not be found. - */ - public static class NameNotFoundException extends AndroidException { - public NameNotFoundException() { - } - - public NameNotFoundException(String name) { - super(name); - } - } - - /** - * {@link PackageInfo} flag: return information about - * activities in the package in {@link PackageInfo#activities}. - */ - public static final int GET_ACTIVITIES = 0x00000001; - - /** - * {@link PackageInfo} flag: return information about - * intent receivers in the package in - * {@link PackageInfo#receivers}. - */ - public static final int GET_RECEIVERS = 0x00000002; - - /** - * {@link PackageInfo} flag: return information about - * services in the package in {@link PackageInfo#services}. - */ - public static final int GET_SERVICES = 0x00000004; - - /** - * {@link PackageInfo} flag: return information about - * content providers in the package in - * {@link PackageInfo#providers}. - */ - public static final int GET_PROVIDERS = 0x00000008; - - /** - * {@link PackageInfo} flag: return information about - * instrumentation in the package in - * {@link PackageInfo#instrumentation}. - */ - public static final int GET_INSTRUMENTATION = 0x00000010; - - /** - * {@link PackageInfo} flag: return information about the - * intent filters supported by the activity. - */ - public static final int GET_INTENT_FILTERS = 0x00000020; - - /** - * {@link PackageInfo} flag: return information about the - * signatures included in the package. - */ - public static final int GET_SIGNATURES = 0x00000040; - - /** - * {@link ResolveInfo} flag: return the IntentFilter that - * was matched for a particular ResolveInfo in - * {@link ResolveInfo#filter}. - */ - public static final int GET_RESOLVED_FILTER = 0x00000040; - - /** - * {@link ComponentInfo} flag: return the {@link ComponentInfo#metaData} - * data {@link android.os.Bundle}s that are associated with a component. - * This applies for any API returning a ComponentInfo subclass. - */ - public static final int GET_META_DATA = 0x00000080; - - /** - * {@link PackageInfo} flag: return the - * {@link PackageInfo#gids group ids} that are associated with an - * application. - * This applies for any API returning an PackageInfo class, either - * directly or nested inside of another. - */ - public static final int GET_GIDS = 0x00000100; - - /** - * {@link PackageInfo} flag: include disabled components in the returned info. - */ - public static final int GET_DISABLED_COMPONENTS = 0x00000200; - - /** - * {@link ApplicationInfo} flag: return the - * {@link ApplicationInfo#sharedLibraryFiles paths to the shared libraries} - * that are associated with an application. - * This applies for any API returning an ApplicationInfo class, either - * directly or nested inside of another. - */ - public static final int GET_SHARED_LIBRARY_FILES = 0x00000400; - - /** - * {@link ProviderInfo} flag: return the - * {@link ProviderInfo#uriPermissionPatterns URI permission patterns} - * that are associated with a content provider. - * This applies for any API returning an ProviderInfo class, either - * directly or nested inside of another. - */ - public static final int GET_URI_PERMISSION_PATTERNS = 0x00000800; - /** - * {@link PackageInfo} flag: return information about - * permissions in the package in - * {@link PackageInfo#permissions}. - */ - public static final int GET_PERMISSIONS = 0x00001000; - - /** - * Flag parameter to retrieve all applications(even uninstalled ones) with data directories. - * This state could have resulted if applications have been deleted with flag - * DONT_DELETE_DATA - * with a possibility of being replaced or reinstalled in future - */ - public static final int GET_UNINSTALLED_PACKAGES = 0x00002000; - - /** - * {@link PackageInfo} flag: return information about - * hardware preferences - * {@link PackageInfo#configPreferences} - */ - public static final int GET_CONFIGURATIONS = 0x00004000; - - /** - * Permission check result: this is returned by {@link #checkPermission} - * if the permission has been granted to the given package. - */ - public static final int PERMISSION_GRANTED = 0; - - /** - * Permission check result: this is returned by {@link #checkPermission} - * if the permission has not been granted to the given package. - */ - public static final int PERMISSION_DENIED = -1; - - /** - * Signature check result: this is returned by {@link #checkSignatures} - * if the two packages have a matching signature. - */ - public static final int SIGNATURE_MATCH = 0; - - /** - * Signature check result: this is returned by {@link #checkSignatures} - * if neither of the two packages is signed. - */ - public static final int SIGNATURE_NEITHER_SIGNED = 1; - - /** - * Signature check result: this is returned by {@link #checkSignatures} - * if the first package is not signed, but the second is. - */ - public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; - - /** - * Signature check result: this is returned by {@link #checkSignatures} - * if the second package is not signed, but the first is. - */ - public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; - - /** - * Signature check result: this is returned by {@link #checkSignatures} - * if both packages are signed but there is no matching signature. - */ - public static final int SIGNATURE_NO_MATCH = -3; - - /** - * Signature check result: this is returned by {@link #checkSignatures} - * if either of the given package names are not valid. - */ - public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; - - /** - * Resolution and querying flag: if set, only filters that support the - * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for - * matching. This is a synonym for including the CATEGORY_DEFAULT in your - * supplied Intent. - */ - public static final int MATCH_DEFAULT_ONLY = 0x00010000; - - public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; - public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; - public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; - - /** - * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to - * indicate that this package should be installed as forward locked, i.e. only the app itself - * should have access to it's code and non-resource assets. - */ - public static final int FORWARD_LOCK_PACKAGE = 0x00000001; - - /** - * Flag parameter for {@link #installPackage} to indicate that you want to replace an already - * installed package, if one exists - */ - public static final int REPLACE_EXISTING_PACKAGE = 0x00000002; - - /** - * Flag parameter for - * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate - * that you don't want to kill the app containing the component. Be careful when you set this - * since changing component states can make the containing application's behavior unpredictable. - */ - public static final int DONT_KILL_APP = 0x00000001; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success. - */ - public static final int INSTALL_SUCCEEDED = 1; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package is - * already installed. - */ - public static final int INSTALL_FAILED_ALREADY_EXISTS = -1; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package archive - * file is invalid. - */ - public static final int INSTALL_FAILED_INVALID_APK = -2; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the URI passed in - * is invalid. - */ - public static final int INSTALL_FAILED_INVALID_URI = -3; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package manager - * service found that the device didn't have enough storage space to install the app - */ - public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if a - * package is already installed with the same name. - */ - public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * the requested shared user does not exist. - */ - public static final int INSTALL_FAILED_NO_SHARED_USER = -6; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * a previously installed package of the same name has a different signature - * than the new package (and the old package's data was not removed). - */ - public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * the new package is requested a shared user which is already installed on the - * device and does not have matching signature. - */ - public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * the new package uses a shared library that is not available. - */ - public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * the new package uses a shared library that is not available. - */ - public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * the new package failed while optimizing and validating its dex files, - * either because there was not enough storage or the validation failed. - */ - public static final int INSTALL_FAILED_DEXOPT = -11; - - /** - * Installation return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if - * the new package failed because the current SDK version is older than - * that required by the package. - */ - public static final int INSTALL_FAILED_OLDER_SDK = -12; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser was given a path that is not a file, or does not end with the expected - * '.apk' extension. - */ - public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser was unable to retrieve the AndroidManifest.xml file. - */ - public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser encountered an unexpected exception. - */ - public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser did not find any certificates in the .apk. - */ - public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser found inconsistent certificates on the files in the .apk. - */ - public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser encountered a CertificateEncodingException in one of the - * files in the .apk. - */ - public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser encountered a bad or missing package name in the manifest. - */ - public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser encountered a bad shared user id name in the manifest. - */ - public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser encountered some structural problem in the manifest. - */ - public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108; - - /** - * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by - * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} - * if the parser did not find any actionable tags (instrumentation or application) - * in the manifest. - */ - public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109; - - /** - * Indicates the state of installation. Used by PackageManager to - * figure out incomplete installations. Say a package is being installed - * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till - * the package installation is successful or unsuccesful lin which case - * the PackageManager will no longer maintain state information associated - * with the package. If some exception(like device freeze or battery being - * pulled out) occurs during installation of a package, the PackageManager - * needs this information to clean up the previously failed installation. - */ - public static final int PKG_INSTALL_INCOMPLETE = 0; - public static final int PKG_INSTALL_COMPLETE = 1; - - /** - * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the - * package's data directory. - * - * @hide - */ - public static final int DONT_DELETE_DATA = 0x00000001; - - /** - * Retrieve overall information about an application package that is - * installed on the system. - * - * <p>Throws {@link NameNotFoundException} if a package with the given - * name can not be found on the system. - * - * @param packageName The full name (i.e. com.google.apps.contacts) of the - * desired package. - - * @param flags Additional option flags. Use any combination of - * {@link #GET_ACTIVITIES}, - * {@link #GET_GIDS}, - * {@link #GET_CONFIGURATIONS}, - * {@link #GET_INSTRUMENTATION}, - * {@link #GET_PERMISSIONS}, - * {@link #GET_PROVIDERS}, - * {@link #GET_RECEIVERS}, - * {@link #GET_SERVICES}, - * {@link #GET_SIGNATURES}, - * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. - * - * @return Returns a PackageInfo object containing information about the package. - * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not - * found in the list of installed applications, the package information is - * retrieved from the list of uninstalled applications(which includes - * installed applications as well as applications - * with data directory ie applications which had been - * deleted with DONT_DELTE_DATA flag set). - * - * @see #GET_ACTIVITIES - * @see #GET_GIDS - * @see #GET_CONFIGURATIONS - * @see #GET_INSTRUMENTATION - * @see #GET_PERMISSIONS - * @see #GET_PROVIDERS - * @see #GET_RECEIVERS - * @see #GET_SERVICES - * @see #GET_SIGNATURES - * @see #GET_UNINSTALLED_PACKAGES - * - */ - public abstract PackageInfo getPackageInfo(String packageName, int flags) - throws NameNotFoundException; - - /** - * Return an array of all of the secondary group-ids that have been - * assigned to a package. - * - * <p>Throws {@link NameNotFoundException} if a package with the given - * name can not be found on the system. - * - * @param packageName The full name (i.e. com.google.apps.contacts) of the - * desired package. - * - * @return Returns an int array of the assigned gids, or null if there - * are none. - */ - public abstract int[] getPackageGids(String packageName) - throws NameNotFoundException; - - /** - * Retrieve all of the information we know about a particular permission. - * - * <p>Throws {@link NameNotFoundException} if a permission with the given - * name can not be found on the system. - * - * @param name The fully qualified name (i.e. com.google.permission.LOGIN) - * of the permission you are interested in. - * @param flags Additional option flags. Use {@link #GET_META_DATA} to - * retrieve any meta-data associated with the permission. - * - * @return Returns a {@link PermissionInfo} containing information about the - * permission. - */ - public abstract PermissionInfo getPermissionInfo(String name, int flags) - throws NameNotFoundException; - - /** - * Query for all of the permissions associated with a particular group. - * - * <p>Throws {@link NameNotFoundException} if the given group does not - * exist. - * - * @param group The fully qualified name (i.e. com.google.permission.LOGIN) - * of the permission group you are interested in. Use null to - * find all of the permissions not associated with a group. - * @param flags Additional option flags. Use {@link #GET_META_DATA} to - * retrieve any meta-data associated with the permissions. - * - * @return Returns a list of {@link PermissionInfo} containing information - * about all of the permissions in the given group. - */ - public abstract List<PermissionInfo> queryPermissionsByGroup(String group, - int flags) throws NameNotFoundException; - - /** - * Retrieve all of the information we know about a particular group of - * permissions. - * - * <p>Throws {@link NameNotFoundException} if a permission group with the given - * name can not be found on the system. - * - * @param name The fully qualified name (i.e. com.google.permission_group.APPS) - * of the permission you are interested in. - * @param flags Additional option flags. Use {@link #GET_META_DATA} to - * retrieve any meta-data associated with the permission group. - * - * @return Returns a {@link PermissionGroupInfo} containing information - * about the permission. - */ - public abstract PermissionGroupInfo getPermissionGroupInfo(String name, - int flags) throws NameNotFoundException; - - /** - * Retrieve all of the known permission groups in the system. - * - * @param flags Additional option flags. Use {@link #GET_META_DATA} to - * retrieve any meta-data associated with the permission group. - * - * @return Returns a list of {@link PermissionGroupInfo} containing - * information about all of the known permission groups. - */ - public abstract List<PermissionGroupInfo> getAllPermissionGroups(int flags); - - /** - * Retrieve all of the information we know about a particular - * package/application. - * - * <p>Throws {@link NameNotFoundException} if an application with the given - * package name can not be found on the system. - * - * @param packageName The full name (i.e. com.google.apps.contacts) of an - * application. - * @param flags Additional option flags. Use any combination of - * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, - * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. - * - * @return {@link ApplicationInfo} Returns ApplicationInfo object containing - * information about the package. - * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not - * found in the list of installed applications, - * the application information is retrieved from the - * list of uninstalled applications(which includes - * installed applications as well as applications - * with data directory ie applications which had been - * deleted with DONT_DELTE_DATA flag set). - * - * @see #GET_META_DATA - * @see #GET_SHARED_LIBRARY_FILES - * @see #GET_UNINSTALLED_PACKAGES - */ - public abstract ApplicationInfo getApplicationInfo(String packageName, - int flags) throws NameNotFoundException; - - /** - * Retrieve all of the information we know about a particular activity - * class. - * - * <p>Throws {@link NameNotFoundException} if an activity with the given - * class name can not be found on the system. - * - * @param className The full name (i.e. - * com.google.apps.contacts.ContactsList) of an Activity - * class. - * @param flags Additional option flags. Use any combination of - * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, - * to modify the data (in ApplicationInfo) returned. - * - * @return {@link ActivityInfo} containing information about the activity. - * - * @see #GET_INTENT_FILTERS - * @see #GET_META_DATA - * @see #GET_SHARED_LIBRARY_FILES - */ - public abstract ActivityInfo getActivityInfo(ComponentName className, - int flags) throws NameNotFoundException; - - /** - * Retrieve all of the information we know about a particular receiver - * class. - * - * <p>Throws {@link NameNotFoundException} if a receiver with the given - * class name can not be found on the system. - * - * @param className The full name (i.e. - * com.google.apps.contacts.CalendarAlarm) of a Receiver - * class. - * @param flags Additional option flags. Use any combination of - * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, - * to modify the data returned. - * - * @return {@link ActivityInfo} containing information about the receiver. - * - * @see #GET_INTENT_FILTERS - * @see #GET_META_DATA - * @see #GET_SHARED_LIBRARY_FILES - */ - public abstract ActivityInfo getReceiverInfo(ComponentName className, - int flags) throws NameNotFoundException; - - /** - * Retrieve all of the information we know about a particular service - * class. - * - * <p>Throws {@link NameNotFoundException} if a service with the given - * class name can not be found on the system. - * - * @param className The full name (i.e. - * com.google.apps.media.BackgroundPlayback) of a Service - * class. - * @param flags Additional option flags. Use any combination of - * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, - * to modify the data returned. - * - * @return ServiceInfo containing information about the service. - * - * @see #GET_META_DATA - * @see #GET_SHARED_LIBRARY_FILES - */ - public abstract ServiceInfo getServiceInfo(ComponentName className, - int flags) throws NameNotFoundException; - - /** - * Return a List of all packages that are installed - * on the device. - * - * @param flags Additional option flags. Use any combination of - * {@link #GET_ACTIVITIES}, - * {@link #GET_GIDS}, - * {@link #GET_CONFIGURATIONS}, - * {@link #GET_INSTRUMENTATION}, - * {@link #GET_PERMISSIONS}, - * {@link #GET_PROVIDERS}, - * {@link #GET_RECEIVERS}, - * {@link #GET_SERVICES}, - * {@link #GET_SIGNATURES}, - * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. - * - * @return A List of PackageInfo objects, one for each package that is - * installed on the device. In the unlikely case of there being no - * installed packages, an empty list is returned. - * If flag GET_UNINSTALLED_PACKAGES is set, a list of all - * applications including those deleted with DONT_DELETE_DATA - * (partially installed apps with data directory) will be returned. - * - * @see #GET_ACTIVITIES - * @see #GET_GIDS - * @see #GET_CONFIGURATIONS - * @see #GET_INSTRUMENTATION - * @see #GET_PERMISSIONS - * @see #GET_PROVIDERS - * @see #GET_RECEIVERS - * @see #GET_SERVICES - * @see #GET_SIGNATURES - * @see #GET_UNINSTALLED_PACKAGES - * - */ - public abstract List<PackageInfo> getInstalledPackages(int flags); - - /** - * Check whether a particular package has been granted a particular - * permission. - * - * @param permName The name of the permission you are checking for, - * @param pkgName The name of the package you are checking against. - * - * @return If the package has the permission, PERMISSION_GRANTED is - * returned. If it does not have the permission, PERMISSION_DENIED - * is returned. - * - * @see #PERMISSION_GRANTED - * @see #PERMISSION_DENIED - */ - public abstract int checkPermission(String permName, String pkgName); - - /** - * Add a new dynamic permission to the system. For this to work, your - * package must have defined a permission tree through the - * {@link android.R.styleable#AndroidManifestPermissionTree - * <permission-tree>} tag in its manifest. A package can only add - * permissions to trees that were defined by either its own package or - * another with the same user id; a permission is in a tree if it - * matches the name of the permission tree + ".": for example, - * "com.foo.bar" is a member of the permission tree "com.foo". - * - * <p>It is good to make your permission tree name descriptive, because you - * are taking possession of that entire set of permission names. Thus, it - * must be under a domain you control, with a suffix that will not match - * any normal permissions that may be declared in any applications that - * are part of that domain. - * - * <p>New permissions must be added before - * any .apks are installed that use those permissions. Permissions you - * add through this method are remembered across reboots of the device. - * If the given permission already exists, the info you supply here - * will be used to update it. - * - * @param info Description of the permission to be added. - * - * @return Returns true if a new permission was created, false if an - * existing one was updated. - * - * @throws SecurityException if you are not allowed to add the - * given permission name. - * - * @see #removePermission(String) - */ - public abstract boolean addPermission(PermissionInfo info); - - /** - * Removes a permission that was previously added with - * {@link #addPermission(PermissionInfo)}. The same ownership rules apply - * -- you are only allowed to remove permissions that you are allowed - * to add. - * - * @param name The name of the permission to remove. - * - * @throws SecurityException if you are not allowed to remove the - * given permission name. - * - * @see #addPermission(PermissionInfo) - */ - public abstract void removePermission(String name); - - /** - * Compare the signatures of two packages to determine if the same - * signature appears in both of them. If they do contain the same - * signature, then they are allowed special privileges when working - * with each other: they can share the same user-id, run instrumentation - * against each other, etc. - * - * @param pkg1 First package name whose signature will be compared. - * @param pkg2 Second package name whose signature will be compared. - * @return Returns an integer indicating whether there is a matching - * signature: the value is >= 0 if there is a match (or neither package - * is signed), or < 0 if there is not a match. The match result can be - * further distinguished with the success (>= 0) constants - * {@link #SIGNATURE_MATCH}, {@link #SIGNATURE_NEITHER_SIGNED}; or - * failure (< 0) constants {@link #SIGNATURE_FIRST_NOT_SIGNED}, - * {@link #SIGNATURE_SECOND_NOT_SIGNED}, {@link #SIGNATURE_NO_MATCH}, - * or {@link #SIGNATURE_UNKNOWN_PACKAGE}. - * - * @see #SIGNATURE_MATCH - * @see #SIGNATURE_NEITHER_SIGNED - * @see #SIGNATURE_FIRST_NOT_SIGNED - * @see #SIGNATURE_SECOND_NOT_SIGNED - * @see #SIGNATURE_NO_MATCH - * @see #SIGNATURE_UNKNOWN_PACKAGE - */ - public abstract int checkSignatures(String pkg1, String pkg2); - - /** - * Retrieve the names of all packages that are associated with a particular - * user id. In most cases, this will be a single package name, the package - * that has been assigned that user id. Where there are multiple packages - * sharing the same user id through the "sharedUserId" mechanism, all - * packages with that id will be returned. - * - * @param uid The user id for which you would like to retrieve the - * associated packages. - * - * @return Returns an array of one or more packages assigned to the user - * id, or null if there are no known packages with the given id. - */ - public abstract String[] getPackagesForUid(int uid); - - /** - * Retrieve the official name associated with a user id. This name is - * guaranteed to never change, though it is possibly for the underlying - * user id to be changed. That is, if you are storing information about - * user ids in persistent storage, you should use the string returned - * by this function instead of the raw user-id. - * - * @param uid The user id for which you would like to retrieve a name. - * @return Returns a unique name for the given user id, or null if the - * user id is not currently assigned. - */ - public abstract String getNameForUid(int uid); - - /** - * Return the user id associated with a shared user name. Multiple - * applications can specify a shared user name in their manifest and thus - * end up using a common uid. This might be used for new applications - * that use an existing shared user name and need to know the uid of the - * shared user. - * - * @param sharedUserName The shared user name whose uid is to be retrieved. - * @return Returns the uid associated with the shared user, or NameNotFoundException - * if the shared user name is not being used by any installed packages - * @hide - */ - public abstract int getUidForSharedUser(String sharedUserName) - throws NameNotFoundException; - - /** - * Return a List of all application packages that are installed on the - * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all - * applications including those deleted with DONT_DELETE_DATA(partially - * installed apps with data directory) will be returned. - * - * @param flags Additional option flags. Use any combination of - * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, - * {link #GET_UNINSTALLED_PACKAGES} to modify the data returned. - * - * @return A List of ApplicationInfo objects, one for each application that - * is installed on the device. In the unlikely case of there being - * no installed applications, an empty list is returned. - * If flag GET_UNINSTALLED_PACKAGES is set, a list of all - * applications including those deleted with DONT_DELETE_DATA - * (partially installed apps with data directory) will be returned. - * - * @see #GET_META_DATA - * @see #GET_SHARED_LIBRARY_FILES - * @see #GET_UNINSTALLED_PACKAGES - */ - public abstract List<ApplicationInfo> getInstalledApplications(int flags); - - /** - * Get a list of shared libraries that are available on the - * system. - * - * @return An array of shared library names that are - * available on the system, or null if none are installed. - * - */ - public abstract String[] getSystemSharedLibraryNames(); - - /** - * Determine the best action to perform for a given Intent. This is how - * {@link Intent#resolveActivity} finds an activity if a class has not - * been explicitly specified. - * - * @param intent An intent containing all of the desired specification - * (action, data, type, category, and/or component). - * @param flags Additional option flags. The most important is - * MATCH_DEFAULT_ONLY, to limit the resolution to only - * those activities that support the CATEGORY_DEFAULT. - * - * @return Returns a ResolveInfo containing the final activity intent that - * was determined to be the best action. Returns null if no - * matching activity was found. - * - * @see #MATCH_DEFAULT_ONLY - * @see #GET_INTENT_FILTERS - * @see #GET_RESOLVED_FILTER - */ - public abstract ResolveInfo resolveActivity(Intent intent, int flags); - - /** - * Retrieve all activities that can be performed for the given intent. - * - * @param intent The desired intent as per resolveActivity(). - * @param flags Additional option flags. The most important is - * MATCH_DEFAULT_ONLY, to limit the resolution to only - * those activities that support the CATEGORY_DEFAULT. - * - * @return A List<ResolveInfo> containing one entry for each matching - * Activity. These are ordered from best to worst match -- that - * is, the first item in the list is what is returned by - * resolveActivity(). If there are no matching activities, an empty - * list is returned. - * - * @see #MATCH_DEFAULT_ONLY - * @see #GET_INTENT_FILTERS - * @see #GET_RESOLVED_FILTER - */ - public abstract List<ResolveInfo> queryIntentActivities(Intent intent, - int flags); - - /** - * Retrieve a set of activities that should be presented to the user as - * similar options. This is like {@link #queryIntentActivities}, except it - * also allows you to supply a list of more explicit Intents that you would - * like to resolve to particular options, and takes care of returning the - * final ResolveInfo list in a reasonable order, with no duplicates, based - * on those inputs. - * - * @param caller The class name of the activity that is making the - * request. This activity will never appear in the output - * list. Can be null. - * @param specifics An array of Intents that should be resolved to the - * first specific results. Can be null. - * @param intent The desired intent as per resolveActivity(). - * @param flags Additional option flags. The most important is - * MATCH_DEFAULT_ONLY, to limit the resolution to only - * those activities that support the CATEGORY_DEFAULT. - * - * @return A List<ResolveInfo> containing one entry for each matching - * Activity. These are ordered first by all of the intents resolved - * in <var>specifics</var> and then any additional activities that - * can handle <var>intent</var> but did not get included by one of - * the <var>specifics</var> intents. If there are no matching - * activities, an empty list is returned. - * - * @see #MATCH_DEFAULT_ONLY - * @see #GET_INTENT_FILTERS - * @see #GET_RESOLVED_FILTER - */ - public abstract List<ResolveInfo> queryIntentActivityOptions( - ComponentName caller, Intent[] specifics, Intent intent, int flags); - - /** - * Retrieve all receivers that can handle a broadcast of the given intent. - * - * @param intent The desired intent as per resolveActivity(). - * @param flags Additional option flags. The most important is - * MATCH_DEFAULT_ONLY, to limit the resolution to only - * those activities that support the CATEGORY_DEFAULT. - * - * @return A List<ResolveInfo> containing one entry for each matching - * Receiver. These are ordered from first to last in priority. If - * there are no matching receivers, an empty list is returned. - * - * @see #MATCH_DEFAULT_ONLY - * @see #GET_INTENT_FILTERS - * @see #GET_RESOLVED_FILTER - */ - public abstract List<ResolveInfo> queryBroadcastReceivers(Intent intent, - int flags); - - /** - * Determine the best service to handle for a given Intent. - * - * @param intent An intent containing all of the desired specification - * (action, data, type, category, and/or component). - * @param flags Additional option flags. - * - * @return Returns a ResolveInfo containing the final service intent that - * was determined to be the best action. Returns null if no - * matching service was found. - * - * @see #GET_INTENT_FILTERS - * @see #GET_RESOLVED_FILTER - */ - public abstract ResolveInfo resolveService(Intent intent, int flags); - - /** - * Retrieve all services that can match the given intent. - * - * @param intent The desired intent as per resolveService(). - * @param flags Additional option flags. - * - * @return A List<ResolveInfo> containing one entry for each matching - * ServiceInfo. These are ordered from best to worst match -- that - * is, the first item in the list is what is returned by - * resolveService(). If there are no matching services, an empty - * list is returned. - * - * @see #GET_INTENT_FILTERS - * @see #GET_RESOLVED_FILTER - */ - public abstract List<ResolveInfo> queryIntentServices(Intent intent, - int flags); - - /** - * Find a single content provider by its base path name. - * - * @param name The name of the provider to find. - * @param flags Additional option flags. Currently should always be 0. - * - * @return ContentProviderInfo Information about the provider, if found, - * else null. - */ - public abstract ProviderInfo resolveContentProvider(String name, - int flags); - - /** - * Retrieve content provider information. - * - * <p><em>Note: unlike most other methods, an empty result set is indicated - * by a null return instead of an empty list.</em> - * - * @param processName If non-null, limits the returned providers to only - * those that are hosted by the given process. If null, - * all content providers are returned. - * @param uid If <var>processName</var> is non-null, this is the required - * uid owning the requested content providers. - * @param flags Additional option flags. Currently should always be 0. - * - * @return A List<ContentProviderInfo> containing one entry for each - * content provider either patching <var>processName</var> or, if - * <var>processName</var> is null, all known content providers. - * <em>If there are no matching providers, null is returned.</em> - */ - public abstract List<ProviderInfo> queryContentProviders( - String processName, int uid, int flags); - - /** - * Retrieve all of the information we know about a particular - * instrumentation class. - * - * <p>Throws {@link NameNotFoundException} if instrumentation with the - * given class name can not be found on the system. - * - * @param className The full name (i.e. - * com.google.apps.contacts.InstrumentList) of an - * Instrumentation class. - * @param flags Additional option flags. Currently should always be 0. - * - * @return InstrumentationInfo containing information about the - * instrumentation. - */ - public abstract InstrumentationInfo getInstrumentationInfo( - ComponentName className, int flags) throws NameNotFoundException; - - /** - * Retrieve information about available instrumentation code. May be used - * to retrieve either all instrumentation code, or only the code targeting - * a particular package. - * - * @param targetPackage If null, all instrumentation is returned; only the - * instrumentation targeting this package name is - * returned. - * @param flags Additional option flags. Currently should always be 0. - * - * @return A List<InstrumentationInfo> containing one entry for each - * matching available Instrumentation. Returns an empty list if - * there is no instrumentation available for the given package. - */ - public abstract List<InstrumentationInfo> queryInstrumentation( - String targetPackage, int flags); - - /** - * Retrieve an image from a package. This is a low-level API used by - * the various package manager info structures (such as - * {@link ComponentInfo} to implement retrieval of their associated - * icon. - * - * @param packageName The name of the package that this icon is coming from. - * Can not be null. - * @param resid The resource identifier of the desired image. Can not be 0. - * @param appInfo Overall information about <var>packageName</var>. This - * may be null, in which case the application information will be retrieved - * for you if needed; if you already have this information around, it can - * be much more efficient to supply it here. - * - * @return Returns a Drawable holding the requested image. Returns null if - * an image could not be found for any reason. - */ - public abstract Drawable getDrawable(String packageName, int resid, - ApplicationInfo appInfo); - - /** - * Retrieve the icon associated with an activity. Given the full name of - * an activity, retrieves the information about it and calls - * {@link ComponentInfo#loadIcon ComponentInfo.loadIcon()} to return its icon. - * If the activity can not be found, NameNotFoundException is thrown. - * - * @param activityName Name of the activity whose icon is to be retrieved. - * - * @return Returns the image of the icon, or the default activity icon if - * it could not be found. Does not return null. - * @throws NameNotFoundException Thrown if the resources for the given - * activity could not be loaded. - * - * @see #getActivityIcon(Intent) - */ - public abstract Drawable getActivityIcon(ComponentName activityName) - throws NameNotFoundException; - - /** - * Retrieve the icon associated with an Intent. If intent.getClassName() is - * set, this simply returns the result of - * getActivityIcon(intent.getClassName()). Otherwise it resolves the intent's - * component and returns the icon associated with the resolved component. - * If intent.getClassName() can not be found or the Intent can not be resolved - * to a component, NameNotFoundException is thrown. - * - * @param intent The intent for which you would like to retrieve an icon. - * - * @return Returns the image of the icon, or the default activity icon if - * it could not be found. Does not return null. - * @throws NameNotFoundException Thrown if the resources for application - * matching the given intent could not be loaded. - * - * @see #getActivityIcon(ComponentName) - */ - public abstract Drawable getActivityIcon(Intent intent) - throws NameNotFoundException; - - /** - * Return the generic icon for an activity that is used when no specific - * icon is defined. - * - * @return Drawable Image of the icon. - */ - public abstract Drawable getDefaultActivityIcon(); - - /** - * Retrieve the icon associated with an application. If it has not defined - * an icon, the default app icon is returned. Does not return null. - * - * @param info Information about application being queried. - * - * @return Returns the image of the icon, or the default application icon - * if it could not be found. - * - * @see #getApplicationIcon(String) - */ - public abstract Drawable getApplicationIcon(ApplicationInfo info); - - /** - * Retrieve the icon associated with an application. Given the name of the - * application's package, retrieves the information about it and calls - * getApplicationIcon() to return its icon. If the application can not be - * found, NameNotFoundException is thrown. - * - * @param packageName Name of the package whose application icon is to be - * retrieved. - * - * @return Returns the image of the icon, or the default application icon - * if it could not be found. Does not return null. - * @throws NameNotFoundException Thrown if the resources for the given - * application could not be loaded. - * - * @see #getApplicationIcon(ApplicationInfo) - */ - public abstract Drawable getApplicationIcon(String packageName) - throws NameNotFoundException; - - /** - * Retrieve text from a package. This is a low-level API used by - * the various package manager info structures (such as - * {@link ComponentInfo} to implement retrieval of their associated - * labels and other text. - * - * @param packageName The name of the package that this text is coming from. - * Can not be null. - * @param resid The resource identifier of the desired text. Can not be 0. - * @param appInfo Overall information about <var>packageName</var>. This - * may be null, in which case the application information will be retrieved - * for you if needed; if you already have this information around, it can - * be much more efficient to supply it here. - * - * @return Returns a CharSequence holding the requested text. Returns null - * if the text could not be found for any reason. - */ - public abstract CharSequence getText(String packageName, int resid, - ApplicationInfo appInfo); - - /** - * Retrieve an XML file from a package. This is a low-level API used to - * retrieve XML meta data. - * - * @param packageName The name of the package that this xml is coming from. - * Can not be null. - * @param resid The resource identifier of the desired xml. Can not be 0. - * @param appInfo Overall information about <var>packageName</var>. This - * may be null, in which case the application information will be retrieved - * for you if needed; if you already have this information around, it can - * be much more efficient to supply it here. - * - * @return Returns an XmlPullParser allowing you to parse out the XML - * data. Returns null if the xml resource could not be found for any - * reason. - */ - public abstract XmlResourceParser getXml(String packageName, int resid, - ApplicationInfo appInfo); - - /** - * Return the label to use for this application. - * - * @return Returns the label associated with this application, or null if - * it could not be found for any reason. - * @param info The application to get the label of - */ - public abstract CharSequence getApplicationLabel(ApplicationInfo info); - - /** - * Retrieve the resources associated with an activity. Given the full - * name of an activity, retrieves the information about it and calls - * getResources() to return its application's resources. If the activity - * can not be found, NameNotFoundException is thrown. - * - * @param activityName Name of the activity whose resources are to be - * retrieved. - * - * @return Returns the application's Resources. - * @throws NameNotFoundException Thrown if the resources for the given - * application could not be loaded. - * - * @see #getResourcesForApplication(ApplicationInfo) - */ - public abstract Resources getResourcesForActivity(ComponentName activityName) - throws NameNotFoundException; - - /** - * Retrieve the resources for an application. Throws NameNotFoundException - * if the package is no longer installed. - * - * @param app Information about the desired application. - * - * @return Returns the application's Resources. - * @throws NameNotFoundException Thrown if the resources for the given - * application could not be loaded (most likely because it was uninstalled). - */ - public abstract Resources getResourcesForApplication(ApplicationInfo app) - throws NameNotFoundException; - - /** - * Retrieve the resources associated with an application. Given the full - * package name of an application, retrieves the information about it and - * calls getResources() to return its application's resources. If the - * appPackageName can not be found, NameNotFoundException is thrown. - * - * @param appPackageName Package name of the application whose resources - * are to be retrieved. - * - * @return Returns the application's Resources. - * @throws NameNotFoundException Thrown if the resources for the given - * application could not be loaded. - * - * @see #getResourcesForApplication(ApplicationInfo) - */ - public abstract Resources getResourcesForApplication(String appPackageName) - throws NameNotFoundException; - - /** - * Retrieve overall information about an application package defined - * in a package archive file - * - * @param archiveFilePath The path to the archive file - * @param flags Additional option flags. Use any combination of - * {@link #GET_ACTIVITIES}, - * {@link #GET_GIDS}, - * {@link #GET_CONFIGURATIONS}, - * {@link #GET_INSTRUMENTATION}, - * {@link #GET_PERMISSIONS}, - * {@link #GET_PROVIDERS}, - * {@link #GET_RECEIVERS}, - * {@link #GET_SERVICES}, - * {@link #GET_SIGNATURES}, to modify the data returned. - * - * @return Returns the information about the package. Returns - * null if the package could not be successfully parsed. - * - * @see #GET_ACTIVITIES - * @see #GET_GIDS - * @see #GET_CONFIGURATIONS - * @see #GET_INSTRUMENTATION - * @see #GET_PERMISSIONS - * @see #GET_PROVIDERS - * @see #GET_RECEIVERS - * @see #GET_SERVICES - * @see #GET_SIGNATURES - * - */ - public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { - PackageParser packageParser = new PackageParser(archiveFilePath); - DisplayMetrics metrics = new DisplayMetrics(); - metrics.setToDefaults(); - final File sourceFile = new File(archiveFilePath); - PackageParser.Package pkg = packageParser.parsePackage( - sourceFile, archiveFilePath, metrics, 0); - if (pkg == null) { - return null; - } - return PackageParser.generatePackageInfo(pkg, null, flags); - } - - /** - * Install a package. Since this may take a little while, the result will - * be posted back to the given observer. An installation will fail if the calling context - * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the - * package named in the package file's manifest is already installed, or if there's no space - * available on the device. - * - * @param packageURI The location of the package file to install. This can be a 'file:' or a - * 'content:' URI. - * @param observer An observer callback to get notified when the package installation is - * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be - * called when that happens. observer may be null to indicate that no callback is desired. - * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, - * {@link #REPLACE_EXISTING_PACKAGE} - * - * @see #installPackage(android.net.Uri) - */ - public abstract void installPackage( - Uri packageURI, IPackageInstallObserver observer, int flags); - - /** - * Attempts to delete a package. Since this may take a little while, the result will - * be posted back to the given observer. A deletion will fail if the calling context - * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the - * named package cannot be found, or if the named package is a "system package". - * (TODO: include pointer to documentation on "system packages") - * - * @param packageName The name of the package to delete - * @param observer An observer callback to get notified when the package deletion is - * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be - * called when that happens. observer may be null to indicate that no callback is desired. - * @param flags - possible values: {@link #DONT_DELETE_DATA} - * - * @hide - */ - public abstract void deletePackage( - String packageName, IPackageDeleteObserver observer, int flags); - /** - * Attempts to clear the user data directory of an application. - * Since this may take a little while, the result will - * be posted back to the given observer. A deletion will fail if the - * named package cannot be found, or if the named package is a "system package". - * - * @param packageName The name of the package - * @param observer An observer callback to get notified when the operation is finished - * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)} - * will be called when that happens. observer may be null to indicate that - * no callback is desired. - * - * @hide - */ - public abstract void clearApplicationUserData(String packageName, - IPackageDataObserver observer); - /** - * Attempts to delete the cache files associated with an application. - * Since this may take a little while, the result will - * be posted back to the given observer. A deletion will fail if the calling context - * lacks the {@link android.Manifest.permission#DELETE_CACHE_FILES} permission, if the - * named package cannot be found, or if the named package is a "system package". - * - * @param packageName The name of the package to delete - * @param observer An observer callback to get notified when the cache file deletion - * is complete. - * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)} - * will be called when that happens. observer may be null to indicate that - * no callback is desired. - * - * @hide - */ - public abstract void deleteApplicationCacheFiles(String packageName, - IPackageDataObserver observer); - - /** - * Free storage by deleting LRU sorted list of cache files across - * all applications. If the currently available free storage - * on the device is greater than or equal to the requested - * free storage, no cache files are cleared. If the currently - * available storage on the device is less than the requested - * free storage, some or all of the cache files across - * all applications are deleted (based on last accessed time) - * to increase the free storage space on the device to - * the requested value. There is no guarantee that clearing all - * the cache files from all applications will clear up - * enough storage to achieve the desired value. - * @param freeStorageSize The number of bytes of storage to be - * freed by the system. Say if freeStorageSize is XX, - * and the current free storage is YY, - * if XX is less than YY, just return. if not free XX-YY number - * of bytes if possible. - * @param observer call back used to notify when - * the operation is completed - * - * @hide - */ - public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer); - - /** - * Free storage by deleting LRU sorted list of cache files across - * all applications. If the currently available free storage - * on the device is greater than or equal to the requested - * free storage, no cache files are cleared. If the currently - * available storage on the device is less than the requested - * free storage, some or all of the cache files across - * all applications are deleted (based on last accessed time) - * to increase the free storage space on the device to - * the requested value. There is no guarantee that clearing all - * the cache files from all applications will clear up - * enough storage to achieve the desired value. - * @param freeStorageSize The number of bytes of storage to be - * freed by the system. Say if freeStorageSize is XX, - * and the current free storage is YY, - * if XX is less than YY, just return. if not free XX-YY number - * of bytes if possible. - * @param opFinishedIntent PendingIntent call back used to - * notify when the operation is completed.May be null - * to indicate that no call back is desired. - * - * @hide - */ - public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent); - - /** - * Retrieve the size information for a package. - * Since this may take a little while, the result will - * be posted back to the given observer. The calling context - * should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission. - * - * @param packageName The name of the package whose size information is to be retrieved - * @param observer An observer callback to get notified when the operation - * is complete. - * {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)} - * The observer's callback is invoked with a PackageStats object(containing the - * code, data and cache sizes of the package) and a boolean value representing - * the status of the operation. observer may be null to indicate that - * no callback is desired. - * - * @hide - */ - public abstract void getPackageSizeInfo(String packageName, - IPackageStatsObserver observer); - - /** - * Install a package. - * - * @param packageURI The location of the package file to install - * - * @see #installPackage(android.net.Uri, IPackageInstallObserver, int) - */ - public void installPackage(Uri packageURI) { - installPackage(packageURI, null, 0); - } - - /** - * Add a new package to the list of preferred packages. This new package - * will be added to the front of the list (removed from its current location - * if already listed), meaning it will now be preferred over all other - * packages when resolving conflicts. - * - * @param packageName The package name of the new package to make preferred. - */ - public abstract void addPackageToPreferred(String packageName); - - /** - * Remove a package from the list of preferred packages. If it was on - * the list, it will no longer be preferred over other packages. - * - * @param packageName The package name to remove. - */ - public abstract void removePackageFromPreferred(String packageName); - - /** - * Retrieve the list of all currently configured preferred packages. The - * first package on the list is the most preferred, the last is the - * least preferred. - * - * @param flags Additional option flags. Use any combination of - * {@link #GET_ACTIVITIES}, - * {@link #GET_GIDS}, - * {@link #GET_CONFIGURATIONS}, - * {@link #GET_INSTRUMENTATION}, - * {@link #GET_PERMISSIONS}, - * {@link #GET_PROVIDERS}, - * {@link #GET_RECEIVERS}, - * {@link #GET_SERVICES}, - * {@link #GET_SIGNATURES}, to modify the data returned. - * - * @return Returns a list of PackageInfo objects describing each - * preferred application, in order of preference. - * - * @see #GET_ACTIVITIES - * @see #GET_GIDS - * @see #GET_CONFIGURATIONS - * @see #GET_INSTRUMENTATION - * @see #GET_PERMISSIONS - * @see #GET_PROVIDERS - * @see #GET_RECEIVERS - * @see #GET_SERVICES - * @see #GET_SIGNATURES - */ - public abstract List<PackageInfo> getPreferredPackages(int flags); - - /** - * Add a new preferred activity mapping to the system. This will be used - * to automatically select the given activity component when - * {@link Context#startActivity(Intent) Context.startActivity()} finds - * multiple matching activities and also matches the given filter. - * - * @param filter The set of intents under which this activity will be - * made preferred. - * @param match The IntentFilter match category that this preference - * applies to. - * @param set The set of activities that the user was picking from when - * this preference was made. - * @param activity The component name of the activity that is to be - * preferred. - */ - public abstract void addPreferredActivity(IntentFilter filter, int match, - ComponentName[] set, ComponentName activity); - - /** - * Remove all preferred activity mappings, previously added with - * {@link #addPreferredActivity}, from the - * system whose activities are implemented in the given package name. - * - * @param packageName The name of the package whose preferred activity - * mappings are to be removed. - */ - public abstract void clearPackagePreferredActivities(String packageName); - - /** - * Retrieve all preferred activities, previously added with - * {@link #addPreferredActivity}, that are - * currently registered with the system. - * - * @param outFilters A list in which to place the filters of all of the - * preferred activities, or null for none. - * @param outActivities A list in which to place the component names of - * all of the preferred activities, or null for none. - * @param packageName An option package in which you would like to limit - * the list. If null, all activities will be returned; if non-null, only - * those activities in the given package are returned. - * - * @return Returns the total number of registered preferred activities - * (the number of distinct IntentFilter records, not the number of unique - * activity components) that were found. - */ - public abstract int getPreferredActivities(List<IntentFilter> outFilters, - List<ComponentName> outActivities, String packageName); - - /** - * Set the enabled setting for a package component (activity, receiver, service, provider). - * This setting will override any enabled state which may have been set by the component in its - * manifest. - * - * @param componentName The component to enable - * @param newState The new enabled state for the component. The legal values for this state - * are: - * {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED} - * and - * {@link #COMPONENT_ENABLED_STATE_DEFAULT} - * The last one removes the setting, thereby restoring the component's state to - * whatever was set in it's manifest (or enabled, by default). - * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. - */ - public abstract void setComponentEnabledSetting(ComponentName componentName, - int newState, int flags); - - - /** - * Return the the enabled setting for a package component (activity, - * receiver, service, provider). This returns the last value set by - * {@link #setComponentEnabledSetting(ComponentName, int, int)}; in most - * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since - * the value originally specified in the manifest has not been modified. - * - * @param componentName The component to retrieve. - * @return Returns the current enabled state for the component. May - * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or - * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the - * component's enabled state is based on the original information in - * the manifest as found in {@link ComponentInfo}. - */ - public abstract int getComponentEnabledSetting(ComponentName componentName); - - /** - * Set the enabled setting for an application - * This setting will override any enabled state which may have been set by the application in - * its manifest. It also overrides the enabled state set in the manifest for any of the - * application's components. It does not override any enabled state set by - * {@link #setComponentEnabledSetting} for any of the application's components. - * - * @param packageName The package name of the application to enable - * @param newState The new enabled state for the component. The legal values for this state - * are: - * {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED} - * and - * {@link #COMPONENT_ENABLED_STATE_DEFAULT} - * The last one removes the setting, thereby restoring the applications's state to - * whatever was set in its manifest (or enabled, by default). - * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. - */ - public abstract void setApplicationEnabledSetting(String packageName, - int newState, int flags); - - /** - * Return the the enabled setting for an application. This returns - * the last value set by - * {@link #setApplicationEnabledSetting(String, int, int)}; in most - * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since - * the value originally specified in the manifest has not been modified. - * - * @param packageName The component to retrieve. - * @return Returns the current enabled state for the component. May - * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or - * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the - * application's enabled state is based on the original information in - * the manifest as found in {@link ComponentInfo}. - */ - public abstract int getApplicationEnabledSetting(String packageName); - - /** - * Return whether the device has been booted into safe mode. - */ - public abstract boolean isSafeMode(); -} diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java deleted file mode 100644 index 4ae8b08..0000000 --- a/core/java/android/content/pm/PackageParser.java +++ /dev/null @@ -1,2352 +0,0 @@ -/* - * 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.pm; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.ComponentName; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.AssetManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.os.Bundle; -import android.os.PatternMatcher; -import android.util.AttributeSet; -import android.util.Config; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import com.android.internal.util.XmlUtils; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.WeakReference; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -/** - * Package archive parsing - * - * {@hide} - */ -public class PackageParser { - - private String mArchiveSourcePath; - private String[] mSeparateProcesses; - private int mSdkVersion; - - private int mParseError = PackageManager.INSTALL_SUCCEEDED; - - private static final Object mSync = new Object(); - private static WeakReference<byte[]> mReadBuffer; - - /** If set to true, we will only allow package files that exactly match - * the DTD. Otherwise, we try to get as much from the package as we - * can without failing. This should normally be set to false, to - * support extensions to the DTD in future versions. */ - private static final boolean RIGID_PARSER = false; - - private static final String TAG = "PackageParser"; - - public PackageParser(String archiveSourcePath) { - mArchiveSourcePath = archiveSourcePath; - } - - public void setSeparateProcesses(String[] procs) { - mSeparateProcesses = procs; - } - - public void setSdkVersion(int sdkVersion) { - mSdkVersion = sdkVersion; - } - - private static final boolean isPackageFilename(String name) { - return name.endsWith(".apk"); - } - - /** - * Generate and return the {@link PackageInfo} for a parsed package. - * - * @param p the parsed package. - * @param flags indicating which optional information is included. - */ - public static PackageInfo generatePackageInfo(PackageParser.Package p, - int gids[], int flags) { - - PackageInfo pi = new PackageInfo(); - pi.packageName = p.packageName; - pi.versionCode = p.mVersionCode; - pi.versionName = p.mVersionName; - pi.sharedUserId = p.mSharedUserId; - pi.sharedUserLabel = p.mSharedUserLabel; - pi.applicationInfo = p.applicationInfo; - if ((flags&PackageManager.GET_GIDS) != 0) { - pi.gids = gids; - } - if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) { - int N = p.configPreferences.size(); - if (N > 0) { - pi.configPreferences = new ConfigurationInfo[N]; - for (int i=0; i<N; i++) { - pi.configPreferences[i] = p.configPreferences.get(i); - } - } - } - if ((flags&PackageManager.GET_ACTIVITIES) != 0) { - int N = p.activities.size(); - if (N > 0) { - pi.activities = new ActivityInfo[N]; - for (int i=0; i<N; i++) { - final Activity activity = p.activities.get(i); - if (activity.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.activities[i] = generateActivityInfo(p.activities.get(i), flags); - } - } - } - } - if ((flags&PackageManager.GET_RECEIVERS) != 0) { - int N = p.receivers.size(); - if (N > 0) { - pi.receivers = new ActivityInfo[N]; - for (int i=0; i<N; i++) { - final Activity activity = p.receivers.get(i); - if (activity.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.receivers[i] = generateActivityInfo(p.receivers.get(i), flags); - } - } - } - } - if ((flags&PackageManager.GET_SERVICES) != 0) { - int N = p.services.size(); - if (N > 0) { - pi.services = new ServiceInfo[N]; - for (int i=0; i<N; i++) { - final Service service = p.services.get(i); - if (service.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.services[i] = generateServiceInfo(p.services.get(i), flags); - } - } - } - } - if ((flags&PackageManager.GET_PROVIDERS) != 0) { - int N = p.providers.size(); - if (N > 0) { - pi.providers = new ProviderInfo[N]; - for (int i=0; i<N; i++) { - final Provider provider = p.providers.get(i); - if (provider.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.providers[i] = generateProviderInfo(p.providers.get(i), flags); - } - } - } - } - if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) { - int N = p.instrumentation.size(); - if (N > 0) { - pi.instrumentation = new InstrumentationInfo[N]; - for (int i=0; i<N; i++) { - pi.instrumentation[i] = generateInstrumentationInfo( - p.instrumentation.get(i), flags); - } - } - } - if ((flags&PackageManager.GET_PERMISSIONS) != 0) { - int N = p.permissions.size(); - if (N > 0) { - pi.permissions = new PermissionInfo[N]; - for (int i=0; i<N; i++) { - pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags); - } - } - N = p.requestedPermissions.size(); - if (N > 0) { - pi.requestedPermissions = new String[N]; - for (int i=0; i<N; i++) { - pi.requestedPermissions[i] = p.requestedPermissions.get(i); - } - } - } - if ((flags&PackageManager.GET_SIGNATURES) != 0) { - int N = p.mSignatures.length; - if (N > 0) { - pi.signatures = new Signature[N]; - System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N); - } - } - return pi; - } - - private Certificate[] loadCertificates(JarFile jarFile, JarEntry je, - byte[] readBuffer) { - try { - // We must read the stream for the JarEntry to retrieve - // its certificates. - InputStream is = jarFile.getInputStream(je); - while (is.read(readBuffer, 0, readBuffer.length) != -1) { - // not using - } - is.close(); - return je != null ? je.getCertificates() : null; - } catch (IOException e) { - Log.w(TAG, "Exception reading " + je.getName() + " in " - + jarFile.getName(), e); - } - return null; - } - - public final static int PARSE_IS_SYSTEM = 0x0001; - public final static int PARSE_CHATTY = 0x0002; - public final static int PARSE_MUST_BE_APK = 0x0004; - public final static int PARSE_IGNORE_PROCESSES = 0x0008; - - public int getParseError() { - return mParseError; - } - - public Package parsePackage(File sourceFile, String destFileName, - DisplayMetrics metrics, int flags) { - mParseError = PackageManager.INSTALL_SUCCEEDED; - - mArchiveSourcePath = sourceFile.getPath(); - if (!sourceFile.isFile()) { - Log.w(TAG, "Skipping dir: " + mArchiveSourcePath); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; - return null; - } - if (!isPackageFilename(sourceFile.getName()) - && (flags&PARSE_MUST_BE_APK) != 0) { - if ((flags&PARSE_IS_SYSTEM) == 0) { - // We expect to have non-.apk files in the system dir, - // so don't warn about them. - Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath); - } - mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; - return null; - } - - if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d( - TAG, "Scanning package: " + mArchiveSourcePath); - - XmlResourceParser parser = null; - AssetManager assmgr = null; - boolean assetError = true; - try { - assmgr = new AssetManager(); - if(assmgr.addAssetPath(mArchiveSourcePath) != 0) { - parser = assmgr.openXmlResourceParser("AndroidManifest.xml"); - assetError = false; - } else { - Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath); - } - } catch (Exception e) { - Log.w(TAG, "Unable to read AndroidManifest.xml of " - + mArchiveSourcePath, e); - } - if(assetError) { - if (assmgr != null) assmgr.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; - return null; - } - String[] errorText = new String[1]; - Package pkg = null; - Exception errorException = null; - try { - // XXXX todo: need to figure out correct configuration. - Resources res = new Resources(assmgr, metrics, null); - pkg = parsePackage(res, parser, flags, errorText); - } catch (Exception e) { - errorException = e; - mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; - } - - - if (pkg == null) { - if (errorException != null) { - Log.w(TAG, mArchiveSourcePath, errorException); - } else { - Log.w(TAG, mArchiveSourcePath + " (at " - + parser.getPositionDescription() - + "): " + errorText[0]); - } - parser.close(); - assmgr.close(); - if (mParseError == PackageManager.INSTALL_SUCCEEDED) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - } - return null; - } - - parser.close(); - assmgr.close(); - - pkg.applicationInfo.sourceDir = destFileName; - pkg.applicationInfo.publicSourceDir = destFileName; - pkg.mSignatures = null; - - return pkg; - } - - public boolean collectCertificates(Package pkg, int flags) { - pkg.mSignatures = null; - - WeakReference<byte[]> readBufferRef; - byte[] readBuffer = null; - synchronized (mSync) { - readBufferRef = mReadBuffer; - if (readBufferRef != null) { - mReadBuffer = null; - readBuffer = readBufferRef.get(); - } - if (readBuffer == null) { - readBuffer = new byte[8192]; - readBufferRef = new WeakReference<byte[]>(readBuffer); - } - } - - try { - JarFile jarFile = new JarFile(mArchiveSourcePath); - - Certificate[] certs = null; - - if ((flags&PARSE_IS_SYSTEM) != 0) { - // If this package comes from the system image, then we - // can trust it... we'll just use the AndroidManifest.xml - // to retrieve its signatures, not validating all of the - // files. - JarEntry jarEntry = jarFile.getJarEntry("AndroidManifest.xml"); - certs = loadCertificates(jarFile, jarEntry, readBuffer); - if (certs == null) { - Log.e(TAG, "Package " + pkg.packageName - + " has no certificates at entry " - + jarEntry.getName() + "; ignoring!"); - jarFile.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; - return false; - } - if (false) { - Log.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry - + " certs=" + (certs != null ? certs.length : 0)); - if (certs != null) { - final int N = certs.length; - for (int i=0; i<N; i++) { - Log.i(TAG, " Public key: " - + certs[i].getPublicKey().getEncoded() - + " " + certs[i].getPublicKey()); - } - } - } - - } else { - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - JarEntry je = (JarEntry)entries.nextElement(); - if (je.isDirectory()) continue; - if (je.getName().startsWith("META-INF/")) continue; - Certificate[] localCerts = loadCertificates(jarFile, je, - readBuffer); - if (false) { - Log.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName() - + ": certs=" + certs + " (" - + (certs != null ? certs.length : 0) + ")"); - } - if (localCerts == null) { - Log.e(TAG, "Package " + pkg.packageName - + " has no certificates at entry " - + je.getName() + "; ignoring!"); - jarFile.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; - return false; - } else if (certs == null) { - certs = localCerts; - } else { - // Ensure all certificates match. - for (int i=0; i<certs.length; i++) { - boolean found = false; - for (int j=0; j<localCerts.length; j++) { - if (certs[i] != null && - certs[i].equals(localCerts[j])) { - found = true; - break; - } - } - if (!found || certs.length != localCerts.length) { - Log.e(TAG, "Package " + pkg.packageName - + " has mismatched certificates at entry " - + je.getName() + "; ignoring!"); - jarFile.close(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; - return false; - } - } - } - } - } - jarFile.close(); - - synchronized (mSync) { - mReadBuffer = readBufferRef; - } - - if (certs != null && certs.length > 0) { - final int N = certs.length; - pkg.mSignatures = new Signature[certs.length]; - for (int i=0; i<N; i++) { - pkg.mSignatures[i] = new Signature( - certs[i].getEncoded()); - } - } else { - Log.e(TAG, "Package " + pkg.packageName - + " has no certificates; ignoring!"); - mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; - return false; - } - } catch (CertificateEncodingException e) { - Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; - return false; - } catch (IOException e) { - Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; - return false; - } catch (RuntimeException e) { - Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); - mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; - return false; - } - - return true; - } - - public static String parsePackageName(String packageFilePath, int flags) { - XmlResourceParser parser = null; - AssetManager assmgr = null; - try { - assmgr = new AssetManager(); - int cookie = assmgr.addAssetPath(packageFilePath); - parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); - } catch (Exception e) { - if (assmgr != null) assmgr.close(); - Log.w(TAG, "Unable to read AndroidManifest.xml of " - + packageFilePath, e); - return null; - } - AttributeSet attrs = parser; - String errors[] = new String[1]; - String packageName = null; - try { - packageName = parsePackageName(parser, attrs, flags, errors); - } catch (IOException e) { - Log.w(TAG, packageFilePath, e); - } catch (XmlPullParserException e) { - Log.w(TAG, packageFilePath, e); - } finally { - if (parser != null) parser.close(); - if (assmgr != null) assmgr.close(); - } - if (packageName == null) { - Log.e(TAG, "parsePackageName error: " + errors[0]); - return null; - } - return packageName; - } - - private static String validateName(String name, boolean requiresSeparator) { - final int N = name.length(); - boolean hasSep = false; - boolean front = true; - for (int i=0; i<N; i++) { - final char c = name.charAt(i); - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - front = false; - continue; - } - if (!front) { - if ((c >= '0' && c <= '9') || c == '_') { - continue; - } - } - if (c == '.') { - hasSep = true; - front = true; - continue; - } - return "bad character '" + c + "'"; - } - return hasSep || !requiresSeparator - ? null : "must have at least one '.' separator"; - } - - private static String parsePackageName(XmlPullParser parser, - AttributeSet attrs, int flags, String[] outError) - throws IOException, XmlPullParserException { - - int type; - while ((type=parser.next()) != parser.START_TAG - && type != parser.END_DOCUMENT) { - ; - } - - if (type != parser.START_TAG) { - outError[0] = "No start tag found"; - return null; - } - if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v( - TAG, "Root element name: '" + parser.getName() + "'"); - if (!parser.getName().equals("manifest")) { - outError[0] = "No <manifest> tag"; - return null; - } - String pkgName = attrs.getAttributeValue(null, "package"); - if (pkgName == null || pkgName.length() == 0) { - outError[0] = "<manifest> does not specify package"; - return null; - } - String nameError = validateName(pkgName, true); - if (nameError != null && !"android".equals(pkgName)) { - outError[0] = "<manifest> specifies bad package name \"" - + pkgName + "\": " + nameError; - return null; - } - - return pkgName.intern(); - } - - /** - * Temporary. - */ - static public Signature stringToSignature(String str) { - final int N = str.length(); - byte[] sig = new byte[N]; - for (int i=0; i<N; i++) { - sig[i] = (byte)str.charAt(i); - } - return new Signature(sig); - } - - private Package parsePackage( - Resources res, XmlResourceParser parser, int flags, String[] outError) - throws XmlPullParserException, IOException { - AttributeSet attrs = parser; - - String pkgName = parsePackageName(parser, attrs, flags, outError); - if (pkgName == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; - return null; - } - int type; - - final Package pkg = new Package(pkgName); - pkg.mSystem = (flags&PARSE_IS_SYSTEM) != 0; - boolean foundApp = false; - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifest); - pkg.mVersionCode = sa.getInteger( - com.android.internal.R.styleable.AndroidManifest_versionCode, 0); - pkg.mVersionName = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifest_versionName); - if (pkg.mVersionName != null) { - pkg.mVersionName = pkg.mVersionName.intern(); - } - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifest_sharedUserId); - if (str != null) { - String nameError = validateName(str, true); - if (nameError != null && !"android".equals(pkgName)) { - outError[0] = "<manifest> specifies bad sharedUserId name \"" - + str + "\": " + nameError; - mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; - return null; - } - pkg.mSharedUserId = str.intern(); - pkg.mSharedUserLabel = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); - } - sa.recycle(); - - final int innerDepth = parser.getDepth(); - - int outerDepth = parser.getDepth(); - while ((type=parser.next()) != parser.END_DOCUMENT - && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == parser.END_TAG || type == parser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("application")) { - if (foundApp) { - if (RIGID_PARSER) { - outError[0] = "<manifest> has more than one <application>"; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } else { - Log.w(TAG, "<manifest> has more than one <application>"); - XmlUtils.skipCurrentTag(parser); - continue; - } - } - - foundApp = true; - if (!parseApplication(pkg, res, parser, attrs, flags, outError)) { - return null; - } - } else if (tagName.equals("permission-group")) { - if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) { - return null; - } - } else if (tagName.equals("permission")) { - if (parsePermission(pkg, res, parser, attrs, outError) == null) { - return null; - } - } else if (tagName.equals("permission-tree")) { - if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) { - return null; - } - } else if (tagName.equals("uses-permission")) { - sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestUsesPermission); - - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestUsesPermission_name); - - sa.recycle(); - - if (name != null && !pkg.requestedPermissions.contains(name)) { - pkg.requestedPermissions.add(name); - } - - XmlUtils.skipCurrentTag(parser); - - } else if (tagName.equals("uses-configuration")) { - ConfigurationInfo cPref = new ConfigurationInfo(); - sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestUsesConfiguration); - cPref.reqTouchScreen = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen, - Configuration.TOUCHSCREEN_UNDEFINED); - cPref.reqKeyboardType = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType, - Configuration.KEYBOARD_UNDEFINED); - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard, - false)) { - cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; - } - cPref.reqNavigation = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation, - Configuration.NAVIGATION_UNDEFINED); - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav, - false)) { - cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; - } - sa.recycle(); - pkg.configPreferences.add(cPref); - - XmlUtils.skipCurrentTag(parser); - - } else if (tagName.equals("uses-sdk")) { - if (mSdkVersion > 0) { - sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestUsesSdk); - - int vers = sa.getInt( - com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion, 0); - - sa.recycle(); - - if (vers > mSdkVersion) { - outError[0] = "Requires newer sdk version #" + vers - + " (current version is #" + mSdkVersion + ")"; - mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; - return null; - } - } - - XmlUtils.skipCurrentTag(parser); - - } else if (tagName.equals("instrumentation")) { - if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) { - return null; - } - } else if (tagName.equals("eat-comment")) { - // Just skip this tag - XmlUtils.skipCurrentTag(parser); - continue; - } else if (RIGID_PARSER) { - outError[0] = "Bad element under <manifest>: " - + parser.getName(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } else { - Log.w(TAG, "Bad element under <manifest>: " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - continue; - } - } - - if (!foundApp && pkg.instrumentation.size() == 0) { - outError[0] = "<manifest> does not contain an <application> or <instrumentation>"; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; - } - - if (pkg.usesLibraries.size() > 0) { - pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()]; - pkg.usesLibraries.toArray(pkg.usesLibraryFiles); - } - - return pkg; - } - - private static String buildClassName(String pkg, CharSequence clsSeq, - String[] outError) { - if (clsSeq == null || clsSeq.length() <= 0) { - outError[0] = "Empty class name in package " + pkg; - return null; - } - String cls = clsSeq.toString(); - char c = cls.charAt(0); - if (c == '.') { - return (pkg + cls).intern(); - } - if (cls.indexOf('.') < 0) { - StringBuilder b = new StringBuilder(pkg); - b.append('.'); - b.append(cls); - return b.toString().intern(); - } - if (c >= 'a' && c <= 'z') { - return cls.intern(); - } - outError[0] = "Bad class name " + cls + " in package " + pkg; - return null; - } - - private static String buildCompoundName(String pkg, - CharSequence procSeq, String type, String[] outError) { - String proc = procSeq.toString(); - char c = proc.charAt(0); - if (pkg != null && c == ':') { - if (proc.length() < 2) { - outError[0] = "Bad " + type + " name " + proc + " in package " + pkg - + ": must be at least two characters"; - return null; - } - String subName = proc.substring(1); - String nameError = validateName(subName, false); - if (nameError != null) { - outError[0] = "Invalid " + type + " name " + proc + " in package " - + pkg + ": " + nameError; - return null; - } - return (pkg + proc).intern(); - } - String nameError = validateName(proc, true); - if (nameError != null && !"system".equals(proc)) { - outError[0] = "Invalid " + type + " name " + proc + " in package " - + pkg + ": " + nameError; - return null; - } - return proc.intern(); - } - - private static String buildProcessName(String pkg, String defProc, - CharSequence procSeq, int flags, String[] separateProcesses, - String[] outError) { - if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) { - return defProc != null ? defProc : pkg; - } - if (separateProcesses != null) { - for (int i=separateProcesses.length-1; i>=0; i--) { - String sp = separateProcesses[i]; - if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) { - return pkg; - } - } - } - if (procSeq == null || procSeq.length() <= 0) { - return defProc; - } - return buildCompoundName(pkg, procSeq, "package", outError); - } - - private static String buildTaskAffinityName(String pkg, String defProc, - CharSequence procSeq, String[] outError) { - if (procSeq == null) { - return defProc; - } - if (procSeq.length() <= 0) { - return null; - } - return buildCompoundName(pkg, procSeq, "taskAffinity", outError); - } - - private PermissionGroup parsePermissionGroup(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, String[] outError) - throws XmlPullParserException, IOException { - PermissionGroup perm = new PermissionGroup(owner); - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestPermissionGroup); - - if (!parsePackageItemInfo(owner, perm.info, outError, - "<permission-group>", sa, - com.android.internal.R.styleable.AndroidManifestPermissionGroup_name, - com.android.internal.R.styleable.AndroidManifestPermissionGroup_label, - com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon)) { - sa.recycle(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - perm.info.descriptionRes = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestPermissionGroup_description, - 0); - - sa.recycle(); - - if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm, - outError)) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - owner.permissionGroups.add(perm); - - return perm; - } - - private Permission parsePermission(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, String[] outError) - throws XmlPullParserException, IOException { - Permission perm = new Permission(owner); - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestPermission); - - if (!parsePackageItemInfo(owner, perm.info, outError, - "<permission>", sa, - com.android.internal.R.styleable.AndroidManifestPermission_name, - com.android.internal.R.styleable.AndroidManifestPermission_label, - com.android.internal.R.styleable.AndroidManifestPermission_icon)) { - sa.recycle(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - perm.info.group = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup); - if (perm.info.group != null) { - perm.info.group = perm.info.group.intern(); - } - - perm.info.descriptionRes = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestPermission_description, - 0); - - perm.info.protectionLevel = sa.getInt( - com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel, - PermissionInfo.PROTECTION_NORMAL); - - sa.recycle(); - - if (perm.info.protectionLevel == -1) { - outError[0] = "<permission> does not specify protectionLevel"; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - if (!parseAllMetaData(res, parser, attrs, "<permission>", perm, - outError)) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - owner.permissions.add(perm); - - return perm; - } - - private Permission parsePermissionTree(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, String[] outError) - throws XmlPullParserException, IOException { - Permission perm = new Permission(owner); - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestPermissionTree); - - if (!parsePackageItemInfo(owner, perm.info, outError, - "<permission-tree>", sa, - com.android.internal.R.styleable.AndroidManifestPermissionTree_name, - com.android.internal.R.styleable.AndroidManifestPermissionTree_label, - com.android.internal.R.styleable.AndroidManifestPermissionTree_icon)) { - sa.recycle(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - sa.recycle(); - - int index = perm.info.name.indexOf('.'); - if (index > 0) { - index = perm.info.name.indexOf('.', index+1); - } - if (index < 0) { - outError[0] = "<permission-tree> name has less than three segments: " - + perm.info.name; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - perm.info.descriptionRes = 0; - perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL; - perm.tree = true; - - if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm, - outError)) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - owner.permissions.add(perm); - - return perm; - } - - private Instrumentation parseInstrumentation(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, String[] outError) - throws XmlPullParserException, IOException { - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestInstrumentation); - - Instrumentation a = new Instrumentation(owner); - - if (!parsePackageItemInfo(owner, a.info, outError, "<instrumentation>", sa, - com.android.internal.R.styleable.AndroidManifestInstrumentation_name, - com.android.internal.R.styleable.AndroidManifestInstrumentation_label, - com.android.internal.R.styleable.AndroidManifestInstrumentation_icon)) { - sa.recycle(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - a.component = new ComponentName(owner.applicationInfo.packageName, - a.info.name); - - String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); - a.info.targetPackage = str != null ? str.intern() : null; - - a.info.handleProfiling = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling, - false); - - a.info.functionalTest = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest, - false); - - sa.recycle(); - - if (a.info.targetPackage == null) { - outError[0] = "<instrumentation> does not specify targetPackage"; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a, - outError)) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - } - - owner.instrumentation.add(a); - - return a; - } - - private boolean parseApplication(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) - throws XmlPullParserException, IOException { - final ApplicationInfo ai = owner.applicationInfo; - final String pkgName = owner.applicationInfo.packageName; - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestApplication); - - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_name); - if (name != null) { - ai.className = buildClassName(pkgName, name, outError); - if (ai.className == null) { - sa.recycle(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - } - - String manageSpaceActivity = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity); - if (manageSpaceActivity != null) { - ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, - outError); - } - - TypedValue v = sa.peekValue( - com.android.internal.R.styleable.AndroidManifestApplication_label); - if (v != null && (ai.labelRes=v.resourceId) == 0) { - ai.nonLocalizedLabel = v.coerceToString(); - } - - ai.icon = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); - ai.theme = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); - ai.descriptionRes = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestApplication_description, 0); - - if ((flags&PARSE_IS_SYSTEM) != 0) { - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestApplication_persistent, - false)) { - ai.flags |= ApplicationInfo.FLAG_PERSISTENT; - } - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestApplication_debuggable, - false)) { - ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestApplication_hasCode, - true)) { - ai.flags |= ApplicationInfo.FLAG_HAS_CODE; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting, - false)) { - ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData, - true)) { - ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; - } - - String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_permission); - ai.permission = (str != null && str.length() > 0) ? str.intern() : null; - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity); - ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, - str, outError); - - if (outError[0] == null) { - ai.processName = buildProcessName(ai.packageName, null, sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_process), - flags, mSeparateProcesses, outError); - - ai.enabled = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); - } - - sa.recycle(); - - if (outError[0] != null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - final int innerDepth = parser.getDepth(); - - int type; - while ((type=parser.next()) != parser.END_DOCUMENT - && (type != parser.END_TAG || parser.getDepth() > innerDepth)) { - if (type == parser.END_TAG || type == parser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("activity")) { - Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false); - if (a == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - owner.activities.add(a); - - } else if (tagName.equals("receiver")) { - Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true); - if (a == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - owner.receivers.add(a); - - } else if (tagName.equals("service")) { - Service s = parseService(owner, res, parser, attrs, flags, outError); - if (s == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - owner.services.add(s); - - } else if (tagName.equals("provider")) { - Provider p = parseProvider(owner, res, parser, attrs, flags, outError); - if (p == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - owner.providers.add(p); - - } else if (tagName.equals("activity-alias")) { - Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError, false); - if (a == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - owner.activities.add(a); - - } else if (parser.getName().equals("meta-data")) { - // note: application meta-data is stored off to the side, so it can - // remain null in the primary copy (we like to avoid extra copies because - // it can be large) - if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData, - outError)) == null) { - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - - } else if (tagName.equals("uses-library")) { - sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestUsesLibrary); - - String lname = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); - - sa.recycle(); - - if (lname != null && !owner.usesLibraries.contains(lname)) { - owner.usesLibraries.add(lname); - } - - XmlUtils.skipCurrentTag(parser); - - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "Unknown element under <application>: " + tagName); - XmlUtils.skipCurrentTag(parser); - continue; - } else { - outError[0] = "Bad element under <application>: " + tagName; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - } - } - - return true; - } - - private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, - String[] outError, String tag, TypedArray sa, - int nameRes, int labelRes, int iconRes) { - String name = sa.getNonResourceString(nameRes); - if (name == null) { - outError[0] = tag + " does not specify android:name"; - return false; - } - - outInfo.name - = buildClassName(owner.applicationInfo.packageName, name, outError); - if (outInfo.name == null) { - return false; - } - - int iconVal = sa.getResourceId(iconRes, 0); - if (iconVal != 0) { - outInfo.icon = iconVal; - outInfo.nonLocalizedLabel = null; - } - - TypedValue v = sa.peekValue(labelRes); - if (v != null && (outInfo.labelRes=v.resourceId) == 0) { - outInfo.nonLocalizedLabel = v.coerceToString(); - } - - outInfo.packageName = owner.packageName; - - return true; - } - - private boolean parseComponentInfo(Package owner, int flags, - ComponentInfo outInfo, String[] outError, String tag, TypedArray sa, - int nameRes, int labelRes, int iconRes, int processRes, - int enabledRes) { - if (!parsePackageItemInfo(owner, outInfo, outError, tag, sa, - nameRes, labelRes, iconRes)) { - return false; - } - - if (processRes != 0) { - outInfo.processName = buildProcessName(owner.applicationInfo.packageName, - owner.applicationInfo.processName, sa.getNonResourceString(processRes), - flags, mSeparateProcesses, outError); - } - outInfo.enabled = sa.getBoolean(enabledRes, true); - - return outError[0] == null; - } - - private Activity parseActivity(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, - boolean receiver) throws XmlPullParserException, IOException { - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestActivity); - - Activity a = new Activity(owner); - - if (!parseComponentInfo(owner, flags, a.info, outError, - receiver ? "<receiver>" : "<activity>", sa, - com.android.internal.R.styleable.AndroidManifestActivity_name, - com.android.internal.R.styleable.AndroidManifestActivity_label, - com.android.internal.R.styleable.AndroidManifestActivity_icon, - com.android.internal.R.styleable.AndroidManifestActivity_process, - com.android.internal.R.styleable.AndroidManifestActivity_enabled)) { - sa.recycle(); - return null; - } - - final boolean setExported = sa.hasValue( - com.android.internal.R.styleable.AndroidManifestActivity_exported); - if (setExported) { - a.info.exported = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_exported, false); - } - - a.component = new ComponentName(owner.applicationInfo.packageName, - a.info.name); - - a.info.theme = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestActivity_theme, 0); - - String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivity_permission); - if (str == null) { - a.info.permission = owner.applicationInfo.permission; - } else { - a.info.permission = str.length() > 0 ? str.toString().intern() : null; - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity); - a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName, - owner.applicationInfo.taskAffinity, str, outError); - - a.info.flags = 0; - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_multiprocess, - false)) { - a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch, - false)) { - a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch, - false)) { - a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_noHistory, - false)) { - a.info.flags |= ActivityInfo.FLAG_NO_HISTORY; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState, - false)) { - a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded, - false)) { - a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents, - false)) { - a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; - } - - if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting, - (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) { - a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING; - } - - if (!receiver) { - a.info.launchMode = sa.getInt( - com.android.internal.R.styleable.AndroidManifestActivity_launchMode, - ActivityInfo.LAUNCH_MULTIPLE); - a.info.screenOrientation = sa.getInt( - com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation, - ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - a.info.configChanges = sa.getInt( - com.android.internal.R.styleable.AndroidManifestActivity_configChanges, - 0); - a.info.softInputMode = sa.getInt( - com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode, - 0); - } else { - a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; - a.info.configChanges = 0; - } - - sa.recycle(); - - if (outError[0] != null) { - return null; - } - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - if (parser.getName().equals("intent-filter")) { - ActivityIntentInfo intent = new ActivityIntentInfo(a); - if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) { - return null; - } - if (intent.countActions() == 0) { - Log.w(TAG, "Intent filter for activity " + intent - + " defines no actions"); - } else { - a.intents.add(intent); - } - } else if (parser.getName().equals("meta-data")) { - if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData, - outError)) == null) { - return null; - } - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - if (receiver) { - Log.w(TAG, "Unknown element under <receiver>: " + parser.getName()); - } else { - Log.w(TAG, "Unknown element under <activity>: " + parser.getName()); - } - XmlUtils.skipCurrentTag(parser); - continue; - } - if (receiver) { - outError[0] = "Bad element under <receiver>: " + parser.getName(); - } else { - outError[0] = "Bad element under <activity>: " + parser.getName(); - } - return null; - } - } - - if (!setExported) { - a.info.exported = a.intents.size() > 0; - } - - return a; - } - - private Activity parseActivityAlias(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, - boolean receiver) throws XmlPullParserException, IOException { - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestActivityAlias); - - String targetActivity = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity); - if (targetActivity == null) { - outError[0] = "<activity-alias> does not specify android:targetActivity"; - sa.recycle(); - return null; - } - - targetActivity = buildClassName(owner.applicationInfo.packageName, - targetActivity, outError); - if (targetActivity == null) { - sa.recycle(); - return null; - } - - Activity a = new Activity(owner); - Activity target = null; - - final int NA = owner.activities.size(); - for (int i=0; i<NA; i++) { - Activity t = owner.activities.get(i); - if (targetActivity.equals(t.info.name)) { - target = t; - break; - } - } - - if (target == null) { - outError[0] = "<activity-alias> target activity " + targetActivity - + " not found in manifest"; - sa.recycle(); - return null; - } - - a.info.targetActivity = targetActivity; - - a.info.configChanges = target.info.configChanges; - a.info.flags = target.info.flags; - a.info.icon = target.info.icon; - a.info.labelRes = target.info.labelRes; - a.info.launchMode = target.info.launchMode; - a.info.nonLocalizedLabel = target.info.nonLocalizedLabel; - a.info.processName = target.info.processName; - a.info.screenOrientation = target.info.screenOrientation; - a.info.taskAffinity = target.info.taskAffinity; - a.info.theme = target.info.theme; - - if (!parseComponentInfo(owner, flags, a.info, outError, - receiver ? "<receiver>" : "<activity>", sa, - com.android.internal.R.styleable.AndroidManifestActivityAlias_name, - com.android.internal.R.styleable.AndroidManifestActivityAlias_label, - com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, - 0, - com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled)) { - sa.recycle(); - return null; - } - - final boolean setExported = sa.hasValue( - com.android.internal.R.styleable.AndroidManifestActivityAlias_exported); - if (setExported) { - a.info.exported = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false); - } - - a.component = new ComponentName(owner.applicationInfo.packageName, - a.info.name); - - String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivityAlias_permission); - if (str != null) { - a.info.permission = str.length() > 0 ? str.toString().intern() : null; - } - - sa.recycle(); - - if (outError[0] != null) { - return null; - } - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - if (parser.getName().equals("intent-filter")) { - ActivityIntentInfo intent = new ActivityIntentInfo(a); - if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) { - return null; - } - if (intent.countActions() == 0) { - Log.w(TAG, "Intent filter for activity alias " + intent - + " defines no actions"); - } else { - a.intents.add(intent); - } - } else if (parser.getName().equals("meta-data")) { - if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData, - outError)) == null) { - return null; - } - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()); - XmlUtils.skipCurrentTag(parser); - continue; - } - outError[0] = "Bad element under <activity-alias>: " + parser.getName(); - return null; - } - } - - if (!setExported) { - a.info.exported = a.intents.size() > 0; - } - - return a; - } - - private Provider parseProvider(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) - throws XmlPullParserException, IOException { - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestProvider); - - Provider p = new Provider(owner); - - if (!parseComponentInfo(owner, flags, p.info, outError, "<provider>", sa, - com.android.internal.R.styleable.AndroidManifestProvider_name, - com.android.internal.R.styleable.AndroidManifestProvider_label, - com.android.internal.R.styleable.AndroidManifestProvider_icon, - com.android.internal.R.styleable.AndroidManifestProvider_process, - com.android.internal.R.styleable.AndroidManifestProvider_enabled)) { - sa.recycle(); - return null; - } - - p.info.exported = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestProvider_exported, true); - - p.component = new ComponentName(owner.applicationInfo.packageName, - p.info.name); - - String cpname = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_authorities); - - p.info.isSyncable = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestProvider_syncable, - false); - - String permission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_permission); - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_readPermission); - if (str == null) { - str = permission; - } - if (str == null) { - p.info.readPermission = owner.applicationInfo.permission; - } else { - p.info.readPermission = - str.length() > 0 ? str.toString().intern() : null; - } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_writePermission); - if (str == null) { - str = permission; - } - if (str == null) { - p.info.writePermission = owner.applicationInfo.permission; - } else { - p.info.writePermission = - str.length() > 0 ? str.toString().intern() : null; - } - - p.info.grantUriPermissions = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions, - false); - - p.info.multiprocess = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestProvider_multiprocess, - false); - - p.info.initOrder = sa.getInt( - com.android.internal.R.styleable.AndroidManifestProvider_initOrder, - 0); - - sa.recycle(); - - if (cpname == null) { - outError[0] = "<provider> does not incude authorities attribute"; - return null; - } - p.info.authority = cpname.intern(); - - if (!parseProviderTags(res, parser, attrs, p, outError)) { - return null; - } - - return p; - } - - private boolean parseProviderTags(Resources res, - XmlPullParser parser, AttributeSet attrs, - Provider outInfo, String[] outError) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - if (parser.getName().equals("meta-data")) { - if ((outInfo.metaData=parseMetaData(res, parser, attrs, - outInfo.metaData, outError)) == null) { - return false; - } - } else if (parser.getName().equals("grant-uri-permission")) { - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestGrantUriPermission); - - PatternMatcher pa = null; - - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path); - if (str != null) { - pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix); - if (str != null) { - pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern); - if (str != null) { - pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); - } - - sa.recycle(); - - if (pa != null) { - if (outInfo.info.uriPermissionPatterns == null) { - outInfo.info.uriPermissionPatterns = new PatternMatcher[1]; - outInfo.info.uriPermissionPatterns[0] = pa; - } else { - final int N = outInfo.info.uriPermissionPatterns.length; - PatternMatcher[] newp = new PatternMatcher[N+1]; - System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N); - newp[N] = pa; - outInfo.info.uriPermissionPatterns = newp; - } - outInfo.info.grantUriPermissions = true; - } - XmlUtils.skipCurrentTag(parser); - - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "Unknown element under <provider>: " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - continue; - } - outError[0] = "Bad element under <provider>: " - + parser.getName(); - return false; - } - } - return true; - } - - private Service parseService(Package owner, Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) - throws XmlPullParserException, IOException { - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestService); - - Service s = new Service(owner); - - if (!parseComponentInfo(owner, flags, s.info, outError, "<service>", sa, - com.android.internal.R.styleable.AndroidManifestService_name, - com.android.internal.R.styleable.AndroidManifestService_label, - com.android.internal.R.styleable.AndroidManifestService_icon, - com.android.internal.R.styleable.AndroidManifestService_process, - com.android.internal.R.styleable.AndroidManifestService_enabled)) { - sa.recycle(); - return null; - } - - final boolean setExported = sa.hasValue( - com.android.internal.R.styleable.AndroidManifestService_exported); - if (setExported) { - s.info.exported = sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestService_exported, false); - } - - s.component = new ComponentName(owner.applicationInfo.packageName, - s.info.name); - - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestService_permission); - if (str == null) { - s.info.permission = owner.applicationInfo.permission; - } else { - s.info.permission = str.length() > 0 ? str.toString().intern() : null; - } - - sa.recycle(); - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - if (parser.getName().equals("intent-filter")) { - ServiceIntentInfo intent = new ServiceIntentInfo(s); - if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) { - return null; - } - - s.intents.add(intent); - } else if (parser.getName().equals("meta-data")) { - if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData, - outError)) == null) { - return null; - } - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "Unknown element under <service>: " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - continue; - } - outError[0] = "Bad element under <service>: " - + parser.getName(); - return null; - } - } - - if (!setExported) { - s.info.exported = s.intents.size() > 0; - } - - return s; - } - - private boolean parseAllMetaData(Resources res, - XmlPullParser parser, AttributeSet attrs, String tag, - Component outInfo, String[] outError) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - if (parser.getName().equals("meta-data")) { - if ((outInfo.metaData=parseMetaData(res, parser, attrs, - outInfo.metaData, outError)) == null) { - return false; - } - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "Unknown element under " + tag + ": " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - continue; - } - outError[0] = "Bad element under " + tag + ": " - + parser.getName(); - return false; - } - } - return true; - } - - private Bundle parseMetaData(Resources res, - XmlPullParser parser, AttributeSet attrs, - Bundle data, String[] outError) - throws XmlPullParserException, IOException { - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestMetaData); - - if (data == null) { - data = new Bundle(); - } - - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestMetaData_name); - if (name == null) { - outError[0] = "<meta-data> requires an android:name attribute"; - sa.recycle(); - return null; - } - - boolean success = true; - - TypedValue v = sa.peekValue( - com.android.internal.R.styleable.AndroidManifestMetaData_resource); - if (v != null && v.resourceId != 0) { - //Log.i(TAG, "Meta data ref " + name + ": " + v); - data.putInt(name, v.resourceId); - } else { - v = sa.peekValue( - com.android.internal.R.styleable.AndroidManifestMetaData_value); - //Log.i(TAG, "Meta data " + name + ": " + v); - if (v != null) { - if (v.type == TypedValue.TYPE_STRING) { - CharSequence cs = v.coerceToString(); - data.putString(name, cs != null ? cs.toString() : null); - } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { - data.putBoolean(name, v.data != 0); - } else if (v.type >= TypedValue.TYPE_FIRST_INT - && v.type <= TypedValue.TYPE_LAST_INT) { - data.putInt(name, v.data); - } else if (v.type == TypedValue.TYPE_FLOAT) { - data.putFloat(name, v.getFloat()); - } else { - if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types"); - } else { - outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types"; - data = null; - } - } - } else { - outError[0] = "<meta-data> requires an android:value or android:resource attribute"; - data = null; - } - } - - sa.recycle(); - - XmlUtils.skipCurrentTag(parser); - - return data; - } - - private static final String ANDROID_RESOURCES - = "http://schemas.android.com/apk/res/android"; - - private boolean parseIntent(Resources res, - XmlPullParser parser, AttributeSet attrs, int flags, - IntentInfo outInfo, String[] outError, boolean isActivity) - throws XmlPullParserException, IOException { - - TypedArray sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestIntentFilter); - - int priority = sa.getInt( - com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0); - if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) { - Log.w(TAG, "Activity with priority > 0, forcing to 0 at " - + parser.getPositionDescription()); - priority = 0; - } - outInfo.setPriority(priority); - - TypedValue v = sa.peekValue( - com.android.internal.R.styleable.AndroidManifestIntentFilter_label); - if (v != null && (outInfo.labelRes=v.resourceId) == 0) { - outInfo.nonLocalizedLabel = v.coerceToString(); - } - - outInfo.icon = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); - - sa.recycle(); - - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != parser.END_DOCUMENT - && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == parser.END_TAG || type == parser.TEXT) { - continue; - } - - String nodeName = parser.getName(); - if (nodeName.equals("action")) { - String value = attrs.getAttributeValue( - ANDROID_RESOURCES, "name"); - if (value == null || value == "") { - outError[0] = "No value supplied for <android:name>"; - return false; - } - XmlUtils.skipCurrentTag(parser); - - outInfo.addAction(value); - } else if (nodeName.equals("category")) { - String value = attrs.getAttributeValue( - ANDROID_RESOURCES, "name"); - if (value == null || value == "") { - outError[0] = "No value supplied for <android:name>"; - return false; - } - XmlUtils.skipCurrentTag(parser); - - outInfo.addCategory(value); - - } else if (nodeName.equals("data")) { - sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestData); - - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_mimeType); - if (str != null) { - try { - outInfo.addDataType(str); - } catch (IntentFilter.MalformedMimeTypeException e) { - outError[0] = e.toString(); - sa.recycle(); - return false; - } - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_scheme); - if (str != null) { - outInfo.addDataScheme(str); - } - - String host = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_host); - String port = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_port); - if (host != null) { - outInfo.addDataAuthority(host, port); - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_path); - if (str != null) { - outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_pathPrefix); - if (str != null) { - outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); - } - - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_pathPattern); - if (str != null) { - outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); - } - - sa.recycle(); - XmlUtils.skipCurrentTag(parser); - } else if (!RIGID_PARSER) { - Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); - Log.w(TAG, "Unknown element under <intent-filter>: " + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } else { - outError[0] = "Bad element under <intent-filter>: " + parser.getName(); - return false; - } - } - - outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT); - if (false) { - String cats = ""; - Iterator<String> it = outInfo.categoriesIterator(); - while (it != null && it.hasNext()) { - cats += " " + it.next(); - } - System.out.println("Intent d=" + - outInfo.hasDefault + ", cat=" + cats); - } - - return true; - } - - public final static class Package { - public final String packageName; - - // For now we only support one application per package. - public final ApplicationInfo applicationInfo = new ApplicationInfo(); - - public final ArrayList<Permission> permissions = new ArrayList<Permission>(0); - public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0); - public final ArrayList<Activity> activities = new ArrayList<Activity>(0); - public final ArrayList<Activity> receivers = new ArrayList<Activity>(0); - public final ArrayList<Provider> providers = new ArrayList<Provider>(0); - public final ArrayList<Service> services = new ArrayList<Service>(0); - public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0); - - public final ArrayList<String> requestedPermissions = new ArrayList<String>(); - - public final ArrayList<String> usesLibraries = new ArrayList<String>(); - public String[] usesLibraryFiles = null; - - // We store the application meta-data independently to avoid multiple unwanted references - public Bundle mAppMetaData = null; - - // If this is a 3rd party app, this is the path of the zip file. - public String mPath; - - // True if this package is part of the system image. - public boolean mSystem; - - // The version code declared for this package. - public int mVersionCode; - - // The version name declared for this package. - public String mVersionName; - - // The shared user id that this package wants to use. - public String mSharedUserId; - - // The shared user label that this package wants to use. - public int mSharedUserLabel; - - // Signatures that were read from the package. - public Signature mSignatures[]; - - // For use by package manager service for quick lookup of - // preferred up order. - public int mPreferredOrder = 0; - - // Additional data supplied by callers. - public Object mExtras; - - /* - * Applications hardware preferences - */ - public final ArrayList<ConfigurationInfo> configPreferences = - new ArrayList<ConfigurationInfo>(); - - public Package(String _name) { - packageName = _name; - applicationInfo.packageName = _name; - applicationInfo.uid = -1; - } - - public String toString() { - return "Package{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName + "}"; - } - } - - public static class Component<II extends IntentInfo> { - public final Package owner; - public final ArrayList<II> intents = new ArrayList<II>(0); - public ComponentName component; - public Bundle metaData; - - public Component(Package _owner) { - owner = _owner; - } - - public Component(Component<II> clone) { - owner = clone.owner; - metaData = clone.metaData; - } - } - - public final static class Permission extends Component<IntentInfo> { - public final PermissionInfo info; - public boolean tree; - public PermissionGroup group; - - public Permission(Package _owner) { - super(_owner); - info = new PermissionInfo(); - } - - public Permission(Package _owner, PermissionInfo _info) { - super(_owner); - info = _info; - } - - public String toString() { - return "Permission{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + info.name + "}"; - } - } - - public final static class PermissionGroup extends Component<IntentInfo> { - public final PermissionGroupInfo info; - - public PermissionGroup(Package _owner) { - super(_owner); - info = new PermissionGroupInfo(); - } - - public PermissionGroup(Package _owner, PermissionGroupInfo _info) { - super(_owner); - info = _info; - } - - public String toString() { - return "PermissionGroup{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + info.name + "}"; - } - } - - private static boolean copyNeeded(int flags, Package p, Bundle metaData) { - if ((flags & PackageManager.GET_META_DATA) != 0 - && (metaData != null || p.mAppMetaData != null)) { - return true; - } - if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0 - && p.usesLibraryFiles != null) { - return true; - } - return false; - } - - public static ApplicationInfo generateApplicationInfo(Package p, int flags) { - if (p == null) return null; - if (!copyNeeded(flags, p, null)) { - return p.applicationInfo; - } - - // Make shallow copy so we can store the metadata/libraries safely - ApplicationInfo ai = new ApplicationInfo(p.applicationInfo); - if ((flags & PackageManager.GET_META_DATA) != 0) { - ai.metaData = p.mAppMetaData; - } - if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) { - ai.sharedLibraryFiles = p.usesLibraryFiles; - } - return ai; - } - - public static final PermissionInfo generatePermissionInfo( - Permission p, int flags) { - if (p == null) return null; - if ((flags&PackageManager.GET_META_DATA) == 0) { - return p.info; - } - PermissionInfo pi = new PermissionInfo(p.info); - pi.metaData = p.metaData; - return pi; - } - - public static final PermissionGroupInfo generatePermissionGroupInfo( - PermissionGroup pg, int flags) { - if (pg == null) return null; - if ((flags&PackageManager.GET_META_DATA) == 0) { - return pg.info; - } - PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info); - pgi.metaData = pg.metaData; - return pgi; - } - - public final static class Activity extends Component<ActivityIntentInfo> { - public final ActivityInfo info = - new ActivityInfo(); - - public Activity(Package _owner) { - super(_owner); - info.applicationInfo = owner.applicationInfo; - } - - public String toString() { - return "Activity{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + component.flattenToString() + "}"; - } - } - - public static final ActivityInfo generateActivityInfo(Activity a, - int flags) { - if (a == null) return null; - if (!copyNeeded(flags, a.owner, a.metaData)) { - return a.info; - } - // Make shallow copies so we can store the metadata safely - ActivityInfo ai = new ActivityInfo(a.info); - ai.metaData = a.metaData; - ai.applicationInfo = generateApplicationInfo(a.owner, flags); - return ai; - } - - public final static class Service extends Component<ServiceIntentInfo> { - public final ServiceInfo info = - new ServiceInfo(); - - public Service(Package _owner) { - super(_owner); - info.applicationInfo = owner.applicationInfo; - } - - public String toString() { - return "Service{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + component.flattenToString() + "}"; - } - } - - public static final ServiceInfo generateServiceInfo(Service s, int flags) { - if (s == null) return null; - if (!copyNeeded(flags, s.owner, s.metaData)) { - return s.info; - } - // Make shallow copies so we can store the metadata safely - ServiceInfo si = new ServiceInfo(s.info); - si.metaData = s.metaData; - si.applicationInfo = generateApplicationInfo(s.owner, flags); - return si; - } - - public final static class Provider extends Component { - public final ProviderInfo info; - public boolean syncable; - - public Provider(Package _owner) { - super(_owner); - info = new ProviderInfo(); - info.applicationInfo = owner.applicationInfo; - syncable = false; - } - - public Provider(Provider existingProvider) { - super(existingProvider); - this.info = existingProvider.info; - this.syncable = existingProvider.syncable; - } - - public String toString() { - return "Provider{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + info.name + "}"; - } - } - - public static final ProviderInfo generateProviderInfo(Provider p, - int flags) { - if (p == null) return null; - if (!copyNeeded(flags, p.owner, p.metaData) - && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0 - || p.info.uriPermissionPatterns == null)) { - return p.info; - } - // Make shallow copies so we can store the metadata safely - ProviderInfo pi = new ProviderInfo(p.info); - pi.metaData = p.metaData; - if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) { - pi.uriPermissionPatterns = null; - } - pi.applicationInfo = generateApplicationInfo(p.owner, flags); - return pi; - } - - public final static class Instrumentation extends Component { - public final InstrumentationInfo info = - new InstrumentationInfo(); - - public Instrumentation(Package _owner) { - super(_owner); - } - - public String toString() { - return "Instrumentation{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + component.flattenToString() + "}"; - } - } - - public static final InstrumentationInfo generateInstrumentationInfo( - Instrumentation i, int flags) { - if (i == null) return null; - if ((flags&PackageManager.GET_META_DATA) == 0) { - return i.info; - } - InstrumentationInfo ii = new InstrumentationInfo(i.info); - ii.metaData = i.metaData; - return ii; - } - - public static class IntentInfo extends IntentFilter { - public boolean hasDefault; - public int labelRes; - public CharSequence nonLocalizedLabel; - public int icon; - } - - public final static class ActivityIntentInfo extends IntentInfo { - public final Activity activity; - - public ActivityIntentInfo(Activity _activity) { - activity = _activity; - } - - public String toString() { - return "ActivityIntentInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + activity.info.name + "}"; - } - } - - public final static class ServiceIntentInfo extends IntentInfo { - public final Service service; - - public ServiceIntentInfo(Service _service) { - service = _service; - } - - public String toString() { - return "ServiceIntentInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + service.info.name + "}"; - } - } -} diff --git a/core/java/android/content/pm/PackageStats.aidl b/core/java/android/content/pm/PackageStats.aidl deleted file mode 100755 index 8c9786f..0000000 --- a/core/java/android/content/pm/PackageStats.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable PackageStats; diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java deleted file mode 100755 index 66c6efd..0000000 --- a/core/java/android/content/pm/PackageStats.java +++ /dev/null @@ -1,63 +0,0 @@ -package android.content.pm; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Arrays; - -/** - * implementation of PackageStats associated with a - * application package. - */ -public class PackageStats implements Parcelable { - public String packageName; - public long codeSize; - public long dataSize; - public long cacheSize; - - public static final Parcelable.Creator<PackageStats> CREATOR - = new Parcelable.Creator<PackageStats>() { - public PackageStats createFromParcel(Parcel in) { - return new PackageStats(in); - } - - public PackageStats[] newArray(int size) { - return new PackageStats[size]; - } - }; - - public String toString() { - return "PackageStats{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName + "}"; - } - - public PackageStats(String pkgName) { - packageName = pkgName; - } - - public PackageStats(Parcel source) { - packageName = source.readString(); - codeSize = source.readLong(); - dataSize = source.readLong(); - cacheSize = source.readLong(); - } - - public PackageStats(PackageStats pStats) { - packageName = pStats.packageName; - codeSize = pStats.codeSize; - dataSize = pStats.dataSize; - cacheSize = pStats.cacheSize; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags){ - dest.writeString(packageName); - dest.writeLong(codeSize); - dest.writeLong(dataSize); - dest.writeLong(cacheSize); - } -} diff --git a/core/java/android/content/pm/PermissionGroupInfo.aidl b/core/java/android/content/pm/PermissionGroupInfo.aidl deleted file mode 100755 index 9f215f1..0000000 --- a/core/java/android/content/pm/PermissionGroupInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 2008, 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.pm; - -parcelable PermissionGroupInfo; diff --git a/core/java/android/content/pm/PermissionGroupInfo.java b/core/java/android/content/pm/PermissionGroupInfo.java deleted file mode 100644 index 02eb816..0000000 --- a/core/java/android/content/pm/PermissionGroupInfo.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008 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.pm; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -/** - * Information you can retrieve about a particular security permission - * group known to the system. This corresponds to information collected from the - * AndroidManifest.xml's <permission-group> tags. - */ -public class PermissionGroupInfo extends PackageItemInfo implements Parcelable { - /** - * A string resource identifier (in the package's resources) of this - * permission's description. From the "description" attribute or, - * if not set, 0. - */ - public int descriptionRes; - - /** - * The description string provided in the AndroidManifest file, if any. You - * probably don't want to use this, since it will be null if the description - * is in a resource. You probably want - * {@link PermissionInfo#loadDescription} instead. - */ - public CharSequence nonLocalizedDescription; - - public PermissionGroupInfo() { - } - - public PermissionGroupInfo(PermissionGroupInfo orig) { - super(orig); - descriptionRes = orig.descriptionRes; - nonLocalizedDescription = orig.nonLocalizedDescription; - } - - /** - * Retrieve the textual description of this permission. This - * will call back on the given PackageManager to load the description from - * the application. - * - * @param pm A PackageManager from which the label can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a CharSequence containing the permission's description. - * If there is no description, null is returned. - */ - public CharSequence loadDescription(PackageManager pm) { - if (nonLocalizedDescription != null) { - return nonLocalizedDescription; - } - if (descriptionRes != 0) { - CharSequence label = pm.getText(packageName, descriptionRes, null); - if (label != null) { - return label; - } - } - return null; - } - - public String toString() { - return "PermissionGroupInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - dest.writeInt(descriptionRes); - TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); - } - - public static final Creator<PermissionGroupInfo> CREATOR = - new Creator<PermissionGroupInfo>() { - public PermissionGroupInfo createFromParcel(Parcel source) { - return new PermissionGroupInfo(source); - } - public PermissionGroupInfo[] newArray(int size) { - return new PermissionGroupInfo[size]; - } - }; - - private PermissionGroupInfo(Parcel source) { - super(source); - descriptionRes = source.readInt(); - nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - } -} diff --git a/core/java/android/content/pm/PermissionInfo.aidl b/core/java/android/content/pm/PermissionInfo.aidl deleted file mode 100755 index 5a7d4f4..0000000 --- a/core/java/android/content/pm/PermissionInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable PermissionInfo; diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java deleted file mode 100644 index 3cc884b..0000000 --- a/core/java/android/content/pm/PermissionInfo.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2008 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.pm; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -/** - * Information you can retrieve about a particular security permission - * known to the system. This corresponds to information collected from the - * AndroidManifest.xml's <permission> tags. - */ -public class PermissionInfo extends PackageItemInfo implements Parcelable { - /** - * A normal application value for {@link #protectionLevel}, corresponding - * to the <code>normal</code> value of - * {@link android.R.attr#protectionLevel}. - */ - public static final int PROTECTION_NORMAL = 0; - - /** - * Dangerous value for {@link #protectionLevel}, corresponding - * to the <code>dangerous</code> value of - * {@link android.R.attr#protectionLevel}. - */ - public static final int PROTECTION_DANGEROUS = 1; - - /** - * System-level value for {@link #protectionLevel}, corresponding - * to the <code>signature</code> value of - * {@link android.R.attr#protectionLevel}. - */ - public static final int PROTECTION_SIGNATURE = 2; - - /** - * System-level value for {@link #protectionLevel}, corresponding - * to the <code>signatureOrSystem</code> value of - * {@link android.R.attr#protectionLevel}. - */ - public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; - - /** - * The group this permission is a part of, as per - * {@link android.R.attr#permissionGroup}. - */ - public String group; - - /** - * A string resource identifier (in the package's resources) of this - * permission's description. From the "description" attribute or, - * if not set, 0. - */ - public int descriptionRes; - - /** - * The description string provided in the AndroidManifest file, if any. You - * probably don't want to use this, since it will be null if the description - * is in a resource. You probably want - * {@link PermissionInfo#loadDescription} instead. - */ - public CharSequence nonLocalizedDescription; - - /** - * The level of access this permission is protecting, as per - * {@link android.R.attr#protectionLevel}. Values may be - * {@link #PROTECTION_NORMAL}, {@link #PROTECTION_DANGEROUS}, or - * {@link #PROTECTION_SIGNATURE}. - */ - public int protectionLevel; - - public PermissionInfo() { - } - - public PermissionInfo(PermissionInfo orig) { - super(orig); - group = orig.group; - descriptionRes = orig.descriptionRes; - protectionLevel = orig.protectionLevel; - nonLocalizedDescription = orig.nonLocalizedDescription; - } - - /** - * Retrieve the textual description of this permission. This - * will call back on the given PackageManager to load the description from - * the application. - * - * @param pm A PackageManager from which the label can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a CharSequence containing the permission's description. - * If there is no description, null is returned. - */ - public CharSequence loadDescription(PackageManager pm) { - if (nonLocalizedDescription != null) { - return nonLocalizedDescription; - } - if (descriptionRes != 0) { - CharSequence label = pm.getText(packageName, descriptionRes, null); - if (label != null) { - return label; - } - } - return null; - } - - public String toString() { - return "PermissionInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - dest.writeString(group); - dest.writeInt(descriptionRes); - dest.writeInt(protectionLevel); - TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); - } - - public static final Creator<PermissionInfo> CREATOR = - new Creator<PermissionInfo>() { - public PermissionInfo createFromParcel(Parcel source) { - return new PermissionInfo(source); - } - public PermissionInfo[] newArray(int size) { - return new PermissionInfo[size]; - } - }; - - private PermissionInfo(Parcel source) { - super(source); - group = source.readString(); - descriptionRes = source.readInt(); - protectionLevel = source.readInt(); - nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - } -} diff --git a/core/java/android/content/pm/ProviderInfo.aidl b/core/java/android/content/pm/ProviderInfo.aidl deleted file mode 100755 index 18fbc8a..0000000 --- a/core/java/android/content/pm/ProviderInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable ProviderInfo; diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java deleted file mode 100644 index b67ddf6..0000000 --- a/core/java/android/content/pm/ProviderInfo.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2006 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.pm; - -import android.os.Parcel; -import android.os.Parcelable; -import android.os.PatternMatcher; - -/** - * Holds information about a specific - * {@link android.content.ContentProvider content provider}. This is returned by - * {@link android.content.pm.PackageManager#resolveContentProvider(java.lang.String, int) - * PackageManager.resolveContentProvider()}. - */ -public final class ProviderInfo extends ComponentInfo - implements Parcelable { - /** The name provider is published under content:// */ - public String authority = null; - - /** Optional permission required for read-only access this content - * provider. */ - public String readPermission = null; - - /** Optional permission required for read/write access this content - * provider. */ - public String writePermission = null; - - /** If true, additional permissions to specific Uris in this content - * provider can be granted, as per the - * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions - * grantUriPermissions} attribute. - */ - public boolean grantUriPermissions = false; - - /** - * If non-null, these are the patterns that are allowed for granting URI - * permissions. Any URI that does not match one of these patterns will not - * allowed to be granted. If null, all URIs are allowed. The - * {@link PackageManager#GET_URI_PERMISSION_PATTERNS - * PackageManager.GET_URI_PERMISSION_PATTERNS} flag must be specified for - * this field to be filled in. - */ - public PatternMatcher[] uriPermissionPatterns = null; - - /** If true, this content provider allows multiple instances of itself - * to run in different process. If false, a single instances is always - * run in {@link #processName}. */ - public boolean multiprocess = false; - - /** Used to control initialization order of single-process providers - * running in the same process. Higher goes first. */ - public int initOrder = 0; - - /** Whether or not this provider is syncable. */ - public boolean isSyncable = false; - - public ProviderInfo() { - } - - public ProviderInfo(ProviderInfo orig) { - super(orig); - authority = orig.authority; - readPermission = orig.readPermission; - writePermission = orig.writePermission; - grantUriPermissions = orig.grantUriPermissions; - uriPermissionPatterns = orig.uriPermissionPatterns; - multiprocess = orig.multiprocess; - initOrder = orig.initOrder; - isSyncable = orig.isSyncable; - } - - public int describeContents() { - return 0; - } - - @Override public void writeToParcel(Parcel out, int parcelableFlags) { - super.writeToParcel(out, parcelableFlags); - out.writeString(authority); - out.writeString(readPermission); - out.writeString(writePermission); - out.writeInt(grantUriPermissions ? 1 : 0); - out.writeTypedArray(uriPermissionPatterns, parcelableFlags); - out.writeInt(multiprocess ? 1 : 0); - out.writeInt(initOrder); - out.writeInt(isSyncable ? 1 : 0); - } - - public static final Parcelable.Creator<ProviderInfo> CREATOR - = new Parcelable.Creator<ProviderInfo>() { - public ProviderInfo createFromParcel(Parcel in) { - return new ProviderInfo(in); - } - - public ProviderInfo[] newArray(int size) { - return new ProviderInfo[size]; - } - }; - - public String toString() { - return "ContentProviderInfo{name=" + authority + " className=" + name - + " isSyncable=" + (isSyncable ? "true" : "false") + "}"; - } - - private ProviderInfo(Parcel in) { - super(in); - authority = in.readString(); - readPermission = in.readString(); - writePermission = in.readString(); - grantUriPermissions = in.readInt() != 0; - uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR); - multiprocess = in.readInt() != 0; - initOrder = in.readInt(); - isSyncable = in.readInt() != 0; - } -} diff --git a/core/java/android/content/pm/ResolveInfo.aidl b/core/java/android/content/pm/ResolveInfo.aidl deleted file mode 100755 index b4e7f8b..0000000 --- a/core/java/android/content/pm/ResolveInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable ResolveInfo; diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java deleted file mode 100644 index ee49c02..0000000 --- a/core/java/android/content/pm/ResolveInfo.java +++ /dev/null @@ -1,280 +0,0 @@ -package android.content.pm; - -import android.content.IntentFilter; -import android.graphics.drawable.Drawable; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Printer; - -import java.text.Collator; -import java.util.Comparator; - -/** - * Information that is returned from resolving an intent - * against an IntentFilter. This partially corresponds to - * information collected from the AndroidManifest.xml's - * <intent> tags. - */ -public class ResolveInfo implements Parcelable { - /** - * The activity that corresponds to this resolution match, if this - * resolution is for an activity. One and only one of this and - * serviceInfo must be non-null. - */ - public ActivityInfo activityInfo; - - /** - * The service that corresponds to this resolution match, if this - * resolution is for a service. One and only one of this and - * activityInfo must be non-null. - */ - public ServiceInfo serviceInfo; - - /** - * The IntentFilter that was matched for this ResolveInfo. - */ - public IntentFilter filter; - - /** - * The declared priority of this match. Comes from the "priority" - * attribute or, if not set, defaults to 0. Higher values are a higher - * priority. - */ - public int priority; - - /** - * Order of result according to the user's preference. If the user - * has not set a preference for this result, the value is 0; higher - * values are a higher priority. - */ - public int preferredOrder; - - /** - * The system's evaluation of how well the activity matches the - * IntentFilter. This is a match constant, a combination of - * {@link IntentFilter#MATCH_CATEGORY_MASK IntentFilter.MATCH_CATEGORY_MASK} - * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}. - */ - public int match; - - /** - * Only set when returned by - * {@link PackageManager#queryIntentActivityOptions}, this tells you - * which of the given specific intents this result came from. 0 is the - * first in the list, < 0 means it came from the generic Intent query. - */ - public int specificIndex = -1; - - /** - * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it - * would like to be considered a default action that the user can - * perform on this data. - */ - public boolean isDefault; - - /** - * A string resource identifier (in the package's resources) of this - * match's label. From the "label" attribute or, if not set, 0. - */ - public int labelRes; - - /** - * The actual string retrieve from <var>labelRes</var> or null if none - * was provided. - */ - public CharSequence nonLocalizedLabel; - - /** - * A drawable resource identifier (in the package's resources) of this - * match's icon. From the "icon" attribute or, if not set, 0. - */ - public int icon; - - /** - * Retrieve the current textual label associated with this resolution. This - * will call back on the given PackageManager to load the label from - * the application. - * - * @param pm A PackageManager from which the label can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a CharSequence containing the resolutions's label. If the - * item does not have a label, its name is returned. - */ - public CharSequence loadLabel(PackageManager pm) { - if (nonLocalizedLabel != null) { - return nonLocalizedLabel; - } - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; - ApplicationInfo ai = ci.applicationInfo; - CharSequence label; - if (labelRes != 0) { - label = pm.getText(ci.packageName, labelRes, ai); - if (label != null) { - return label; - } - } - return ci.loadLabel(pm); - } - - /** - * Retrieve the current graphical icon associated with this resolution. This - * will call back on the given PackageManager to load the icon from - * the application. - * - * @param pm A PackageManager from which the icon can be loaded; usually - * the PackageManager from which you originally retrieved this item. - * - * @return Returns a Drawable containing the resolution's icon. If the - * item does not have an icon, the default activity icon is returned. - */ - public Drawable loadIcon(PackageManager pm) { - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; - ApplicationInfo ai = ci.applicationInfo; - Drawable dr; - if (icon != 0) { - dr = pm.getDrawable(ci.packageName, icon, ai); - if (dr != null) { - return dr; - } - } - return ci.loadIcon(pm); - } - - /** - * Return the icon resource identifier to use for this match. If the - * match defines an icon, that is used; else if the activity defines - * an icon, that is used; else, the application icon is used. - * - * @return The icon associated with this match. - */ - public final int getIconResource() { - if (icon != 0) return icon; - if (activityInfo != null) return activityInfo.getIconResource(); - if (serviceInfo != null) return serviceInfo.getIconResource(); - return 0; - } - - public void dump(Printer pw, String prefix) { - if (filter != null) { - pw.println(prefix + "Filter:"); - filter.dump(pw, prefix + " "); - } else { - pw.println(prefix + "Filter: null"); - } - pw.println(prefix + "priority=" + priority - + " preferredOrder=" + preferredOrder - + " match=0x" + Integer.toHexString(match) - + " specificIndex=" + specificIndex - + " isDefault=" + isDefault); - pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) - + " nonLocalizedLabel=" + nonLocalizedLabel - + " icon=0x" + Integer.toHexString(icon)); - if (activityInfo != null) { - pw.println(prefix + "ActivityInfo:"); - activityInfo.dump(pw, prefix + " "); - } else if (serviceInfo != null) { - pw.println(prefix + "ServiceInfo:"); - // TODO - //serviceInfo.dump(pw, prefix + " "); - } - } - - public ResolveInfo() { - } - - public String toString() { - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; - return "ResolveInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + ci.name + " p=" + priority + " o=" - + preferredOrder + " m=0x" + Integer.toHexString(match) + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - if (activityInfo != null) { - dest.writeInt(1); - activityInfo.writeToParcel(dest, parcelableFlags); - } else if (serviceInfo != null) { - dest.writeInt(2); - serviceInfo.writeToParcel(dest, parcelableFlags); - } else { - dest.writeInt(0); - } - if (filter != null) { - dest.writeInt(1); - filter.writeToParcel(dest, parcelableFlags); - } else { - dest.writeInt(0); - } - dest.writeInt(priority); - dest.writeInt(preferredOrder); - dest.writeInt(match); - dest.writeInt(specificIndex); - dest.writeInt(labelRes); - TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); - dest.writeInt(icon); - } - - public static final Creator<ResolveInfo> CREATOR - = new Creator<ResolveInfo>() { - public ResolveInfo createFromParcel(Parcel source) { - return new ResolveInfo(source); - } - public ResolveInfo[] newArray(int size) { - return new ResolveInfo[size]; - } - }; - - private ResolveInfo(Parcel source) { - switch (source.readInt()) { - case 1: - activityInfo = ActivityInfo.CREATOR.createFromParcel(source); - serviceInfo = null; - break; - case 2: - serviceInfo = ServiceInfo.CREATOR.createFromParcel(source); - activityInfo = null; - break; - default: - activityInfo = null; - serviceInfo = null; - break; - } - if (source.readInt() != 0) { - filter = IntentFilter.CREATOR.createFromParcel(source); - } - priority = source.readInt(); - preferredOrder = source.readInt(); - match = source.readInt(); - specificIndex = source.readInt(); - labelRes = source.readInt(); - nonLocalizedLabel - = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - icon = source.readInt(); - } - - public static class DisplayNameComparator - implements Comparator<ResolveInfo> { - public DisplayNameComparator(PackageManager pm) { - mPM = pm; - } - - public final int compare(ResolveInfo a, ResolveInfo b) { - CharSequence sa = a.loadLabel(mPM); - if (sa == null) sa = a.activityInfo.name; - CharSequence sb = b.loadLabel(mPM); - if (sb == null) sb = b.activityInfo.name; - - return sCollator.compare(sa.toString(), sb.toString()); - } - - private final Collator sCollator = Collator.getInstance(); - private PackageManager mPM; - } -} diff --git a/core/java/android/content/pm/ServiceInfo.aidl b/core/java/android/content/pm/ServiceInfo.aidl deleted file mode 100755 index 5ddae1a..0000000 --- a/core/java/android/content/pm/ServiceInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable ServiceInfo; diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java deleted file mode 100644 index b60650c..0000000 --- a/core/java/android/content/pm/ServiceInfo.java +++ /dev/null @@ -1,56 +0,0 @@ -package android.content.pm; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Information you can retrieve about a particular application - * service. This corresponds to information collected from the - * AndroidManifest.xml's <service> tags. - */ -public class ServiceInfo extends ComponentInfo - implements Parcelable { - /** - * Optional name of a permission required to be able to access this - * Service. From the "permission" attribute. - */ - public String permission; - - public ServiceInfo() { - } - - public ServiceInfo(ServiceInfo orig) { - super(orig); - permission = orig.permission; - } - - public String toString() { - return "ServiceInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + name + "}"; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - super.writeToParcel(dest, parcelableFlags); - dest.writeString(permission); - } - - public static final Creator<ServiceInfo> CREATOR = - new Creator<ServiceInfo>() { - public ServiceInfo createFromParcel(Parcel source) { - return new ServiceInfo(source); - } - public ServiceInfo[] newArray(int size) { - return new ServiceInfo[size]; - } - }; - - private ServiceInfo(Parcel source) { - super(source); - permission = source.readString(); - } -} diff --git a/core/java/android/content/pm/Signature.aidl b/core/java/android/content/pm/Signature.aidl deleted file mode 100755 index 3a0d775..0000000 --- a/core/java/android/content/pm/Signature.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.pm; - -parcelable Signature; diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java deleted file mode 100644 index 1bb3857..0000000 --- a/core/java/android/content/pm/Signature.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2008 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.pm; - -import android.content.ComponentName; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Arrays; - -/** - * Opaque, immutable representation of a signature associated with an - * application package. - */ -public class Signature implements Parcelable { - private final byte[] mSignature; - private int mHashCode; - private boolean mHaveHashCode; - private String mString; - - /** - * Create Signature from an existing raw byte array. - */ - public Signature(byte[] signature) { - mSignature = signature.clone(); - } - - /** - * Create Signature from a text representation previously returned by - * {@link #toChars} or {@link #toCharsString()}. - */ - public Signature(String text) { - final int N = text.length()/2; - byte[] sig = new byte[N]; - for (int i=0; i<N; i++) { - char c = text.charAt(i*2); - byte b = (byte)( - (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4); - c = text.charAt(i*2 + 1); - b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0')); - sig[i] = b; - } - mSignature = sig; - } - - /** - * Encode the Signature as ASCII text. - */ - public char[] toChars() { - return toChars(null, null); - } - - /** - * Encode the Signature as ASCII text in to an existing array. - * - * @param existingArray Existing char array or null. - * @param outLen Output parameter for the number of characters written in - * to the array. - * @return Returns either <var>existingArray</var> if it was large enough - * to hold the ASCII representation, or a newly created char[] array if - * needed. - */ - public char[] toChars(char[] existingArray, int[] outLen) { - byte[] sig = mSignature; - final int N = sig.length; - final int N2 = N*2; - char[] text = existingArray == null || N2 > existingArray.length - ? new char[N2] : existingArray; - for (int j=0; j<N; j++) { - byte v = sig[j]; - int d = (v>>4)&0xf; - text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); - d = v&0xf; - text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); - } - if (outLen != null) outLen[0] = N; - return text; - } - - /** - * Return the result of {@link #toChars()} as a String. This result is - * cached so future calls will return the same String. - */ - public String toCharsString() { - if (mString != null) return mString; - String str = new String(toChars()); - mString = str; - return mString; - } - - /** - * @return the contents of this signature as a byte array. - */ - public byte[] toByteArray() { - byte[] bytes = new byte[mSignature.length]; - System.arraycopy(mSignature, 0, bytes, 0, mSignature.length); - return bytes; - } - - @Override - public boolean equals(Object obj) { - try { - if (obj != null) { - Signature other = (Signature)obj; - return Arrays.equals(mSignature, other.mSignature); - } - } catch (ClassCastException e) { - } - return false; - } - - @Override - public int hashCode() { - if (mHaveHashCode) { - return mHashCode; - } - mHashCode = Arrays.hashCode(mSignature); - mHaveHashCode = true; - return mHashCode; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int parcelableFlags) { - dest.writeByteArray(mSignature); - } - - public static final Parcelable.Creator<Signature> CREATOR - = new Parcelable.Creator<Signature>() { - public Signature createFromParcel(Parcel source) { - return new Signature(source); - } - - public Signature[] newArray(int size) { - return new Signature[size]; - } - }; - - private Signature(Parcel source) { - mSignature = source.createByteArray(); - } -} diff --git a/core/java/android/content/pm/package.html b/core/java/android/content/pm/package.html deleted file mode 100644 index 766b7dd..0000000 --- a/core/java/android/content/pm/package.html +++ /dev/null @@ -1,7 +0,0 @@ -<HTML> -<BODY> -Contains classes for accessing information about an -application package, including information about its activities, -permissions, services, signatures, and providers. -</BODY> -</HTML>
\ No newline at end of file diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java deleted file mode 100644 index 4a073f7..0000000 --- a/core/java/android/content/res/AssetFileDescriptor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2006 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.res; - -import android.os.ParcelFileDescriptor; - -import java.io.FileDescriptor; -import java.io.IOException; - -/** - * File descriptor of an entry in the AssetManager. This provides your own - * opened FileDescriptor that can be used to read the data, as well as the - * offset and length of that entry's data in the file. - */ -public class AssetFileDescriptor { - private final ParcelFileDescriptor mFd; - private final long mStartOffset; - private final long mLength; - - /** - * Create a new AssetFileDescriptor from the given values. - */ - public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset, - long length) { - mFd = fd; - mStartOffset = startOffset; - mLength = length; - } - - /** - * The AssetFileDescriptor contains its own ParcelFileDescriptor, which - * in addition to the normal FileDescriptor object also allows you to close - * the descriptor when you are done with it. - */ - public ParcelFileDescriptor getParcelFileDescriptor() { - return mFd; - } - - /** - * Returns the FileDescriptor that can be used to read the data in the - * file. - */ - public FileDescriptor getFileDescriptor() { - return mFd.getFileDescriptor(); - } - - /** - * Returns the byte offset where this asset entry's data starts. - */ - public long getStartOffset() { - return mStartOffset; - } - - /** - * Returns the total number of bytes of this asset entry's data. - */ - public long getLength() { - return mLength; - } - - /** - * Convenience for calling <code>getParcelFileDescriptor().close()</code>. - */ - public void close() throws IOException { - mFd.close(); - } -} diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java deleted file mode 100644 index fadcb35..0000000 --- a/core/java/android/content/res/AssetManager.java +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (C) 2006 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.res; - -import android.os.ParcelFileDescriptor; -import android.util.Config; -import android.util.Log; -import android.util.TypedValue; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -/** - * Provides access to an application's raw asset files; see {@link Resources} - * for the way most applications will want to retrieve their resource data. - * This class presents a lower-level API that allows you to open and read raw - * files that have been bundled with the application as a simple stream of - * bytes. - */ -public final class AssetManager { - /* modes used when opening an asset */ - - /** - * Mode for {@link #open(String, int)}: no specific information about how - * data will be accessed. - */ - public static final int ACCESS_UNKNOWN = 0; - /** - * Mode for {@link #open(String, int)}: Read chunks, and seek forward and - * backward. - */ - public static final int ACCESS_RANDOM = 1; - /** - * Mode for {@link #open(String, int)}: Read sequentially, with an - * occasional forward seek. - */ - public static final int ACCESS_STREAMING = 2; - /** - * Mode for {@link #open(String, int)}: Attempt to load contents into - * memory, for fast small reads. - */ - public static final int ACCESS_BUFFER = 3; - - private static final String TAG = "AssetManager"; - private static final boolean localLOGV = Config.LOGV || false; - - private static final Object mSync = new Object(); - private static final TypedValue mValue = new TypedValue(); - private static final long[] mOffsets = new long[2]; - private static AssetManager mSystem = null; - - // For communication with native code. - private int mObject; - - private StringBlock mStringBlocks[] = null; - - private int mNumRefs = 1; - private boolean mOpen = true; - private String mAssetDir; - private String mAppName; - - /** - * Create a new AssetManager containing only the basic system assets. - * Applications will not generally use this method, instead retrieving the - * appropriate asset manager with {@link Resources#getAssets}. Not for - * use by applications. - * {@hide} - */ - public AssetManager() { - synchronized (mSync) { - init(); - if (localLOGV) Log.v(TAG, "New asset manager: " + this); - ensureSystemAssets(); - } - } - - private static void ensureSystemAssets() { - synchronized (mSync) { - if (mSystem == null) { - AssetManager system = new AssetManager(true); - system.makeStringBlocks(false); - mSystem = system; - } - } - } - - private AssetManager(boolean isSystem) { - init(); - if (localLOGV) Log.v(TAG, "New asset manager: " + this); - } - - /** - * Return a global shared asset manager that provides access to only - * system assets (no application assets). - * {@hide} - */ - public static AssetManager getSystem() { - ensureSystemAssets(); - return mSystem; - } - - /** - * Close this asset manager. - */ - public void close() { - synchronized(mSync) { - //System.out.println("Release: num=" + mNumRefs - // + ", released=" + mReleased); - if (mOpen) { - mOpen = false; - decRefsLocked(); - } - } - } - - /** - * Retrieve the string value associated with a particular resource - * identifier for the current configuration / skin. - */ - /*package*/ final CharSequence getResourceText(int ident) { - synchronized (mSync) { - TypedValue tmpValue = mValue; - int block = loadResourceValue(ident, tmpValue, true); - if (block >= 0) { - if (tmpValue.type == TypedValue.TYPE_STRING) { - return mStringBlocks[block].get(tmpValue.data); - } - return tmpValue.coerceToString(); - } - } - return null; - } - - /** - * Retrieve the string value associated with a particular resource - * identifier for the current configuration / skin. - */ - /*package*/ final CharSequence getResourceBagText(int ident, int bagEntryId) { - synchronized (mSync) { - TypedValue tmpValue = mValue; - int block = loadResourceBagValue(ident, bagEntryId, tmpValue, true); - if (block >= 0) { - if (tmpValue.type == TypedValue.TYPE_STRING) { - return mStringBlocks[block].get(tmpValue.data); - } - return tmpValue.coerceToString(); - } - } - return null; - } - - /** - * Retrieve the string array associated with a particular resource - * identifier. - * @param id Resource id of the string array - */ - /*package*/ final String[] getResourceStringArray(final int id) { - String[] retArray = getArrayStringResource(id); - return retArray; - } - - - /*package*/ final boolean getResourceValue(int ident, - TypedValue outValue, - boolean resolveRefs) - { - int block = loadResourceValue(ident, outValue, resolveRefs); - if (block >= 0) { - if (outValue.type != TypedValue.TYPE_STRING) { - return true; - } - outValue.string = mStringBlocks[block].get(outValue.data); - return true; - } - return false; - } - - /** - * Retrieve the text array associated with a particular resource - * identifier. - * @param id Resource id of the string array - */ - /*package*/ final CharSequence[] getResourceTextArray(final int id) { - int[] rawInfoArray = getArrayStringInfo(id); - int rawInfoArrayLen = rawInfoArray.length; - final int infoArrayLen = rawInfoArrayLen / 2; - int block; - int index; - CharSequence[] retArray = new CharSequence[infoArrayLen]; - for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) { - block = rawInfoArray[i]; - index = rawInfoArray[i + 1]; - retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null; - } - return retArray; - } - - /*package*/ final boolean getThemeValue(int theme, int ident, - TypedValue outValue, boolean resolveRefs) { - int block = loadThemeAttributeValue(theme, ident, outValue, resolveRefs); - if (block >= 0) { - if (outValue.type != TypedValue.TYPE_STRING) { - return true; - } - StringBlock[] blocks = mStringBlocks; - if (blocks == null) { - ensureStringBlocks(); - } - outValue.string = blocks[block].get(outValue.data); - return true; - } - return false; - } - - /*package*/ final void ensureStringBlocks() { - if (mStringBlocks == null) { - synchronized (mSync) { - if (mStringBlocks == null) { - makeStringBlocks(true); - } - } - } - } - - private final void makeStringBlocks(boolean copyFromSystem) { - final int sysNum = copyFromSystem ? mSystem.mStringBlocks.length : 0; - final int num = getStringBlockCount(); - mStringBlocks = new StringBlock[num]; - if (localLOGV) Log.v(TAG, "Making string blocks for " + this - + ": " + num); - for (int i=0; i<num; i++) { - if (i < sysNum) { - mStringBlocks[i] = mSystem.mStringBlocks[i]; - } else { - mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true); - } - } - } - - /*package*/ final CharSequence getPooledString(int block, int id) { - //System.out.println("Get pooled: block=" + block - // + ", id=#" + Integer.toHexString(id) - // + ", blocks=" + mStringBlocks); - return mStringBlocks[block-1].get(id); - } - - /** - * Open an asset using ACCESS_STREAMING mode. This provides access to - * files that have been bundled with an application as assets -- that is, - * files placed in to the "assets" directory. - * - * @param fileName The name of the asset to open. This name can be - * hierarchical. - * - * @see #open(String, int) - * @see #list - */ - public final InputStream open(String fileName) throws IOException { - return open(fileName, ACCESS_STREAMING); - } - - /** - * Open an asset using an explicit access mode, returning an InputStream to - * read its contents. This provides access to files that have been bundled - * with an application as assets -- that is, files placed in to the - * "assets" directory. - * - * @param fileName The name of the asset to open. This name can be - * hierarchical. - * @param accessMode Desired access mode for retrieving the data. - * - * @see #ACCESS_UNKNOWN - * @see #ACCESS_STREAMING - * @see #ACCESS_RANDOM - * @see #ACCESS_BUFFER - * @see #open(String) - * @see #list - */ - public final InputStream open(String fileName, int accessMode) - throws IOException { - synchronized (mSync) { - if (!mOpen) { - throw new RuntimeException("Assetmanager has been closed"); - } - int asset = openAsset(fileName, accessMode); - if (asset != 0) { - mNumRefs++; - return new AssetInputStream(asset); - } - } - throw new FileNotFoundException("Asset file: " + fileName); - } - - public final AssetFileDescriptor openFd(String fileName) - throws IOException { - synchronized (mSync) { - if (!mOpen) { - throw new RuntimeException("Assetmanager has been closed"); - } - ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets); - if (pfd != null) { - return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]); - } - } - throw new FileNotFoundException("Asset file: " + fileName); - } - - /** - * Return a String array of all the assets at the given path. - * - * @param path A relative path within the assets, i.e., "docs/home.html". - * - * @return String[] Array of strings, one for each asset. These file - * names are relative to 'path'. You can open the file by - * concatenating 'path' and a name in the returned string (via - * File) and passing that to open(). - * - * @see #open - */ - public native final String[] list(String path) - throws IOException; - - /** - * {@hide} - * Open a non-asset file as an asset using ACCESS_STREAMING mode. This - * provides direct access to all of the files included in an application - * package (not only its assets). Applications should not normally use - * this. - * - * @see #open(String) - */ - public final InputStream openNonAsset(String fileName) throws IOException { - return openNonAsset(0, fileName, ACCESS_STREAMING); - } - - /** - * {@hide} - * Open a non-asset file as an asset using a specific access mode. This - * provides direct access to all of the files included in an application - * package (not only its assets). Applications should not normally use - * this. - * - * @see #open(String, int) - */ - public final InputStream openNonAsset(String fileName, int accessMode) - throws IOException { - return openNonAsset(0, fileName, accessMode); - } - - /** - * {@hide} - * Open a non-asset in a specified package. Not for use by applications. - * - * @param cookie Identifier of the package to be opened. - * @param fileName Name of the asset to retrieve. - */ - public final InputStream openNonAsset(int cookie, String fileName) - throws IOException { - return openNonAsset(cookie, fileName, ACCESS_STREAMING); - } - - /** - * {@hide} - * Open a non-asset in a specified package. Not for use by applications. - * - * @param cookie Identifier of the package to be opened. - * @param fileName Name of the asset to retrieve. - * @param accessMode Desired access mode for retrieving the data. - */ - public final InputStream openNonAsset(int cookie, String fileName, int accessMode) - throws IOException { - synchronized (mSync) { - if (!mOpen) { - throw new RuntimeException("Assetmanager has been closed"); - } - int asset = openNonAssetNative(cookie, fileName, accessMode); - if (asset != 0) { - mNumRefs++; - return new AssetInputStream(asset); - } - } - throw new FileNotFoundException("Asset absolute file: " + fileName); - } - - public final AssetFileDescriptor openNonAssetFd(String fileName) - throws IOException { - return openNonAssetFd(0, fileName); - } - - public final AssetFileDescriptor openNonAssetFd(int cookie, - String fileName) throws IOException { - synchronized (mSync) { - if (!mOpen) { - throw new RuntimeException("Assetmanager has been closed"); - } - ParcelFileDescriptor pfd = openNonAssetFdNative(cookie, - fileName, mOffsets); - if (pfd != null) { - return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]); - } - } - throw new FileNotFoundException("Asset absolute file: " + fileName); - } - - /** - * Retrieve a parser for a compiled XML file. - * - * @param fileName The name of the file to retrieve. - */ - public final XmlResourceParser openXmlResourceParser(String fileName) - throws IOException { - return openXmlResourceParser(0, fileName); - } - - /** - * Retrieve a parser for a compiled XML file. - * - * @param cookie Identifier of the package to be opened. - * @param fileName The name of the file to retrieve. - */ - public final XmlResourceParser openXmlResourceParser(int cookie, - String fileName) throws IOException { - XmlBlock block = openXmlBlockAsset(cookie, fileName); - XmlResourceParser rp = block.newParser(); - block.close(); - return rp; - } - - /** - * {@hide} - * Retrieve a non-asset as a compiled XML file. Not for use by - * applications. - * - * @param fileName The name of the file to retrieve. - */ - /*package*/ final XmlBlock openXmlBlockAsset(String fileName) - throws IOException { - return openXmlBlockAsset(0, fileName); - } - - /** - * {@hide} - * Retrieve a non-asset as a compiled XML file. Not for use by - * applications. - * - * @param cookie Identifier of the package to be opened. - * @param fileName Name of the asset to retrieve. - */ - /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName) - throws IOException { - synchronized (mSync) { - if (!mOpen) { - throw new RuntimeException("Assetmanager has been closed"); - } - int xmlBlock = openXmlAssetNative(cookie, fileName); - if (xmlBlock != 0) { - mNumRefs++; - return new XmlBlock(this, xmlBlock); - } - } - throw new FileNotFoundException("Asset XML file: " + fileName); - } - - /*package*/ void xmlBlockGone() { - synchronized (mSync) { - decRefsLocked(); - } - } - - /*package*/ final int createTheme() { - synchronized (mSync) { - if (!mOpen) { - throw new RuntimeException("Assetmanager has been closed"); - } - mNumRefs++; - return newTheme(); - } - } - - /*package*/ final void releaseTheme(int theme) { - synchronized (mSync) { - deleteTheme(theme); - decRefsLocked(); - } - } - - protected void finalize() throws Throwable { - destroy(); - } - - public final class AssetInputStream extends InputStream { - public final int getAssetInt() { - return mAsset; - } - private AssetInputStream(int asset) - { - mAsset = asset; - mLength = getAssetLength(asset); - } - public final int read() throws IOException { - return readAssetChar(mAsset); - } - public final boolean markSupported() { - return true; - } - public final int available() throws IOException { - long len = getAssetRemainingLength(mAsset); - return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len; - } - public final void close() throws IOException { - synchronized (AssetManager.mSync) { - if (mAsset != 0) { - destroyAsset(mAsset); - mAsset = 0; - decRefsLocked(); - } - } - } - public final void mark(int readlimit) { - mMarkPos = seekAsset(mAsset, 0, 0); - } - public final void reset() throws IOException { - seekAsset(mAsset, mMarkPos, -1); - } - public final int read(byte[] b) throws IOException { - return readAsset(mAsset, b, 0, b.length); - } - public final int read(byte[] b, int off, int len) throws IOException { - return readAsset(mAsset, b, off, len); - } - public final long skip(long n) throws IOException { - long pos = seekAsset(mAsset, 0, 0); - if ((pos+n) > mLength) { - n = mLength-pos; - } - if (n > 0) { - seekAsset(mAsset, n, 0); - } - return n; - } - - protected void finalize() throws Throwable - { - close(); - } - - private int mAsset; - private long mLength; - private long mMarkPos; - } - - /** - * Add an additional set of assets to the asset manager. This can be - * either a directory or ZIP file. Not for use by applications. A - * zero return value indicates failure. - * {@hide} - */ - public native final int addAssetPath(String path); - - /** - * Determine whether the state in this asset manager is up-to-date with - * the files on the filesystem. If false is returned, you need to - * instantiate a new AssetManager class to see the new data. - * {@hide} - */ - public native final boolean isUpToDate(); - - /** - * Change the locale being used by this asset manager. Not for use by - * applications. - * {@hide} - */ - public native final void setLocale(String locale); - - /** - * Get the locales that this asset manager contains data for. - */ - public native final String[] getLocales(); - - /** - * Change the configuation used when retrieving resources. Not for use by - * applications. - * {@hide} - */ - public native final void setConfiguration(int mcc, int mnc, String locale, - int orientation, int touchscreen, int density, int keyboard, - int keyboardHidden, int navigation, int screenWidth, int screenHeight, - int majorVersion); - - /** - * Retrieve the resource identifier for the given resource name. - */ - /*package*/ native final int getResourceIdentifier(String type, - String name, - String defPackage); - - /*package*/ native final String getResourceName(int resid); - /*package*/ native final String getResourcePackageName(int resid); - /*package*/ native final String getResourceTypeName(int resid); - /*package*/ native final String getResourceEntryName(int resid); - - private native final int openAsset(String fileName, int accessMode); - private final native ParcelFileDescriptor openAssetFd(String fileName, - long[] outOffsets) throws IOException; - private native final int openNonAssetNative(int cookie, String fileName, - int accessMode); - private native ParcelFileDescriptor openNonAssetFdNative(int cookie, - String fileName, long[] outOffsets) throws IOException; - private native final void destroyAsset(int asset); - private native final int readAssetChar(int asset); - private native final int readAsset(int asset, byte[] b, int off, int len); - private native final long seekAsset(int asset, long offset, int whence); - private native final long getAssetLength(int asset); - private native final long getAssetRemainingLength(int asset); - - /** Returns true if the resource was found, filling in mRetStringBlock and - * mRetData. */ - private native final int loadResourceValue(int ident, TypedValue outValue, - boolean resolve); - /** Returns true if the resource was found, filling in mRetStringBlock and - * mRetData. */ - private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue, - boolean resolve); - /*package*/ static final int STYLE_NUM_ENTRIES = 5; - /*package*/ static final int STYLE_TYPE = 0; - /*package*/ static final int STYLE_DATA = 1; - /*package*/ static final int STYLE_ASSET_COOKIE = 2; - /*package*/ static final int STYLE_RESOURCE_ID = 3; - /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4; - /*package*/ native static final boolean applyStyle(int theme, - int defStyleAttr, int defStyleRes, int xmlParser, - int[] inAttrs, int[] outValues, int[] outIndices); - /*package*/ native final boolean retrieveAttributes( - int xmlParser, int[] inAttrs, int[] outValues, int[] outIndices); - /*package*/ native final int getArraySize(int resource); - /*package*/ native final int retrieveArray(int resource, int[] outValues); - private native final int getStringBlockCount(); - private native final int getNativeStringBlock(int block); - - /** - * {@hide} - */ - public native final String getCookieName(int cookie); - - /** - * {@hide} - */ - public native static final int getGlobalAssetCount(); - - /** - * {@hide} - */ - public native static final int getGlobalAssetManagerCount(); - - private native final int newTheme(); - private native final void deleteTheme(int theme); - /*package*/ native static final void applyThemeStyle(int theme, int styleRes, boolean force); - /*package*/ native static final void copyTheme(int dest, int source); - /*package*/ native static final int loadThemeAttributeValue(int theme, int ident, - TypedValue outValue, - boolean resolve); - /*package*/ native static final void dumpTheme(int theme, int priority, String tag, String prefix); - - private native final int openXmlAssetNative(int cookie, String fileName); - - private native final String[] getArrayStringResource(int arrayRes); - private native final int[] getArrayStringInfo(int arrayRes); - /*package*/ native final int[] getArrayIntResource(int arrayRes); - - private native final void init(); - private native final void destroy(); - - private final void decRefsLocked() { - mNumRefs--; - //System.out.println("Dec streams: mNumRefs=" + mNumRefs - // + " mReleased=" + mReleased); - if (mNumRefs == 0) { - destroy(); - } - } -} diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java deleted file mode 100644 index 17cb687..0000000 --- a/core/java/android/content/res/ColorStateList.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * 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.res; - -import com.google.android.collect.Lists; - -import com.android.internal.util.ArrayUtils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.util.AttributeSet; -import android.util.SparseArray; -import android.util.StateSet; -import android.util.Xml; -import android.os.Parcel; -import android.os.Parcelable; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.util.Arrays; - -/** - * - * Lets you map {@link android.view.View} state sets to colors. - * - * {@link android.content.res.ColorStateList}s are created from XML resource files defined in the - * "color" subdirectory directory of an application's resource directory. The XML file contains - * a single "selector" element with a number of "item" elements inside. For example: - * - * <pre> - * <selector xmlns:android="http://schemas.android.com/apk/res/android"> - * <item android:state_focused="true" android:color="@color/testcolor1"/> - * <item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /> - * <item android:state_enabled="false" android:colore="@color/testcolor3" /> - * <item android:state_active="true" android:color="@color/testcolor4" /> - * <item android:color="@color/testcolor5"/> - * </selector> - * </pre> - * - * This defines a set of state spec / color pairs where each state spec specifies a set of - * states that a view must either be in or not be in and the color specifies the color associated - * with that spec. The list of state specs will be processed in order of the items in the XML file. - * An item with no state spec is considered to match any set of states and is generally useful as - * a final item to be used as a default. Note that if you have such an item before any other items - * in the list then any subsequent items will end up being ignored. - */ -public class ColorStateList implements Parcelable { - - private int[][] mStateSpecs; // must be parallel to mColors - private int[] mColors; // must be parallel to mStateSpecs - private int mDefaultColor = 0xffff0000; - - private static final int[][] EMPTY = new int[][] { new int[0] }; - private static final SparseArray<WeakReference<ColorStateList>> sCache = - new SparseArray<WeakReference<ColorStateList>>(); - - private ColorStateList() { } - - /** - * Creates a ColorStateList that returns the specified mapping from - * states to colors. - */ - public ColorStateList(int[][] states, int[] colors) { - mStateSpecs = states; - mColors = colors; - - if (states.length > 0) { - mDefaultColor = colors[0]; - - for (int i = 0; i < states.length; i++) { - if (states[i].length == 0) { - mDefaultColor = colors[i]; - } - } - } - } - - /** - * Creates or retrieves a ColorStateList that always returns a single color. - */ - public static ColorStateList valueOf(int color) { - // TODO: should we collect these eventually? - synchronized (sCache) { - WeakReference<ColorStateList> ref = sCache.get(color); - ColorStateList csl = ref != null ? ref.get() : null; - - if (csl != null) { - return csl; - } - - csl = new ColorStateList(EMPTY, new int[] { color }); - sCache.put(color, new WeakReference<ColorStateList>(csl)); - return csl; - } - } - - /** - * Create a ColorStateList from an XML document, given a set of {@link Resources}. - */ - public static ColorStateList createFromXml(Resources r, XmlPullParser parser) - throws XmlPullParserException, IOException { - AttributeSet attrs = Xml.asAttributeSet(parser); - - int type; - while ((type=parser.next()) != XmlPullParser.START_TAG - && type != XmlPullParser.END_DOCUMENT) { - } - - if (type != XmlPullParser.START_TAG) { - throw new XmlPullParserException("No start tag found"); - } - - final ColorStateList colorStateList = createFromXmlInner(r, parser, attrs); - - return colorStateList; - } - - /* Create from inside an XML document. Called on a parser positioned at - * a tag in an XML document, tries to create a ColorStateList from that tag. - * Returns null if the tag is not a valid ColorStateList. - */ - private static ColorStateList createFromXmlInner(Resources r, - XmlPullParser parser, - AttributeSet attrs) - throws XmlPullParserException, IOException { - ColorStateList colorStateList; - - final String name = parser.getName(); - - if (name.equals("selector")) { - colorStateList = new ColorStateList(); - } else { - throw new XmlPullParserException( - parser.getPositionDescription() + ": invalid drawable tag " - + name); - } - - colorStateList.inflate(r, parser, attrs); - return colorStateList; - } - - /** - * Creates a new ColorStateList that has the same states and - * colors as this one but where each color has the specified alpha value - * (0-255). - */ - public ColorStateList withAlpha(int alpha) { - int[] colors = new int[mColors.length]; - - int len = colors.length; - for (int i = 0; i < len; i++) { - colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24); - } - - return new ColorStateList(mStateSpecs, colors); - } - - /** - * Fill in this object based on the contents of an XML "selector" element. - */ - private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) - throws XmlPullParserException, IOException { - - int type; - - final int innerDepth = parser.getDepth()+1; - int depth; - - int listAllocated = 20; - int listSize = 0; - int[] colorList = new int[listAllocated]; - int[][] stateSpecList = new int[listAllocated][]; - - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && ((depth=parser.getDepth()) >= innerDepth - || type != XmlPullParser.END_TAG)) { - if (type != XmlPullParser.START_TAG) { - continue; - } - - if (depth > innerDepth || !parser.getName().equals("item")) { - continue; - } - - int colorRes = 0; - int color = 0xffff0000; - boolean haveColor = false; - - int i; - int j = 0; - final int numAttrs = attrs.getAttributeCount(); - int[] stateSpec = new int[numAttrs]; - for (i = 0; i < numAttrs; i++) { - final int stateResId = attrs.getAttributeNameResource(i); - if (stateResId == 0) break; - if (stateResId == com.android.internal.R.attr.color) { - colorRes = attrs.getAttributeResourceValue(i, 0); - - if (colorRes == 0) { - color = attrs.getAttributeIntValue(i, color); - haveColor = true; - } - } else { - stateSpec[j++] = attrs.getAttributeBooleanValue(i, false) - ? stateResId - : -stateResId; - } - } - stateSpec = StateSet.trimStateSet(stateSpec, j); - - if (colorRes != 0) { - color = r.getColor(colorRes); - } else if (!haveColor) { - throw new XmlPullParserException( - parser.getPositionDescription() - + ": <item> tag requires a 'android:color' attribute."); - } - - if (listSize == 0 || stateSpec.length == 0) { - mDefaultColor = color; - } - - if (listSize + 1 >= listAllocated) { - listAllocated = ArrayUtils.idealIntArraySize(listSize + 1); - - int[] ncolor = new int[listAllocated]; - System.arraycopy(colorList, 0, ncolor, 0, listSize); - - int[][] nstate = new int[listAllocated][]; - System.arraycopy(stateSpecList, 0, nstate, 0, listSize); - - colorList = ncolor; - stateSpecList = nstate; - } - - colorList[listSize] = color; - stateSpecList[listSize] = stateSpec; - listSize++; - } - - mColors = new int[listSize]; - mStateSpecs = new int[listSize][]; - System.arraycopy(colorList, 0, mColors, 0, listSize); - System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize); - } - - public boolean isStateful() { - return mStateSpecs.length > 1; - } - - /** - * Return the color associated with the given set of {@link android.view.View} states. - * - * @param stateSet an array of {@link android.view.View} states - * @param defaultColor the color to return if there's not state spec in this - * {@link ColorStateList} that matches the stateSet. - * - * @return the color associated with that set of states in this {@link ColorStateList}. - */ - public int getColorForState(int[] stateSet, int defaultColor) { - final int setLength = mStateSpecs.length; - for (int i = 0; i < setLength; i++) { - int[] stateSpec = mStateSpecs[i]; - if (StateSet.stateSetMatches(stateSpec, stateSet)) { - return mColors[i]; - } - } - return defaultColor; - } - - /** - * Return the default color in this {@link ColorStateList}. - * - * @return the default color in this {@link ColorStateList}. - */ - public int getDefaultColor() { - return mDefaultColor; - } - - public String toString() { - return "ColorStateList{" + - "mStateSpecs=" + Arrays.deepToString(mStateSpecs) + - "mColors=" + Arrays.toString(mColors) + - "mDefaultColor=" + mDefaultColor + '}'; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - final int N = mStateSpecs.length; - dest.writeInt(N); - for (int i=0; i<N; i++) { - dest.writeIntArray(mStateSpecs[i]); - } - dest.writeArray(mStateSpecs); - dest.writeIntArray(mColors); - } - - public static final Parcelable.Creator<ColorStateList> CREATOR = - new Parcelable.Creator<ColorStateList>() { - public ColorStateList[] newArray(int size) { - return new ColorStateList[size]; - } - - public ColorStateList createFromParcel(Parcel source) { - final int N = source.readInt(); - int[][] stateSpecs = new int[N][]; - for (int i=0; i<N; i++) { - stateSpecs[i] = source.createIntArray(); - } - int[] colors = source.createIntArray(); - return new ColorStateList(stateSpecs, colors); - } - }; -} diff --git a/core/java/android/content/res/Configuration.aidl b/core/java/android/content/res/Configuration.aidl deleted file mode 100755 index bb7f2dd..0000000 --- a/core/java/android/content/res/Configuration.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 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.res; - -parcelable Configuration; - diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java deleted file mode 100644 index 7e4b7ac..0000000 --- a/core/java/android/content/res/Configuration.java +++ /dev/null @@ -1,436 +0,0 @@ -package android.content.res; - -import android.content.pm.ActivityInfo; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Locale; - -/** - * This class describes all device configuration information that can - * impact the resources the application retrieves. This includes both - * user-specified configuration options (locale and scaling) as well - * as dynamic device configuration (various types of input devices). - */ -public final class Configuration implements Parcelable, Comparable<Configuration> { - /** - * Current user preference for the scaling factor for fonts, relative - * to the base density scaling. - */ - public float fontScale; - - /** - * IMSI MCC (Mobile Country Code). 0 if undefined. - */ - public int mcc; - - /** - * IMSI MNC (Mobile Network Code). 0 if undefined. - */ - public int mnc; - - /** - * Current user preference for the locale. - */ - public Locale locale; - - /** - * Locale should persist on setting - * @hide pending API council approval - */ - public boolean userSetLocale; - - public static final int TOUCHSCREEN_UNDEFINED = 0; - public static final int TOUCHSCREEN_NOTOUCH = 1; - public static final int TOUCHSCREEN_STYLUS = 2; - public static final int TOUCHSCREEN_FINGER = 3; - - /** - * The kind of touch screen attached to the device. - * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_STYLUS}, - * {@link #TOUCHSCREEN_FINGER}. - */ - public int touchscreen; - - public static final int KEYBOARD_UNDEFINED = 0; - public static final int KEYBOARD_NOKEYS = 1; - public static final int KEYBOARD_QWERTY = 2; - public static final int KEYBOARD_12KEY = 3; - - /** - * The kind of keyboard attached to the device. - * One of: {@link #KEYBOARD_QWERTY}, {@link #KEYBOARD_12KEY}. - */ - public int keyboard; - - public static final int KEYBOARDHIDDEN_UNDEFINED = 0; - public static final int KEYBOARDHIDDEN_NO = 1; - public static final int KEYBOARDHIDDEN_YES = 2; - /** Constant matching actual resource implementation. {@hide} */ - public static final int KEYBOARDHIDDEN_SOFT = 3; - - /** - * A flag indicating whether any keyboard is available. Unlike - * {@link #hardKeyboardHidden}, this also takes into account a soft - * keyboard, so if the hard keyboard is hidden but there is soft - * keyboard available, it will be set to NO. Value is one of: - * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}. - */ - public int keyboardHidden; - - public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; - public static final int HARDKEYBOARDHIDDEN_NO = 1; - public static final int HARDKEYBOARDHIDDEN_YES = 2; - - /** - * A flag indicating whether the hard keyboard has been hidden. This will - * be set on a device with a mechanism to hide the keyboard from the - * user, when that mechanism is closed. One of: - * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}. - */ - public int hardKeyboardHidden; - - public static final int NAVIGATION_UNDEFINED = 0; - public static final int NAVIGATION_NONAV = 1; - public static final int NAVIGATION_DPAD = 2; - public static final int NAVIGATION_TRACKBALL = 3; - public static final int NAVIGATION_WHEEL = 4; - - /** - * The kind of navigation method available on the device. - * One of: {@link #NAVIGATION_DPAD}, {@link #NAVIGATION_TRACKBALL}, - * {@link #NAVIGATION_WHEEL}. - */ - public int navigation; - - public static final int ORIENTATION_UNDEFINED = 0; - public static final int ORIENTATION_PORTRAIT = 1; - public static final int ORIENTATION_LANDSCAPE = 2; - public static final int ORIENTATION_SQUARE = 3; - - /** - * Overall orientation of the screen. May be one of - * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}, - * or {@link #ORIENTATION_SQUARE}. - */ - public int orientation; - - /** - * Construct an invalid Configuration. You must call {@link #setToDefaults} - * for this object to be valid. {@more} - */ - public Configuration() { - setToDefaults(); - } - - /** - * Makes a deep copy suitable for modification. - */ - public Configuration(Configuration o) { - fontScale = o.fontScale; - mcc = o.mcc; - mnc = o.mnc; - if (o.locale != null) { - locale = (Locale) o.locale.clone(); - } - userSetLocale = o.userSetLocale; - touchscreen = o.touchscreen; - keyboard = o.keyboard; - keyboardHidden = o.keyboardHidden; - hardKeyboardHidden = o.hardKeyboardHidden; - navigation = o.navigation; - orientation = o.orientation; - } - - public String toString() { - return "{ scale=" + fontScale + " imsi=" + mcc + "/" + mnc - + " locale=" + locale - + " touch=" + touchscreen + " key=" + keyboard + "/" - + keyboardHidden + "/" + hardKeyboardHidden - + " nav=" + navigation + " orien=" + orientation + " }"; - } - - /** - * Set this object to the system defaults. - */ - public void setToDefaults() { - fontScale = 1; - mcc = mnc = 0; - locale = Locale.getDefault(); - userSetLocale = false; - touchscreen = TOUCHSCREEN_UNDEFINED; - keyboard = KEYBOARD_UNDEFINED; - keyboardHidden = KEYBOARDHIDDEN_UNDEFINED; - hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED; - navigation = NAVIGATION_UNDEFINED; - orientation = ORIENTATION_UNDEFINED; - } - - /** {@hide} */ - @Deprecated public void makeDefault() { - setToDefaults(); - } - - /** - * Copy the fields from delta into this Configuration object, keeping - * track of which ones have changed. Any undefined fields in - * <var>delta</var> are ignored and not copied in to the current - * Configuration. - * @return Returns a bit mask of the changed fields, as per - * {@link #diff}. - */ - public int updateFrom(Configuration delta) { - int changed = 0; - if (delta.fontScale > 0 && fontScale != delta.fontScale) { - changed |= ActivityInfo.CONFIG_FONT_SCALE; - fontScale = delta.fontScale; - } - if (delta.mcc != 0 && mcc != delta.mcc) { - changed |= ActivityInfo.CONFIG_MCC; - mcc = delta.mcc; - } - if (delta.mnc != 0 && mnc != delta.mnc) { - changed |= ActivityInfo.CONFIG_MNC; - mnc = delta.mnc; - } - if (delta.locale != null - && (locale == null || !locale.equals(delta.locale))) { - changed |= ActivityInfo.CONFIG_LOCALE; - locale = delta.locale != null - ? (Locale) delta.locale.clone() : null; - } - if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))) - { - userSetLocale = true; - changed |= ActivityInfo.CONFIG_LOCALE; - } - if (delta.touchscreen != TOUCHSCREEN_UNDEFINED - && touchscreen != delta.touchscreen) { - changed |= ActivityInfo.CONFIG_TOUCHSCREEN; - touchscreen = delta.touchscreen; - } - if (delta.keyboard != KEYBOARD_UNDEFINED - && keyboard != delta.keyboard) { - changed |= ActivityInfo.CONFIG_KEYBOARD; - keyboard = delta.keyboard; - } - if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED - && keyboardHidden != delta.keyboardHidden) { - changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; - keyboardHidden = delta.keyboardHidden; - } - if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED - && hardKeyboardHidden != delta.hardKeyboardHidden) { - changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; - hardKeyboardHidden = delta.hardKeyboardHidden; - } - if (delta.navigation != NAVIGATION_UNDEFINED - && navigation != delta.navigation) { - changed |= ActivityInfo.CONFIG_NAVIGATION; - navigation = delta.navigation; - } - if (delta.orientation != ORIENTATION_UNDEFINED - && orientation != delta.orientation) { - changed |= ActivityInfo.CONFIG_ORIENTATION; - orientation = delta.orientation; - } - - return changed; - } - - /** - * Return a bit mask of the differences between this Configuration - * object and the given one. Does not change the values of either. Any - * undefined fields in <var>delta</var> are ignored. - * @return Returns a bit mask indicating which configuration - * values has changed, containing any combination of - * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE - * PackageManager.ActivityInfo.CONFIG_FONT_SCALE}, - * {@link android.content.pm.ActivityInfo#CONFIG_MCC - * PackageManager.ActivityInfo.CONFIG_MCC}, - * {@link android.content.pm.ActivityInfo#CONFIG_MNC - * PackageManager.ActivityInfo.CONFIG_MNC}, - * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE - * PackageManager.ActivityInfo.CONFIG_LOCALE}, - * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN - * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN}, - * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD - * PackageManager.ActivityInfo.CONFIG_KEYBOARD}, - * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION - * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, or - * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION - * PackageManager.ActivityInfo.CONFIG_ORIENTATION}. - */ - public int diff(Configuration delta) { - int changed = 0; - if (delta.fontScale > 0 && fontScale != delta.fontScale) { - changed |= ActivityInfo.CONFIG_FONT_SCALE; - } - if (delta.mcc != 0 && mcc != delta.mcc) { - changed |= ActivityInfo.CONFIG_MCC; - } - if (delta.mnc != 0 && mnc != delta.mnc) { - changed |= ActivityInfo.CONFIG_MNC; - } - if (delta.locale != null - && (locale == null || !locale.equals(delta.locale))) { - changed |= ActivityInfo.CONFIG_LOCALE; - } - if (delta.touchscreen != TOUCHSCREEN_UNDEFINED - && touchscreen != delta.touchscreen) { - changed |= ActivityInfo.CONFIG_TOUCHSCREEN; - } - if (delta.keyboard != KEYBOARD_UNDEFINED - && keyboard != delta.keyboard) { - changed |= ActivityInfo.CONFIG_KEYBOARD; - } - if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED - && keyboardHidden != delta.keyboardHidden) { - changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; - } - if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED - && hardKeyboardHidden != delta.hardKeyboardHidden) { - changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN; - } - if (delta.navigation != NAVIGATION_UNDEFINED - && navigation != delta.navigation) { - changed |= ActivityInfo.CONFIG_NAVIGATION; - } - if (delta.orientation != ORIENTATION_UNDEFINED - && orientation != delta.orientation) { - changed |= ActivityInfo.CONFIG_ORIENTATION; - } - - return changed; - } - - /** - * Determine if a new resource needs to be loaded from the bit set of - * configuration changes returned by {@link #updateFrom(Configuration)}. - * - * @param configChanges The mask of changes configurations as returned by - * {@link #updateFrom(Configuration)}. - * @param interestingChanges The configuration changes that the resource - * can handled, as given in {@link android.util.TypedValue#changingConfigurations}. - * - * @return Return true if the resource needs to be loaded, else false. - */ - public static boolean needNewResources(int configChanges, int interestingChanges) { - return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0; - } - - /** - * Parcelable methods - */ - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeFloat(fontScale); - dest.writeInt(mcc); - dest.writeInt(mnc); - if (locale == null) { - dest.writeInt(0); - } else { - dest.writeInt(1); - dest.writeString(locale.getLanguage()); - dest.writeString(locale.getCountry()); - dest.writeString(locale.getVariant()); - } - if(userSetLocale) { - dest.writeInt(1); - } else { - dest.writeInt(0); - } - dest.writeInt(touchscreen); - dest.writeInt(keyboard); - dest.writeInt(keyboardHidden); - dest.writeInt(hardKeyboardHidden); - dest.writeInt(navigation); - dest.writeInt(orientation); - } - - public static final Parcelable.Creator<Configuration> CREATOR - = new Parcelable.Creator<Configuration>() { - public Configuration createFromParcel(Parcel source) { - return new Configuration(source); - } - - public Configuration[] newArray(int size) { - return new Configuration[size]; - } - }; - - /** - * Construct this Configuration object, reading from the Parcel. - */ - private Configuration(Parcel source) { - fontScale = source.readFloat(); - mcc = source.readInt(); - mnc = source.readInt(); - if (source.readInt() != 0) { - locale = new Locale(source.readString(), source.readString(), - source.readString()); - } - userSetLocale = (source.readInt()==1); - touchscreen = source.readInt(); - keyboard = source.readInt(); - keyboardHidden = source.readInt(); - hardKeyboardHidden = source.readInt(); - navigation = source.readInt(); - orientation = source.readInt(); - } - - public int compareTo(Configuration that) { - int n; - float a = this.fontScale; - float b = that.fontScale; - if (a < b) return -1; - if (a > b) return 1; - n = this.mcc - that.mcc; - if (n != 0) return n; - n = this.mnc - that.mnc; - if (n != 0) return n; - n = this.locale.getLanguage().compareTo(that.locale.getLanguage()); - if (n != 0) return n; - n = this.locale.getCountry().compareTo(that.locale.getCountry()); - if (n != 0) return n; - n = this.locale.getVariant().compareTo(that.locale.getVariant()); - if (n != 0) return n; - n = this.touchscreen - that.touchscreen; - if (n != 0) return n; - n = this.keyboard - that.keyboard; - if (n != 0) return n; - n = this.keyboardHidden - that.keyboardHidden; - if (n != 0) return n; - n = this.hardKeyboardHidden - that.hardKeyboardHidden; - if (n != 0) return n; - n = this.navigation - that.navigation; - if (n != 0) return n; - n = this.orientation - that.orientation; - //if (n != 0) return n; - return n; - } - - public boolean equals(Configuration that) { - if (that == null) return false; - if (that == this) return true; - return this.compareTo(that) == 0; - } - - public boolean equals(Object that) { - try { - return equals((Configuration)that); - } catch (ClassCastException e) { - } - return false; - } - - public int hashCode() { - return ((int)this.fontScale) + this.mcc + this.mnc - + this.locale.hashCode() + this.touchscreen - + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden - + this.navigation + this.orientation; - } -} diff --git a/core/java/android/content/res/PluralRules.java b/core/java/android/content/res/PluralRules.java deleted file mode 100644 index 2dce3c1..0000000 --- a/core/java/android/content/res/PluralRules.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.res; - -import java.util.Locale; - -/* - * Yuck-o. This is not the right way to implement this. When the ICU PluralRules - * object has been integrated to android, we should switch to that. For now, yuck-o. - */ - -abstract class PluralRules { - - static final int QUANTITY_OTHER = 0x0000; - static final int QUANTITY_ZERO = 0x0001; - static final int QUANTITY_ONE = 0x0002; - static final int QUANTITY_TWO = 0x0004; - static final int QUANTITY_FEW = 0x0008; - static final int QUANTITY_MANY = 0x0010; - - static final int ID_OTHER = 0x01000004; - - abstract int quantityForNumber(int n); - - final int attrForNumber(int n) { - return PluralRules.attrForQuantity(quantityForNumber(n)); - } - - static final int attrForQuantity(int quantity) { - // see include/utils/ResourceTypes.h - switch (quantity) { - case QUANTITY_ZERO: return 0x01000005; - case QUANTITY_ONE: return 0x01000006; - case QUANTITY_TWO: return 0x01000007; - case QUANTITY_FEW: return 0x01000008; - case QUANTITY_MANY: return 0x01000009; - default: return ID_OTHER; - } - } - - static final String stringForQuantity(int quantity) { - switch (quantity) { - case QUANTITY_ZERO: - return "zero"; - case QUANTITY_ONE: - return "one"; - case QUANTITY_TWO: - return "two"; - case QUANTITY_FEW: - return "few"; - case QUANTITY_MANY: - return "many"; - default: - return "other"; - } - } - - static final PluralRules ruleForLocale(Locale locale) { - String lang = locale.getLanguage(); - if ("cs".equals(lang)) { - if (cs == null) cs = new cs(); - return cs; - } - else { - if (en == null) en = new en(); - return en; - } - } - - private static PluralRules cs; - private static class cs extends PluralRules { - int quantityForNumber(int n) { - if (n == 1) { - return QUANTITY_ONE; - } - else if (n >= 2 && n <= 4) { - return QUANTITY_FEW; - } - else { - return QUANTITY_OTHER; - } - } - } - - private static PluralRules en; - private static class en extends PluralRules { - int quantityForNumber(int n) { - if (n == 1) { - return QUANTITY_ONE; - } - else { - return QUANTITY_OTHER; - } - } - } -} - diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java deleted file mode 100644 index 5a0daea..0000000 --- a/core/java/android/content/res/Resources.java +++ /dev/null @@ -1,1850 +0,0 @@ -/* - * Copyright (C) 2006 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.res; - - -import com.android.internal.util.XmlUtils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.graphics.Movie; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.os.SystemProperties; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.SparseArray; -import android.util.TypedValue; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.WeakReference; - -/** - * Class for accessing an application's resources. This sits on top of the - * asset manager of the application (accessible through getAssets()) and - * provides a higher-level API for getting typed data from the assets. - */ -public class Resources { - static final String TAG = "Resources"; - private static final boolean DEBUG_LOAD = false; - private static final boolean DEBUG_CONFIG = false; - - private static final int sSdkVersion = SystemProperties.getInt( - "ro.build.version.sdk", 0); - private static final Object mSync = new Object(); - private static Resources mSystem = null; - - // Information about preloaded resources. Note that they are not - // protected by a lock, because while preloading in zygote we are all - // single-threaded, and after that these are immutable. - private static final SparseArray<Drawable.ConstantState> mPreloadedDrawables - = new SparseArray<Drawable.ConstantState>(); - private static boolean mPreloaded; - - /*package*/ final TypedValue mTmpValue = new TypedValue(); - - // These are protected by the mTmpValue lock. - private final SparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache - = new SparseArray<WeakReference<Drawable.ConstantState> >(); - private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache - = new SparseArray<WeakReference<ColorStateList> >(); - private boolean mPreloading; - - /*package*/ TypedArray mCachedStyledAttributes = null; - - private int mLastCachedXmlBlockIndex = -1; - private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 }; - private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4]; - - /*package*/ final AssetManager mAssets; - private final Configuration mConfiguration = new Configuration(); - /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics(); - PluralRules mPluralRule; - - /** - * This exception is thrown by the resource APIs when a requested resource - * can not be found. - */ - public static class NotFoundException extends RuntimeException { - public NotFoundException() { - } - - public NotFoundException(String name) { - super(name); - } - }; - - /** - * Create a new Resources object on top of an existing set of assets in an - * AssetManager. - * - * @param assets Previously created AssetManager. - * @param metrics Current display metrics to consider when - * selecting/computing resource values. - * @param config Desired device configuration to consider when - * selecting/computing resource values (optional). - */ - public Resources(AssetManager assets, DisplayMetrics metrics, - Configuration config) { - mAssets = assets; - mConfiguration.setToDefaults(); - mMetrics.setToDefaults(); - updateConfiguration(config, metrics); - assets.ensureStringBlocks(); - } - - /** - * Return a global shared Resources object that provides access to only - * system resources (no application resources), and is not configured for - * the current screen (can not use dimension units, does not change based - * on orientation, etc). - */ - public static Resources getSystem() { - synchronized (mSync) { - Resources ret = mSystem; - if (ret == null) { - ret = new Resources(); - mSystem = ret; - } - - return ret; - } - } - - /** - * Return the string value associated with a particular resource ID. The - * returned object will be a String if this is a plain string; it will be - * some other type of CharSequence if it is styled. - * {@more} - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return CharSequence The string data associated with the resource, plus - * possibly styled text information. - */ - public CharSequence getText(int id) throws NotFoundException { - CharSequence res = mAssets.getResourceText(id); - if (res != null) { - return res; - } - throw new NotFoundException("String resource ID #0x" - + Integer.toHexString(id)); - } - - /** - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return CharSequence The string data associated with the resource, plus - * possibly styled text information. - */ - public CharSequence getQuantityText(int id, int quantity) throws NotFoundException { - PluralRules rule = getPluralRule(); - CharSequence res = mAssets.getResourceBagText(id, rule.attrForNumber(quantity)); - if (res != null) { - return res; - } - res = mAssets.getResourceBagText(id, PluralRules.ID_OTHER); - if (res != null) { - return res; - } - throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id) - + " quantity=" + quantity - + " item=" + PluralRules.stringForQuantity(rule.quantityForNumber(quantity))); - } - - private PluralRules getPluralRule() { - synchronized (mSync) { - if (mPluralRule == null) { - mPluralRule = PluralRules.ruleForLocale(mConfiguration.locale); - } - return mPluralRule; - } - } - - /** - * Return the string value associated with a particular resource ID. It - * will be stripped of any styled text information. - * {@more} - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return String The string data associated with the resource, - * stripped of styled text information. - */ - public String getString(int id) throws NotFoundException { - CharSequence res = getText(id); - if (res != null) { - return res.toString(); - } - throw new NotFoundException("String resource ID #0x" - + Integer.toHexString(id)); - } - - - /** - * Return the string value associated with a particular resource ID, - * substituting the format arguments as defined in {@link java.util.Formatter} - * and {@link java.lang.String#format}. It will be stripped of any styled text - * information. - * {@more} - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @param formatArgs The format arguments that will be used for substitution. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return String The string data associated with the resource, - * stripped of styled text information. - */ - public String getString(int id, Object... formatArgs) throws NotFoundException { - String raw = getString(id); - return String.format(mConfiguration.locale, raw, formatArgs); - } - - /** - * Return the string value associated with a particular resource ID for a particular - * numerical quantity, substituting the format arguments as defined in - * {@link java.util.Formatter} and {@link java.lang.String#format}. It will be - * stripped of any styled text information. - * {@more} - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param quantity The number used to get the correct string for the current language's - * plural rules. - * @param formatArgs The format arguments that will be used for substitution. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return String The string data associated with the resource, - * stripped of styled text information. - */ - public String getQuantityString(int id, int quantity, Object... formatArgs) - throws NotFoundException { - String raw = getQuantityText(id, quantity).toString(); - return String.format(mConfiguration.locale, raw, formatArgs); - } - - /** - * Return the string value associated with a particular resource ID for a particular - * numerical quantity. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param quantity The number used to get the correct string for the current language's - * plural rules. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return String The string data associated with the resource, - * stripped of styled text information. - */ - public String getQuantityString(int id, int quantity) throws NotFoundException { - return getQuantityText(id, quantity).toString(); - } - - /** - * Return the string value associated with a particular resource ID. The - * returned object will be a String if this is a plain string; it will be - * some other type of CharSequence if it is styled. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @param def The default CharSequence to return. - * - * @return CharSequence The string data associated with the resource, plus - * possibly styled text information, or def if id is 0 or not found. - */ - public CharSequence getText(int id, CharSequence def) { - CharSequence res = id != 0 ? mAssets.getResourceText(id) : null; - return res != null ? res : def; - } - - /** - * Return the styled text array associated with a particular resource ID. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return The styled text array associated with the resource. - */ - public CharSequence[] getTextArray(int id) throws NotFoundException { - CharSequence[] res = mAssets.getResourceTextArray(id); - if (res != null) { - return res; - } - throw new NotFoundException("Text array resource ID #0x" - + Integer.toHexString(id)); - } - - /** - * Return the string array associated with a particular resource ID. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return The string array associated with the resource. - */ - public String[] getStringArray(int id) throws NotFoundException { - String[] res = mAssets.getResourceStringArray(id); - if (res != null) { - return res; - } - throw new NotFoundException("String array resource ID #0x" - + Integer.toHexString(id)); - } - - /** - * Return the int array associated with a particular resource ID. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return The int array associated with the resource. - */ - public int[] getIntArray(int id) throws NotFoundException { - int[] res = mAssets.getArrayIntResource(id); - if (res != null) { - return res; - } - throw new NotFoundException("Int array resource ID #0x" - + Integer.toHexString(id)); - } - - /** - * Return an array of heterogeneous values. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns a TypedArray holding an array of the array values. - * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} - * when done with it. - */ - public TypedArray obtainTypedArray(int id) throws NotFoundException { - int len = mAssets.getArraySize(id); - if (len < 0) { - throw new NotFoundException("Array resource ID #0x" - + Integer.toHexString(id)); - } - - TypedArray array = getCachedStyledAttributes(len); - array.mLength = mAssets.retrieveArray(id, array.mData); - array.mIndices[0] = 0; - - return array; - } - - /** - * Retrieve a dimensional for a particular resource ID. Unit - * conversions are based on the current {@link DisplayMetrics} associated - * with the resources. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @return Resource dimension value multiplied by the appropriate - * metric. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getDimensionPixelOffset - * @see #getDimensionPixelSize - */ - public float getDimension(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimension(value.data, mMetrics); - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Retrieve a dimensional for a particular resource ID for use - * as an offset in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for you. An offset conversion involves simply - * truncating the base value to an integer. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @return Resource dimension value multiplied by the appropriate - * metric and truncated to integer pixels. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getDimension - * @see #getDimensionPixelSize - */ - public int getDimensionPixelOffset(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelOffset( - value.data, mMetrics); - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Retrieve a dimensional for a particular resource ID for use - * as a size in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for use as a size. A size conversion involves - * rounding the base value, and ensuring that a non-zero base value - * is at least one pixel in size. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @return Resource dimension value multiplied by the appropriate - * metric and truncated to integer pixels. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getDimension - * @see #getDimensionPixelOffset - */ - public int getDimensionPixelSize(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelSize( - value.data, mMetrics); - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Retrieve a fractional unit for a particular resource ID. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param base The base value of this fraction. In other words, a - * standard fraction is multiplied by this value. - * @param pbase The parent base value of this fraction. In other - * words, a parent fraction (nn%p) is multiplied by this - * value. - * - * @return Attribute fractional value multiplied by the appropriate - * base value. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - */ - public float getFraction(int id, int base, int pbase) { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type == TypedValue.TYPE_FRACTION) { - return TypedValue.complexToFraction(value.data, base, pbase); - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Return a drawable object associated with a particular resource ID. - * Various types of objects will be returned depending on the underlying - * resource -- for example, a solid color, PNG image, scalable image, etc. - * The Drawable API hides these implementation details. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Drawable An object that can be used to draw this resource. - */ - public Drawable getDrawable(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - return loadDrawable(value, id); - } - } - - /** - * Return a movie object associated with the particular resource ID. - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - */ - public Movie getMovie(int id) throws NotFoundException { - InputStream is = openRawResource(id); - Movie movie = Movie.decodeStream(is); - try { - is.close(); - } - catch (java.io.IOException e) { - // don't care, since the return value is valid - } - return movie; - } - - /** - * Return a color integer associated with a particular resource ID. - * If the resource holds a complex - * {@link android.content.res.ColorStateList}, then the default color from - * the set is returned. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns a single color value in the form 0xAARRGGBB. - */ - public int getColor(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type >= TypedValue.TYPE_FIRST_INT - && value.type <= TypedValue.TYPE_LAST_INT) { - return value.data; - } else if (value.type == TypedValue.TYPE_STRING) { - ColorStateList csl = loadColorStateList(mTmpValue, id); - return csl.getDefaultColor(); - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Return a color state list associated with a particular resource ID. The - * resource may contain either a single raw color value, or a complex - * {@link android.content.res.ColorStateList} holding multiple possible colors. - * - * @param id The desired resource identifier of a {@link ColorStateList}, - * as generated by the aapt tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns a ColorStateList object containing either a single - * solid color or multiple colors that can be selected based on a state. - */ - public ColorStateList getColorStateList(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - return loadColorStateList(value, id); - } - } - - /** - * Return a boolean associated with a particular resource ID. This can be - * used with any integral resource value, and will return true if it is - * non-zero. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns the boolean value contained in the resource. - */ - public boolean getBoolean(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type >= TypedValue.TYPE_FIRST_INT - && value.type <= TypedValue.TYPE_LAST_INT) { - return value.data != 0; - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Return an integer associated with a particular resource ID. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns the integer value contained in the resource. - */ - public int getInteger(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type >= TypedValue.TYPE_FIRST_INT - && value.type <= TypedValue.TYPE_LAST_INT) { - return value.data; - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /** - * Return an XmlResourceParser through which you can read a view layout - * description for the given resource ID. This parser has limited - * functionality -- in particular, you can't change its input, and only - * the high-level events are available. - * - * <p>This function is really a simple wrapper for calling - * {@link #getXml} with a layout resource. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return A new parser object through which you can read - * the XML data. - * - * @see #getXml - */ - public XmlResourceParser getLayout(int id) throws NotFoundException { - return loadXmlResourceParser(id, "layout"); - } - - /** - * Return an XmlResourceParser through which you can read an animation - * description for the given resource ID. This parser has limited - * functionality -- in particular, you can't change its input, and only - * the high-level events are available. - * - * <p>This function is really a simple wrapper for calling - * {@link #getXml} with an animation resource. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return A new parser object through which you can read - * the XML data. - * - * @see #getXml - */ - public XmlResourceParser getAnimation(int id) throws NotFoundException { - return loadXmlResourceParser(id, "anim"); - } - - /** - * Return an XmlResourceParser through which you can read a generic XML - * resource for the given resource ID. - * - * <p>The XmlPullParser implementation returned here has some limited - * functionality. In particular, you can't change its input, and only - * high-level parsing events are available (since the document was - * pre-parsed for you at build time, which involved merging text and - * stripping comments). - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return A new parser object through which you can read - * the XML data. - * - * @see android.util.AttributeSet - */ - public XmlResourceParser getXml(int id) throws NotFoundException { - return loadXmlResourceParser(id, "xml"); - } - - /** - * Open a data stream for reading a raw resource. This can only be used - * with resources whose value is the name of an asset files -- that is, it can be - * used to open drawable, sound, and raw resources; it will fail on string - * and color resources. - * - * @param id The resource identifier to open, as generated by the appt - * tool. - * - * @return InputStream Access to the resource data. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - */ - public InputStream openRawResource(int id) throws NotFoundException { - synchronized (mTmpValue) { - return openRawResource(id, mTmpValue); - } - } - - /** - * Open a data stream for reading a raw resource. This can only be used - * with resources whose value is the name of an asset files -- that is, it can be - * used to open drawable, sound, and raw resources; it will fail on string - * and color resources. - * - * @param id The resource identifier to open, as generated by the appt tool. - * @param value The TypedValue object to hold the resource information. - * - * @return InputStream Access to the resource data. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @hide Pending API council approval - */ - public InputStream openRawResource(int id, TypedValue value) throws NotFoundException { - getValue(id, value, true); - - try { - return mAssets.openNonAsset(value.assetCookie, value.string.toString(), - AssetManager.ACCESS_STREAMING); - } catch (Exception e) { - NotFoundException rnf = new NotFoundException("File " + value.string.toString() + - " from drawable resource ID #0x" + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - } - - /** - * Open a file descriptor for reading a raw resource. This can only be used - * with resources whose value is the name of an asset files -- that is, it can be - * used to open drawable, sound, and raw resources; it will fail on string - * and color resources. - * - * <p>This function only works for resources that are stored in the package - * as uncompressed data, which typically includes things like mp3 files - * and png images. - * - * @param id The resource identifier to open, as generated by the appt - * tool. - * - * @return AssetFileDescriptor A new file descriptor you can use to read - * the resource. This includes the file descriptor itself, as well as the - * offset and length of data where the resource appears in the file. A - * null is returned if the file exists but is compressed. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - */ - public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - - try { - return mAssets.openNonAssetFd( - value.assetCookie, value.string.toString()); - } catch (Exception e) { - NotFoundException rnf = new NotFoundException( - "File " + value.string.toString() - + " from drawable resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - - } - } - - /** - * Return the raw data associated with a particular resource ID. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param outValue Object in which to place the resource data. - * @param resolveRefs If true, a resource that is a reference to another - * resource will be followed so that you receive the - * actual final resource data. If false, the TypedValue - * will be filled in with the reference itself. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - */ - public void getValue(int id, TypedValue outValue, boolean resolveRefs) - throws NotFoundException { - boolean found = mAssets.getResourceValue(id, outValue, resolveRefs); - if (found) { - return; - } - throw new NotFoundException("Resource ID #0x" - + Integer.toHexString(id)); - } - - /** - * Return the raw data associated with a particular resource ID. - * See getIdentifier() for information on how names are mapped to resource - * IDs, and getString(int) for information on how string resources are - * retrieved. - * - * <p>Note: use of this function is discouraged. It is much more - * efficient to retrieve resources by identifier than by name. - * - * @param name The name of the desired resource. This is passed to - * getIdentifier() with a default type of "string". - * @param outValue Object in which to place the resource data. - * @param resolveRefs If true, a resource that is a reference to another - * resource will be followed so that you receive the - * actual final resource data. If false, the TypedValue - * will be filled in with the reference itself. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - */ - public void getValue(String name, TypedValue outValue, boolean resolveRefs) - throws NotFoundException { - int id = getIdentifier(name, "string", null); - if (id != 0) { - getValue(id, outValue, resolveRefs); - return; - } - throw new NotFoundException("String resource name " + name); - } - - /** - * This class holds the current attribute values for a particular theme. - * In other words, a Theme is a set of values for resource attributes; - * these are used in conjunction with {@link TypedArray} - * to resolve the final value for an attribute. - * - * <p>The Theme's attributes come into play in two ways: (1) a styled - * attribute can explicit reference a value in the theme through the - * "?themeAttribute" syntax; (2) if no value has been defined for a - * particular styled attribute, as a last resort we will try to find that - * attribute's value in the Theme. - * - * <p>You will normally use the {@link #obtainStyledAttributes} APIs to - * retrieve XML attributes with style and theme information applied. - */ - public final class Theme { - /** - * Place new attribute values into the theme. The style resource - * specified by <var>resid</var> will be retrieved from this Theme's - * resources, its values placed into the Theme object. - * - * <p>The semantics of this function depends on the <var>force</var> - * argument: If false, only values that are not already defined in - * the theme will be copied from the system resource; otherwise, if - * any of the style's attributes are already defined in the theme, the - * current values in the theme will be overwritten. - * - * @param resid The resource ID of a style resource from which to - * obtain attribute values. - * @param force If true, values in the style resource will always be - * used in the theme; otherwise, they will only be used - * if not already defined in the theme. - */ - public void applyStyle(int resid, boolean force) { - AssetManager.applyThemeStyle(mTheme, resid, force); - } - - /** - * Set this theme to hold the same contents as the theme - * <var>other</var>. If both of these themes are from the same - * Resources object, they will be identical after this function - * returns. If they are from different Resources, only the resources - * they have in common will be set in this theme. - * - * @param other The existing Theme to copy from. - */ - public void setTo(Theme other) { - AssetManager.copyTheme(mTheme, other.mTheme); - } - - /** - * Return a StyledAttributes holding the values defined by - * <var>Theme</var> which are listed in <var>attrs</var>. - * - * <p>Be sure to call StyledAttributes.recycle() when you are done with - * the array. - * - * @param attrs The desired attributes. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns a TypedArray holding an array of the attribute values. - * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} - * when done with it. - * - * @see Resources#obtainAttributes - * @see #obtainStyledAttributes(int, int[]) - * @see #obtainStyledAttributes(AttributeSet, int[], int, int) - */ - public TypedArray obtainStyledAttributes(int[] attrs) { - int len = attrs.length; - TypedArray array = getCachedStyledAttributes(len); - array.mRsrcs = attrs; - AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, - array.mData, array.mIndices); - return array; - } - - /** - * Return a StyledAttributes holding the values defined by the style - * resource <var>resid</var> which are listed in <var>attrs</var>. - * - * <p>Be sure to call StyledAttributes.recycle() when you are done with - * the array. - * - * @param resid The desired style resource. - * @param attrs The desired attributes in the style. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @return Returns a TypedArray holding an array of the attribute values. - * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} - * when done with it. - * - * @see Resources#obtainAttributes - * @see #obtainStyledAttributes(int[]) - * @see #obtainStyledAttributes(AttributeSet, int[], int, int) - */ - public TypedArray obtainStyledAttributes(int resid, int[] attrs) - throws NotFoundException { - int len = attrs.length; - TypedArray array = getCachedStyledAttributes(len); - array.mRsrcs = attrs; - - AssetManager.applyStyle(mTheme, 0, resid, 0, attrs, - array.mData, array.mIndices); - if (false) { - int[] data = array.mData; - - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("Attributes:"); - String s = " Attrs:"; - int i; - for (i=0; i<attrs.length; i++) { - s = s + " 0x" + Integer.toHexString(attrs[i]); - } - System.out.println(s); - s = " Found:"; - TypedValue value = new TypedValue(); - for (i=0; i<attrs.length; i++) { - int d = i*AssetManager.STYLE_NUM_ENTRIES; - value.type = data[d+AssetManager.STYLE_TYPE]; - value.data = data[d+AssetManager.STYLE_DATA]; - value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE]; - value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID]; - s = s + " 0x" + Integer.toHexString(attrs[i]) - + "=" + value; - } - System.out.println(s); - } - return array; - } - - /** - * Return a StyledAttributes holding the attribute values in - * <var>set</var> - * that are listed in <var>attrs</var>. In addition, if the given - * AttributeSet specifies a style class (through the "style" attribute), - * that style will be applied on top of the base attributes it defines. - * - * <p>Be sure to call StyledAttributes.recycle() when you are done with - * the array. - * - * <p>When determining the final value of a particular attribute, there - * are four inputs that come into play:</p> - * - * <ol> - * <li> Any attribute values in the given AttributeSet. - * <li> The style resource specified in the AttributeSet (named - * "style"). - * <li> The default style specified by <var>defStyleAttr</var> and - * <var>defStyleRes</var> - * <li> The base values in this theme. - * </ol> - * - * <p>Each of these inputs is considered in-order, with the first listed - * taking precedence over the following ones. In other words, if in the - * AttributeSet you have supplied <code><Button - * textColor="#ff000000"></code>, then the button's text will - * <em>always</em> be black, regardless of what is specified in any of - * the styles. - * - * @param set The base set of attribute values. May be null. - * @param attrs The desired attributes to be retrieved. - * @param defStyleAttr An attribute in the current theme that contains a - * reference to a style resource that supplies - * defaults values for the StyledAttributes. Can be - * 0 to not look for defaults. - * @param defStyleRes A resource identifier of a style resource that - * supplies default values for the StyledAttributes, - * used only if defStyleAttr is 0 or can not be found - * in the theme. Can be 0 to not look for defaults. - * - * @return Returns a TypedArray holding an array of the attribute values. - * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} - * when done with it. - * - * @see Resources#obtainAttributes - * @see #obtainStyledAttributes(int[]) - * @see #obtainStyledAttributes(int, int[]) - */ - public TypedArray obtainStyledAttributes(AttributeSet set, - int[] attrs, int defStyleAttr, int defStyleRes) { - int len = attrs.length; - TypedArray array = getCachedStyledAttributes(len); - - // XXX note that for now we only work with compiled XML files. - // To support generic XML files we will need to manually parse - // out the attributes from the XML file (applying type information - // contained in the resources and such). - XmlBlock.Parser parser = (XmlBlock.Parser)set; - AssetManager.applyStyle( - mTheme, defStyleAttr, defStyleRes, - parser != null ? parser.mParseState : 0, attrs, - array.mData, array.mIndices); - - array.mRsrcs = attrs; - array.mXml = parser; - - if (false) { - int[] data = array.mData; - - System.out.println("Attributes:"); - String s = " Attrs:"; - int i; - for (i=0; i<set.getAttributeCount(); i++) { - s = s + " " + set.getAttributeName(i); - int id = set.getAttributeNameResource(i); - if (id != 0) { - s = s + "(0x" + Integer.toHexString(id) + ")"; - } - s = s + "=" + set.getAttributeValue(i); - } - System.out.println(s); - s = " Found:"; - TypedValue value = new TypedValue(); - for (i=0; i<attrs.length; i++) { - int d = i*AssetManager.STYLE_NUM_ENTRIES; - value.type = data[d+AssetManager.STYLE_TYPE]; - value.data = data[d+AssetManager.STYLE_DATA]; - value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE]; - value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID]; - s = s + " 0x" + Integer.toHexString(attrs[i]) - + "=" + value; - } - System.out.println(s); - } - - return array; - } - - /** - * Retrieve the value of an attribute in the Theme. The contents of - * <var>outValue</var> are ultimately filled in by - * {@link Resources#getValue}. - * - * @param resid The resource identifier of the desired theme - * attribute. - * @param outValue Filled in with the ultimate resource value supplied - * by the attribute. - * @param resolveRefs If true, resource references will be walked; if - * false, <var>outValue</var> may be a - * TYPE_REFERENCE. In either case, it will never - * be a TYPE_ATTRIBUTE. - * - * @return boolean Returns true if the attribute was found and - * <var>outValue</var> is valid, else false. - */ - public boolean resolveAttribute(int resid, TypedValue outValue, - boolean resolveRefs) { - boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs); - if (false) { - System.out.println( - "resolveAttribute #" + Integer.toHexString(resid) - + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type) - + ", data=0x" + Integer.toHexString(outValue.data)); - } - return got; - } - - /** - * Print contents of this theme out to the log. For debugging only. - * - * @param priority The log priority to use. - * @param tag The log tag to use. - * @param prefix Text to prefix each line printed. - */ - public void dump(int priority, String tag, String prefix) { - AssetManager.dumpTheme(mTheme, priority, tag, prefix); - } - - protected void finalize() throws Throwable { - super.finalize(); - mAssets.releaseTheme(mTheme); - } - - /*package*/ Theme() { - mAssets = Resources.this.mAssets; - mTheme = mAssets.createTheme(); - } - - private final AssetManager mAssets; - private final int mTheme; - } - - /** - * Generate a new Theme object for this set of Resources. It initially - * starts out empty. - * - * @return Theme The newly created Theme container. - */ - public final Theme newTheme() { - return new Theme(); - } - - /** - * Retrieve a set of basic attribute values from an AttributeSet, not - * performing styling of them using a theme and/or style resources. - * - * @param set The current attribute values to retrieve. - * @param attrs The specific attributes to be retrieved. - * @return Returns a TypedArray holding an array of the attribute values. - * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} - * when done with it. - * - * @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int) - */ - public TypedArray obtainAttributes(AttributeSet set, int[] attrs) { - int len = attrs.length; - TypedArray array = getCachedStyledAttributes(len); - - // XXX note that for now we only work with compiled XML files. - // To support generic XML files we will need to manually parse - // out the attributes from the XML file (applying type information - // contained in the resources and such). - XmlBlock.Parser parser = (XmlBlock.Parser)set; - mAssets.retrieveAttributes(parser.mParseState, attrs, - array.mData, array.mIndices); - - array.mRsrcs = attrs; - array.mXml = parser; - - return array; - } - - /** - * Store the newly updated configuration. - */ - public void updateConfiguration(Configuration config, - DisplayMetrics metrics) { - synchronized (mTmpValue) { - int configChanges = 0xfffffff; - if (config != null) { - configChanges = mConfiguration.updateFrom(config); - } - if (metrics != null) { - mMetrics.setTo(metrics); - } - mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; - String locale = null; - if (mConfiguration.locale != null) { - locale = mConfiguration.locale.getLanguage(); - if (mConfiguration.locale.getCountry() != null) { - locale += "-" + mConfiguration.locale.getCountry(); - } - } - int width, height; - if (mMetrics.widthPixels >= mMetrics.heightPixels) { - width = mMetrics.widthPixels; - height = mMetrics.heightPixels; - } else { - width = mMetrics.heightPixels; - height = mMetrics.widthPixels; - } - int keyboardHidden = mConfiguration.keyboardHidden; - if (keyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO - && mConfiguration.hardKeyboardHidden - == Configuration.HARDKEYBOARDHIDDEN_YES) { - keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT; - } - mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, - locale, mConfiguration.orientation, - mConfiguration.touchscreen, - (int)(mMetrics.density*160), mConfiguration.keyboard, - keyboardHidden, mConfiguration.navigation, width, height, - sSdkVersion); - int N = mDrawableCache.size(); - if (DEBUG_CONFIG) { - Log.d(TAG, "Cleaning up drawables config changes: 0x" - + Integer.toHexString(configChanges)); - } - for (int i=0; i<N; i++) { - WeakReference<Drawable.ConstantState> ref = mDrawableCache.valueAt(i); - if (ref != null) { - Drawable.ConstantState cs = ref.get(); - if (cs != null) { - if (Configuration.needNewResources( - configChanges, cs.getChangingConfigurations())) { - if (DEBUG_CONFIG) { - Log.d(TAG, "FLUSHING #0x" - + Integer.toHexString(mDrawableCache.keyAt(i)) - + " / " + cs + " with changes: 0x" - + Integer.toHexString(cs.getChangingConfigurations())); - } - mDrawableCache.setValueAt(i, null); - } else if (DEBUG_CONFIG) { - Log.d(TAG, "(Keeping #0x" - + Integer.toHexString(mDrawableCache.keyAt(i)) - + " / " + cs + " with changes: 0x" - + Integer.toHexString(cs.getChangingConfigurations()) - + ")"); - } - } - } - } - mDrawableCache.clear(); - mColorStateListCache.clear(); - flushLayoutCache(); - } - synchronized (mSync) { - if (mPluralRule != null) { - mPluralRule = PluralRules.ruleForLocale(config.locale); - } - } - } - - /** - * Update the system resources configuration if they have previously - * been initialized. - * - * @hide - */ - public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) { - if (mSystem != null) { - mSystem.updateConfiguration(config, metrics); - //Log.i(TAG, "Updated system resources " + mSystem - // + ": " + mSystem.getConfiguration()); - } - } - - /** - * Return the current display metrics that are in effect for this resource - * object. The returned object should be treated as read-only. - * - * @return The resource's current display metrics. - */ - public DisplayMetrics getDisplayMetrics() { - return mMetrics; - } - - /** - * Return the current configuration that is in effect for this resource - * object. The returned object should be treated as read-only. - * - * @return The resource's current configuration. - */ - public Configuration getConfiguration() { - return mConfiguration; - } - - /** - * Return a resource identifier for the given resource name. A fully - * qualified resource name is of the form "package:type/entry". The first - * two components (package and type) are optional if defType and - * defPackage, respectively, are specified here. - * - * <p>Note: use of this function is discouraged. It is much more - * efficient to retrieve resources by identifier than by name. - * - * @param name The name of the desired resource. - * @param defType Optional default resource type to find, if "type/" is - * not included in the name. Can be null to require an - * explicit type. - * @param defPackage Optional default package to find, if "package:" is - * not included in the name. Can be null to require an - * explicit package. - * - * @return int The associated resource identifier. Returns 0 if no such - * resource was found. (0 is not a valid resource ID.) - */ - public int getIdentifier(String name, String defType, String defPackage) { - try { - return Integer.parseInt(name); - } catch (Exception e) { - } - return mAssets.getResourceIdentifier(name, defType, defPackage); - } - - /** - * Return the full name for a given resource identifier. This name is - * a single string of the form "package:type/entry". - * - * @param resid The resource identifier whose name is to be retrieved. - * - * @return A string holding the name of the resource. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getResourcePackageName - * @see #getResourceTypeName - * @see #getResourceEntryName - */ - public String getResourceName(int resid) throws NotFoundException { - String str = mAssets.getResourceName(resid); - if (str != null) return str; - throw new NotFoundException("Unable to find resource ID #0x" - + Integer.toHexString(resid)); - } - - /** - * Return the package name for a given resource identifier. - * - * @param resid The resource identifier whose package name is to be - * retrieved. - * - * @return A string holding the package name of the resource. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getResourceName - */ - public String getResourcePackageName(int resid) throws NotFoundException { - String str = mAssets.getResourcePackageName(resid); - if (str != null) return str; - throw new NotFoundException("Unable to find resource ID #0x" - + Integer.toHexString(resid)); - } - - /** - * Return the type name for a given resource identifier. - * - * @param resid The resource identifier whose type name is to be - * retrieved. - * - * @return A string holding the type name of the resource. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getResourceName - */ - public String getResourceTypeName(int resid) throws NotFoundException { - String str = mAssets.getResourceTypeName(resid); - if (str != null) return str; - throw new NotFoundException("Unable to find resource ID #0x" - + Integer.toHexString(resid)); - } - - /** - * Return the entry name for a given resource identifier. - * - * @param resid The resource identifier whose entry name is to be - * retrieved. - * - * @return A string holding the entry name of the resource. - * - * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * - * @see #getResourceName - */ - public String getResourceEntryName(int resid) throws NotFoundException { - String str = mAssets.getResourceEntryName(resid); - if (str != null) return str; - throw new NotFoundException("Unable to find resource ID #0x" - + Integer.toHexString(resid)); - } - - /** - * Parse a series of {@link android.R.styleable#Extra <extra>} tags from - * an XML file. You call this when you are at the parent tag of the - * extra tags, and it return once all of the child tags have been parsed. - * This will call {@link #parseBundleExtra} for each extra tag encountered. - * - * @param parser The parser from which to retrieve the extras. - * @param outBundle A Bundle in which to place all parsed extras. - * @throws XmlPullParserException - * @throws IOException - */ - public void parseBundleExtras(XmlResourceParser parser, Bundle outBundle) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - String nodeName = parser.getName(); - if (nodeName.equals("extra")) { - parseBundleExtra("extra", parser, outBundle); - XmlUtils.skipCurrentTag(parser); - - } else { - XmlUtils.skipCurrentTag(parser); - } - } - } - - /** - * Parse a name/value pair out of an XML tag holding that data. The - * AttributeSet must be holding the data defined by - * {@link android.R.styleable#Extra}. The following value types are supported: - * <ul> - * <li> {@link TypedValue#TYPE_STRING}: - * {@link Bundle#putCharSequence Bundle.putCharSequence()} - * <li> {@link TypedValue#TYPE_INT_BOOLEAN}: - * {@link Bundle#putCharSequence Bundle.putBoolean()} - * <li> {@link TypedValue#TYPE_FIRST_INT}-{@link TypedValue#TYPE_LAST_INT}: - * {@link Bundle#putCharSequence Bundle.putBoolean()} - * <li> {@link TypedValue#TYPE_FLOAT}: - * {@link Bundle#putCharSequence Bundle.putFloat()} - * </ul> - * - * @param tagName The name of the tag these attributes come from; this is - * only used for reporting error messages. - * @param attrs The attributes from which to retrieve the name/value pair. - * @param outBundle The Bundle in which to place the parsed value. - * @throws XmlPullParserException If the attributes are not valid. - */ - public void parseBundleExtra(String tagName, AttributeSet attrs, - Bundle outBundle) throws XmlPullParserException { - TypedArray sa = obtainAttributes(attrs, - com.android.internal.R.styleable.Extra); - - String name = sa.getString( - com.android.internal.R.styleable.Extra_name); - if (name == null) { - sa.recycle(); - throw new XmlPullParserException("<" + tagName - + "> requires an android:name attribute at " - + attrs.getPositionDescription()); - } - - TypedValue v = sa.peekValue( - com.android.internal.R.styleable.Extra_value); - if (v != null) { - if (v.type == TypedValue.TYPE_STRING) { - CharSequence cs = v.coerceToString(); - outBundle.putCharSequence(name, cs); - } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { - outBundle.putBoolean(name, v.data != 0); - } else if (v.type >= TypedValue.TYPE_FIRST_INT - && v.type <= TypedValue.TYPE_LAST_INT) { - outBundle.putInt(name, v.data); - } else if (v.type == TypedValue.TYPE_FLOAT) { - outBundle.putFloat(name, v.getFloat()); - } else { - sa.recycle(); - throw new XmlPullParserException("<" + tagName - + "> only supports string, integer, float, color, and boolean at " - + attrs.getPositionDescription()); - } - } else { - sa.recycle(); - throw new XmlPullParserException("<" + tagName - + "> requires an android:value or android:resource attribute at " - + attrs.getPositionDescription()); - } - - sa.recycle(); - } - - /** - * Retrieve underlying AssetManager storage for these resources. - */ - public final AssetManager getAssets() { - return mAssets; - } - - /** - * Call this to remove all cached loaded layout resources from the - * Resources object. Only intended for use with performance testing - * tools. - */ - public final void flushLayoutCache() { - synchronized (mCachedXmlBlockIds) { - // First see if this block is in our cache. - final int num = mCachedXmlBlockIds.length; - for (int i=0; i<num; i++) { - mCachedXmlBlockIds[i] = -0; - XmlBlock oldBlock = mCachedXmlBlocks[i]; - if (oldBlock != null) { - oldBlock.close(); - } - mCachedXmlBlocks[i] = null; - } - } - } - - /** - * Start preloading of resource data using this Resources object. Only - * for use by the zygote process for loading common system resources. - * {@hide} - */ - public final void startPreloading() { - synchronized (mSync) { - if (mPreloaded) { - throw new IllegalStateException("Resources already preloaded"); - } - mPreloaded = true; - mPreloading = true; - } - } - - /** - * Called by zygote when it is done preloading resources, to change back - * to normal Resources operation. - */ - public final void finishPreloading() { - if (mPreloading) { - mPreloading = false; - flushLayoutCache(); - } - } - - /*package*/ Drawable loadDrawable(TypedValue value, int id) - throws NotFoundException { - if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT - && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { - // Should we be caching these? If we use constant colors much - // at all, most likely... - //System.out.println("Creating drawable for color: #" + - // Integer.toHexString(value.data)); - Drawable dr = new ColorDrawable(value.data); - dr.setChangingConfigurations(value.changingConfigurations); - return dr; - } - - final int key = (value.assetCookie<<24)|value.data; - Drawable dr = getCachedDrawable(key); - //System.out.println("Cached drawable @ #" + - // Integer.toHexString(key.intValue()) + ": " + dr); - if (dr != null) { - return dr; - } - - Drawable.ConstantState cs = mPreloadedDrawables.get(key); - if (cs != null) { - dr = cs.newDrawable(); - - } else { - if (value.string == null) { - throw new NotFoundException( - "Resource is not a Drawable (color or path): " + value); - } - - String file = value.string.toString(); - - if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie " - + value.assetCookie + ": " + file); - - if (file.endsWith(".xml")) { - try { - XmlResourceParser rp = loadXmlResourceParser( - file, id, value.assetCookie, "drawable"); - dr = Drawable.createFromXml(this, rp); - rp.close(); - } catch (Exception e) { - NotFoundException rnf = new NotFoundException( - "File " + file + " from drawable resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - - } else { - try { - InputStream is = mAssets.openNonAsset( - value.assetCookie, file, AssetManager.ACCESS_BUFFER); - // System.out.println("Opened file " + file + ": " + is); - dr = Drawable.createFromResourceStream(this, value, is, file); - is.close(); - // System.out.println("Created stream: " + dr); - } catch (Exception e) { - NotFoundException rnf = new NotFoundException( - "File " + file + " from drawable resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - } - } - - if (dr != null) { - dr.setChangingConfigurations(value.changingConfigurations); - cs = dr.getConstantState(); - if (cs != null) { - if (mPreloading) { - mPreloadedDrawables.put(key, cs); - } - synchronized (mTmpValue) { - //Log.i(TAG, "Saving cached drawable @ #" + - // Integer.toHexString(key.intValue()) - // + " in " + this + ": " + cs); - mDrawableCache.put( - key, new WeakReference<Drawable.ConstantState>(cs)); - } - } - } - - return dr; - } - - private final Drawable getCachedDrawable(int key) { - synchronized (mTmpValue) { - WeakReference<Drawable.ConstantState> wr = mDrawableCache.get(key); - if (wr != null) { // we have the key - Drawable.ConstantState entry = wr.get(); - if (entry != null) { - //Log.i(TAG, "Returning cached drawable @ #" + - // Integer.toHexString(((Integer)key).intValue()) - // + " in " + this + ": " + entry); - return entry.newDrawable(); - } - else { // our entry has been purged - mDrawableCache.delete(key); - } - } - } - return null; - } - - /*package*/ ColorStateList loadColorStateList(TypedValue value, int id) - throws NotFoundException { - if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT - && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { - return ColorStateList.valueOf(value.data); - } - - final int key = (value.assetCookie<<24)|value.data; - ColorStateList csl = getCachedColorStateList(key); - if (csl != null) { - return csl; - } - - if (value.string == null) { - throw new NotFoundException( - "Resource is not a ColorStateList (color or path): " + value); - } - - String file = value.string.toString(); - - if (file.endsWith(".xml")) { - try { - XmlResourceParser rp = loadXmlResourceParser( - file, id, value.assetCookie, "colorstatelist"); - csl = ColorStateList.createFromXml(this, rp); - rp.close(); - } catch (Exception e) { - NotFoundException rnf = new NotFoundException( - "File " + file + " from color state list resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - } else { - throw new NotFoundException( - "File " + file + " from drawable resource ID #0x" - + Integer.toHexString(id) + ": .xml extension required"); - } - - if (csl != null) { - synchronized (mTmpValue) { - //Log.i(TAG, "Saving cached color state list @ #" + - // Integer.toHexString(key.intValue()) - // + " in " + this + ": " + csl); - mColorStateListCache.put( - key, new WeakReference<ColorStateList>(csl)); - } - } - - return csl; - } - - private ColorStateList getCachedColorStateList(int key) { - synchronized (mTmpValue) { - WeakReference<ColorStateList> wr = mColorStateListCache.get(key); - if (wr != null) { // we have the key - ColorStateList entry = wr.get(); - if (entry != null) { - //Log.i(TAG, "Returning cached color state list @ #" + - // Integer.toHexString(((Integer)key).intValue()) - // + " in " + this + ": " + entry); - return entry; - } - else { // our entry has been purged - mColorStateListCache.delete(key); - } - } - } - return null; - } - - /*package*/ XmlResourceParser loadXmlResourceParser(int id, String type) - throws NotFoundException { - synchronized (mTmpValue) { - TypedValue value = mTmpValue; - getValue(id, value, true); - if (value.type == TypedValue.TYPE_STRING) { - return loadXmlResourceParser(value.string.toString(), id, - value.assetCookie, type); - } - throw new NotFoundException( - "Resource ID #0x" + Integer.toHexString(id) + " type #0x" - + Integer.toHexString(value.type) + " is not valid"); - } - } - - /*package*/ XmlResourceParser loadXmlResourceParser(String file, int id, - int assetCookie, String type) throws NotFoundException { - if (id != 0) { - try { - // These may be compiled... - synchronized (mCachedXmlBlockIds) { - // First see if this block is in our cache. - final int num = mCachedXmlBlockIds.length; - for (int i=0; i<num; i++) { - if (mCachedXmlBlockIds[i] == id) { - //System.out.println("**** REUSING XML BLOCK! id=" - // + id + ", index=" + i); - return mCachedXmlBlocks[i].newParser(); - } - } - - // Not in the cache, create a new block and put it at - // the next slot in the cache. - XmlBlock block = mAssets.openXmlBlockAsset( - assetCookie, file); - if (block != null) { - int pos = mLastCachedXmlBlockIndex+1; - if (pos >= num) pos = 0; - mLastCachedXmlBlockIndex = pos; - XmlBlock oldBlock = mCachedXmlBlocks[pos]; - if (oldBlock != null) { - oldBlock.close(); - } - mCachedXmlBlockIds[pos] = id; - mCachedXmlBlocks[pos] = block; - //System.out.println("**** CACHING NEW XML BLOCK! id=" - // + id + ", index=" + pos); - return block.newParser(); - } - } - } catch (Exception e) { - NotFoundException rnf = new NotFoundException( - "File " + file + " from xml type " + type + " resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - } - - throw new NotFoundException( - "File " + file + " from xml type " + type + " resource ID #0x" - + Integer.toHexString(id)); - } - - private TypedArray getCachedStyledAttributes(int len) { - synchronized (mTmpValue) { - TypedArray attrs = mCachedStyledAttributes; - if (attrs != null) { - mCachedStyledAttributes = null; - - attrs.mLength = len; - int fullLen = len * AssetManager.STYLE_NUM_ENTRIES; - if (attrs.mData.length >= fullLen) { - return attrs; - } - attrs.mData = new int[fullLen]; - attrs.mIndices = new int[1+len]; - return attrs; - } - return new TypedArray(this, - new int[len*AssetManager.STYLE_NUM_ENTRIES], - new int[1+len], len); - } - } - - private Resources() { - mAssets = AssetManager.getSystem(); - // NOTE: Intentionally leaving this uninitialized (all values set - // to zero), so that anyone who tries to do something that requires - // metrics will get a very wrong value. - mConfiguration.setToDefaults(); - mMetrics.setToDefaults(); - updateConfiguration(null, null); - mAssets.ensureStringBlocks(); - } -} - diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java deleted file mode 100644 index 3df7708..0000000 --- a/core/java/android/content/res/StringBlock.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (C) 2006 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.res; - -import android.text.*; -import android.text.style.*; -import android.util.Config; -import android.util.Log; -import android.util.SparseArray; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import com.android.internal.util.XmlUtils; - -/** - * Conveniences for retrieving data out of a compiled string resource. - * - * {@hide} - */ -final class StringBlock { - private static final String TAG = "AssetManager"; - private static final boolean localLOGV = Config.LOGV || false; - - private final int mNative; - private final boolean mUseSparse; - private final boolean mOwnsNative; - private CharSequence[] mStrings; - private SparseArray<CharSequence> mSparseStrings; - StyleIDs mStyleIDs = null; - - public StringBlock(byte[] data, boolean useSparse) { - mNative = nativeCreate(data, 0, data.length); - mUseSparse = useSparse; - mOwnsNative = true; - if (localLOGV) Log.v(TAG, "Created string block " + this - + ": " + nativeGetSize(mNative)); - } - - public StringBlock(byte[] data, int offset, int size, boolean useSparse) { - mNative = nativeCreate(data, offset, size); - mUseSparse = useSparse; - mOwnsNative = true; - if (localLOGV) Log.v(TAG, "Created string block " + this - + ": " + nativeGetSize(mNative)); - } - - public CharSequence get(int idx) { - synchronized (this) { - if (mStrings != null) { - CharSequence res = mStrings[idx]; - if (res != null) { - return res; - } - } else if (mSparseStrings != null) { - CharSequence res = mSparseStrings.get(idx); - if (res != null) { - return res; - } - } else { - final int num = nativeGetSize(mNative); - if (mUseSparse && num > 250) { - mSparseStrings = new SparseArray<CharSequence>(); - } else { - mStrings = new CharSequence[num]; - } - } - String str = nativeGetString(mNative, idx); - CharSequence res = str; - int[] style = nativeGetStyle(mNative, idx); - if (localLOGV) Log.v(TAG, "Got string: " + str); - if (localLOGV) Log.v(TAG, "Got styles: " + style); - if (style != null) { - if (mStyleIDs == null) { - mStyleIDs = new StyleIDs(); - mStyleIDs.boldId = nativeIndexOfString(mNative, "b"); - mStyleIDs.italicId = nativeIndexOfString(mNative, "i"); - mStyleIDs.underlineId = nativeIndexOfString(mNative, "u"); - mStyleIDs.ttId = nativeIndexOfString(mNative, "tt"); - mStyleIDs.bigId = nativeIndexOfString(mNative, "big"); - mStyleIDs.smallId = nativeIndexOfString(mNative, "small"); - mStyleIDs.supId = nativeIndexOfString(mNative, "sup"); - mStyleIDs.subId = nativeIndexOfString(mNative, "sub"); - mStyleIDs.strikeId = nativeIndexOfString(mNative, "strike"); - mStyleIDs.listItemId = nativeIndexOfString(mNative, "li"); - mStyleIDs.marqueeId = nativeIndexOfString(mNative, "marquee"); - - if (localLOGV) Log.v(TAG, "BoldId=" + mStyleIDs.boldId - + ", ItalicId=" + mStyleIDs.italicId - + ", UnderlineId=" + mStyleIDs.underlineId); - } - - res = applyStyles(str, style, mStyleIDs); - } - if (mStrings != null) mStrings[idx] = res; - else mSparseStrings.put(idx, res); - return res; - } - } - - protected void finalize() throws Throwable { - if (mOwnsNative) { - nativeDestroy(mNative); - } - } - - static final class StyleIDs { - private int boldId; - private int italicId; - private int underlineId; - private int ttId; - private int bigId; - private int smallId; - private int subId; - private int supId; - private int strikeId; - private int listItemId; - private int marqueeId; - } - - private CharSequence applyStyles(String str, int[] style, StyleIDs ids) { - if (style.length == 0) - return str; - - SpannableString buffer = new SpannableString(str); - int i=0; - while (i < style.length) { - int type = style[i]; - if (localLOGV) Log.v(TAG, "Applying style span id=" + type - + ", start=" + style[i+1] + ", end=" + style[i+2]); - if (type == ids.boldId) { - buffer.setSpan(new StyleSpan(Typeface.BOLD), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.italicId) { - buffer.setSpan(new StyleSpan(Typeface.ITALIC), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.underlineId) { - buffer.setSpan(new UnderlineSpan(), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.ttId) { - buffer.setSpan(new TypefaceSpan("monospace"), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.bigId) { - buffer.setSpan(new RelativeSizeSpan(1.25f), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.smallId) { - buffer.setSpan(new RelativeSizeSpan(0.8f), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.subId) { - buffer.setSpan(new SubscriptSpan(), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.supId) { - buffer.setSpan(new SuperscriptSpan(), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.strikeId) { - buffer.setSpan(new StrikethroughSpan(), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (type == ids.listItemId) { - buffer.setSpan(new BulletSpan(10), - style[i+1], style[i+2]+1, - Spannable.SPAN_PARAGRAPH); - } else if (type == ids.marqueeId) { - buffer.setSpan(TextUtils.TruncateAt.MARQUEE, - style[i+1], style[i+2]+1, - Spannable.SPAN_INCLUSIVE_INCLUSIVE); - } else { - String tag = nativeGetString(mNative, type); - - if (tag.startsWith("font;")) { - String sub; - - sub = subtag(tag, ";height="); - if (sub != null) { - int size = Integer.parseInt(sub); - buffer.setSpan(new Height(size), - style[i+1], style[i+2]+1, - Spannable.SPAN_PARAGRAPH); - } - - sub = subtag(tag, ";size="); - if (sub != null) { - int size = Integer.parseInt(sub); - buffer.setSpan(new AbsoluteSizeSpan(size), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - sub = subtag(tag, ";fgcolor="); - if (sub != null) { - int color = XmlUtils.convertValueToUnsignedInt(sub, -1); - buffer.setSpan(new ForegroundColorSpan(color), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - sub = subtag(tag, ";bgcolor="); - if (sub != null) { - int color = XmlUtils.convertValueToUnsignedInt(sub, -1); - buffer.setSpan(new BackgroundColorSpan(color), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } else if (tag.startsWith("a;")) { - String sub; - - sub = subtag(tag, ";href="); - if (sub != null) { - buffer.setSpan(new URLSpan(sub), - style[i+1], style[i+2]+1, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - } - - i += 3; - } - return new SpannedString(buffer); - } - - private static String subtag(String full, String attribute) { - int start = full.indexOf(attribute); - if (start < 0) { - return null; - } - - start += attribute.length(); - int end = full.indexOf(';', start); - - if (end < 0) { - return full.substring(start); - } else { - return full.substring(start, end); - } - } - - /** - * Forces the text line to be the specified height, shrinking/stretching - * the ascent if possible, or the descent if shrinking the ascent further - * will make the text unreadable. - */ - private static class Height implements LineHeightSpan { - private int mSize; - private static float sProportion = 0; - - public Height(int size) { - mSize = size; - } - - public void chooseHeight(CharSequence text, int start, int end, - int spanstartv, int v, - Paint.FontMetricsInt fm) { - if (fm.bottom - fm.top < mSize) { - fm.top = fm.bottom - mSize; - fm.ascent = fm.ascent - mSize; - } else { - if (sProportion == 0) { - /* - * Calculate what fraction of the nominal ascent - * the height of a capital letter actually is, - * so that we won't reduce the ascent to less than - * that unless we absolutely have to. - */ - - Paint p = new Paint(); - p.setTextSize(100); - Rect r = new Rect(); - p.getTextBounds("ABCDEFG", 0, 7, r); - - sProportion = (r.top) / p.ascent(); - } - - int need = (int) Math.ceil(-fm.top * sProportion); - - if (mSize - fm.descent >= need) { - /* - * It is safe to shrink the ascent this much. - */ - - fm.top = fm.bottom - mSize; - fm.ascent = fm.descent - mSize; - } else if (mSize >= need) { - /* - * We can't show all the descent, but we can at least - * show all the ascent. - */ - - fm.top = fm.ascent = -need; - fm.bottom = fm.descent = fm.top + mSize; - } else { - /* - * Show as much of the ascent as we can, and no descent. - */ - - fm.top = fm.ascent = -mSize; - fm.bottom = fm.descent = 0; - } - } - } - } - - /** - * Create from an existing string block native object. This is - * -extremely- dangerous -- only use it if you absolutely know what you - * are doing! The given native object must exist for the entire lifetime - * of this newly creating StringBlock. - */ - StringBlock(int obj, boolean useSparse) { - mNative = obj; - mUseSparse = useSparse; - mOwnsNative = false; - if (localLOGV) Log.v(TAG, "Created string block " + this - + ": " + nativeGetSize(mNative)); - } - - private static final native int nativeCreate(byte[] data, - int offset, - int size); - private static final native int nativeGetSize(int obj); - private static final native String nativeGetString(int obj, int idx); - private static final native int[] nativeGetStyle(int obj, int idx); - private static final native int nativeIndexOfString(int obj, String str); - private static final native void nativeDestroy(int obj); -} diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java deleted file mode 100644 index 82a57dd..0000000 --- a/core/java/android/content/res/TypedArray.java +++ /dev/null @@ -1,660 +0,0 @@ -package android.content.res; - -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import com.android.internal.util.XmlUtils; - -import java.util.Arrays; - -/** - * Container for an array of values that were retrieved with - * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)} - * or {@link Resources#obtainAttributes}. Be - * sure to call {@link #recycle} when done with them. - * - * The indices used to retrieve values from this structure correspond to - * the positions of the attributes given to obtainStyledAttributes. - */ -public class TypedArray { - private final Resources mResources; - /*package*/ XmlBlock.Parser mXml; - /*package*/ int[] mRsrcs; - /*package*/ int[] mData; - /*package*/ int[] mIndices; - /*package*/ int mLength; - private TypedValue mValue = new TypedValue(); - - /** - * Return the number of values in this array. - */ - public int length() { - return mLength; - } - - /** - * Return the number of indices in the array that actually have data. - */ - public int getIndexCount() { - return mIndices[0]; - } - - /** - * Return an index in the array that has data. - * - * @param at The index you would like to returned, ranging from 0 to - * {@link #getIndexCount()}. - * - * @return The index at the given offset, which can be used with - * {@link #getValue} and related APIs. - */ - public int getIndex(int at) { - return mIndices[1+at]; - } - - /** - * Return the Resources object this array was loaded from. - */ - public Resources getResources() { - return mResources; - } - - /** - * Retrieve the styled string value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return CharSequence holding string data. May be styled. Returns - * null if the attribute is not defined. - */ - public CharSequence getText(int index) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return null; - } else if (type == TypedValue.TYPE_STRING) { - return loadStringValueAt(index); - } - - TypedValue v = mValue; - if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to string: " + v); - return v.coerceToString(); - } - Log.w(Resources.TAG, "getString of bad type: 0x" - + Integer.toHexString(type)); - return null; - } - - /** - * Retrieve the string value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined. - */ - public String getString(int index) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return null; - } else if (type == TypedValue.TYPE_STRING) { - return loadStringValueAt(index).toString(); - } - - TypedValue v = mValue; - if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to string: " + v); - CharSequence cs = v.coerceToString(); - return cs != null ? cs.toString() : null; - } - Log.w(Resources.TAG, "getString of bad type: 0x" - + Integer.toHexString(type)); - return null; - } - - /** - * Retrieve the string value for the attribute at <var>index</var>, but - * only if that string comes from an immediate value in an XML file. That - * is, this does not allow references to string resources, string - * attributes, or conversions from other types. As such, this method - * will only return strings for TypedArray objects that come from - * attributes in an XML file. - * - * @param index Index of attribute to retrieve. - * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined or is not - * an immediate string value. - */ - public String getNonResourceString(int index) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_STRING) { - final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE]; - if (cookie < 0) { - return mXml.getPooledString( - data[index+AssetManager.STYLE_DATA]).toString(); - } - } - return null; - } - - /** - * Retrieve the boolean value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. - * - * @return Attribute boolean value, or defValue if not defined. - */ - public boolean getBoolean(int index, boolean defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { - return data[index+AssetManager.STYLE_DATA] != 0; - } - - TypedValue v = mValue; - if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to boolean: " + v); - return XmlUtils.convertValueToBoolean( - v.coerceToString(), defValue); - } - Log.w(Resources.TAG, "getBoolean of bad type: 0x" - + Integer.toHexString(type)); - return defValue; - } - - /** - * Retrieve the integer value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. - * - * @return Attribute int value, or defValue if not defined. - */ - public int getInt(int index, int defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { - return data[index+AssetManager.STYLE_DATA]; - } - - TypedValue v = mValue; - if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to int: " + v); - return XmlUtils.convertValueToInt( - v.coerceToString(), defValue); - } - Log.w(Resources.TAG, "getInt of bad type: 0x" - + Integer.toHexString(type)); - return defValue; - } - - /** - * Retrieve the float value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return Attribute float value, or defValue if not defined.. - */ - public float getFloat(int index, float defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type == TypedValue.TYPE_FLOAT) { - return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]); - } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { - return data[index+AssetManager.STYLE_DATA]; - } - - TypedValue v = mValue; - if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to float: " + v); - CharSequence str = v.coerceToString(); - if (str != null) { - return Float.parseFloat(str.toString()); - } - } - Log.w(Resources.TAG, "getFloat of bad type: 0x" - + Integer.toHexString(type)); - return defValue; - } - - /** - * Retrieve the color value for the attribute at <var>index</var>. If - * the attribute references a color resource holding a complex - * {@link android.content.res.ColorStateList}, then the default color from - * the set is returned. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute color value, or defValue if not defined. - */ - public int getColor(int index, int defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { - return data[index+AssetManager.STYLE_DATA]; - } else if (type == TypedValue.TYPE_STRING) { - final TypedValue value = mValue; - if (getValueAt(index, value)) { - ColorStateList csl = mResources.loadColorStateList( - value, value.resourceId); - return csl.getDefaultColor(); - } - return defValue; - } - - throw new UnsupportedOperationException("Can't convert to color: type=0x" - + Integer.toHexString(type)); - } - - /** - * Retrieve the ColorStateList for the attribute at <var>index</var>. - * The value may be either a single solid color or a reference to - * a color or complex {@link android.content.res.ColorStateList} description. - * - * @param index Index of attribute to retrieve. - * - * @return ColorStateList for the attribute, or null if not defined. - */ - public ColorStateList getColorStateList(int index) { - final TypedValue value = mValue; - if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { - return mResources.loadColorStateList(value, value.resourceId); - } - return null; - } - - /** - * Retrieve the integer value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute integer value, or defValue if not defined. - */ - public int getInteger(int index, int defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { - return data[index+AssetManager.STYLE_DATA]; - } - - throw new UnsupportedOperationException("Can't convert to integer: type=0x" - + Integer.toHexString(type)); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var>. Unit - * conversions are based on the current {@link DisplayMetrics} - * associated with the resources this {@link TypedArray} object - * came from. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric, or defValue if not defined. - * - * @see #getDimensionPixelOffset - * @see #getDimensionPixelSize - */ - public float getDimension(int index, float defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimension( - data[index+AssetManager.STYLE_DATA], mResources.mMetrics); - } - - throw new UnsupportedOperationException("Can't convert to dimension: type=0x" - + Integer.toHexString(type)); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var> for use - * as an offset in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for you. An offset conversion involves simply - * truncating the base value to an integer. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. - * - * @see #getDimension - * @see #getDimensionPixelSize - */ - public int getDimensionPixelOffset(int index, int defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelOffset( - data[index+AssetManager.STYLE_DATA], mResources.mMetrics); - } - - throw new UnsupportedOperationException("Can't convert to dimension: type=0x" - + Integer.toHexString(type)); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var> for use - * as a size in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for use as a size. A size conversion involves - * rounding the base value, and ensuring that a non-zero base value - * is at least one pixel in size. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. - * - * @see #getDimension - * @see #getDimensionPixelOffset - */ - public int getDimensionPixelSize(int index, int defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelSize( - data[index+AssetManager.STYLE_DATA], mResources.mMetrics); - } - - throw new UnsupportedOperationException("Can't convert to dimension: type=0x" - + Integer.toHexString(type)); - } - - /** - * Special version of {@link #getDimensionPixelSize} for retrieving - * {@link android.view.ViewGroup}'s layout_width and layout_height - * attributes. This is only here for performance reasons; applications - * should use {@link #getDimensionPixelSize}. - * - * @param index Index of the attribute to retrieve. - * @param name Textual name of attribute for error reporting. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels. - */ - public int getLayoutDimension(int index, String name) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { - return data[index+AssetManager.STYLE_DATA]; - } else if (type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelSize( - data[index+AssetManager.STYLE_DATA], mResources.mMetrics); - } - - throw new RuntimeException(getPositionDescription() - + ": You must supply a " + name + " attribute."); - } - - /** - * Retrieve a fractional unit attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param base The base value of this fraction. In other words, a - * standard fraction is multiplied by this value. - * @param pbase The parent base value of this fraction. In other - * words, a parent fraction (nn%p) is multiplied by this - * value. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute fractional value multiplied by the appropriate - * base value, or defValue if not defined. - */ - public float getFraction(int index, int base, int pbase, float defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return defValue; - } else if (type == TypedValue.TYPE_FRACTION) { - return TypedValue.complexToFraction( - data[index+AssetManager.STYLE_DATA], base, pbase); - } - - throw new UnsupportedOperationException("Can't convert to fraction: type=0x" - + Integer.toHexString(type)); - } - - /** - * Retrieve the resource identifier for the attribute at - * <var>index</var>. Note that attribute resource as resolved when - * the overall {@link TypedArray} object is retrieved. As a - * result, this function will return the resource identifier of the - * final resource value that was found, <em>not</em> necessarily the - * original resource that was specified by the attribute. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute resource identifier, or defValue if not defined. - */ - public int getResourceId(int index, int defValue) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) { - final int resid = data[index+AssetManager.STYLE_RESOURCE_ID]; - if (resid != 0) { - return resid; - } - } - return defValue; - } - - /** - * Retrieve the Drawable for the attribute at <var>index</var>. This - * gets the resource ID of the selected attribute, and uses - * {@link Resources#getDrawable Resources.getDrawable} of the owning - * Resources object to retrieve its Drawable. - * - * @param index Index of attribute to retrieve. - * - * @return Drawable for the attribute, or null if not defined. - */ - public Drawable getDrawable(int index) { - final TypedValue value = mValue; - if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { - if (false) { - System.out.println("******************************************************************"); - System.out.println("Got drawable resource: type=" - + value.type - + " str=" + value.string - + " int=0x" + Integer.toHexString(value.data) - + " cookie=" + value.assetCookie); - System.out.println("******************************************************************"); - } - return mResources.loadDrawable(value, value.resourceId); - } - return null; - } - - /** - * Retrieve the CharSequence[] for the attribute at <var>index</var>. - * This gets the resource ID of the selected attribute, and uses - * {@link Resources#getTextArray Resources.getTextArray} of the owning - * Resources object to retrieve its String[]. - * - * @param index Index of attribute to retrieve. - * - * @return CharSequence[] for the attribute, or null if not defined. - */ - public CharSequence[] getTextArray(int index) { - final TypedValue value = mValue; - if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { - if (false) { - System.out.println("******************************************************************"); - System.out.println("Got drawable resource: type=" - + value.type - + " str=" + value.string - + " int=0x" + Integer.toHexString(value.data) - + " cookie=" + value.assetCookie); - System.out.println("******************************************************************"); - } - return mResources.getTextArray(value.resourceId); - } - return null; - } - - /** - * Retrieve the raw TypedValue for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param outValue TypedValue object in which to place the attribute's - * data. - * - * @return Returns true if the value was retrieved, else false. - */ - public boolean getValue(int index, TypedValue outValue) { - return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue); - } - - /** - * Determines whether there is an attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return True if the attribute has a value, false otherwise. - */ - public boolean hasValue(int index) { - index *= AssetManager.STYLE_NUM_ENTRIES; - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - return type != TypedValue.TYPE_NULL; - } - - /** - * Retrieve the raw TypedValue for the attribute at <var>index</var> - * and return a temporary object holding its data. This object is only - * valid until the next call on to {@link TypedArray}. - * - * @param index Index of attribute to retrieve. - * - * @return Returns a TypedValue object if the attribute is defined, - * containing its data; otherwise returns null. (You will not - * receive a TypedValue whose type is TYPE_NULL.) - */ - public TypedValue peekValue(int index) { - final TypedValue value = mValue; - if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { - return value; - } - return null; - } - - /** - * Returns a message about the parser state suitable for printing error messages. - */ - public String getPositionDescription() { - return mXml != null ? mXml.getPositionDescription() : "<internal>"; - } - - /** - * Give back a previously retrieved StyledAttributes, for later re-use. - */ - public void recycle() { - synchronized (mResources.mTmpValue) { - TypedArray cached = mResources.mCachedStyledAttributes; - if (cached == null || cached.mData.length < mData.length) { - mXml = null; - mResources.mCachedStyledAttributes = this; - } - } - } - - private boolean getValueAt(int index, TypedValue outValue) { - final int[] data = mData; - final int type = data[index+AssetManager.STYLE_TYPE]; - if (type == TypedValue.TYPE_NULL) { - return false; - } - outValue.type = type; - outValue.data = data[index+AssetManager.STYLE_DATA]; - outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE]; - outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID]; - outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]; - if (type == TypedValue.TYPE_STRING) { - outValue.string = loadStringValueAt(index); - } - return true; - } - - private CharSequence loadStringValueAt(int index) { - final int[] data = mData; - final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE]; - if (cookie < 0) { - if (mXml != null) { - return mXml.getPooledString( - data[index+AssetManager.STYLE_DATA]); - } - return null; - } - //System.out.println("Getting pooled from: " + v); - return mResources.mAssets.getPooledString( - cookie, data[index+AssetManager.STYLE_DATA]); - } - - /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) { - mResources = resources; - mData = data; - mIndices = indices; - mLength = len; - } - - public String toString() { - return Arrays.toString(mData); - } -}
\ No newline at end of file diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java deleted file mode 100644 index 6336678..0000000 --- a/core/java/android/content/res/XmlBlock.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (C) 2006 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.res; - -import android.util.TypedValue; -import com.android.internal.util.XmlUtils; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; - -/** - * Wrapper around a compiled XML file. - * - * {@hide} - */ -final class XmlBlock { - private static final boolean DEBUG=false; - - public XmlBlock(byte[] data) { - mAssets = null; - mNative = nativeCreate(data, 0, data.length); - mStrings = new StringBlock(nativeGetStringBlock(mNative), false); - } - - public XmlBlock(byte[] data, int offset, int size) { - mAssets = null; - mNative = nativeCreate(data, offset, size); - mStrings = new StringBlock(nativeGetStringBlock(mNative), false); - } - - public void close() { - synchronized (this) { - if (mOpen) { - mOpen = false; - decOpenCountLocked(); - } - } - } - - private void decOpenCountLocked() { - mOpenCount--; - if (mOpenCount == 0) { - nativeDestroy(mNative); - if (mAssets != null) { - mAssets.xmlBlockGone(); - } - } - } - - public XmlResourceParser newParser() { - synchronized (this) { - if (mNative != 0) { - return new Parser(nativeCreateParseState(mNative), this); - } - return null; - } - } - - /*package*/ final class Parser implements XmlResourceParser { - Parser(int parseState, XmlBlock block) { - mParseState = parseState; - mBlock = block; - block.mOpenCount++; - } - - public void setFeature(String name, boolean state) throws XmlPullParserException { - if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) { - return; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) { - return; - } - throw new XmlPullParserException("Unsupported feature: " + name); - } - public boolean getFeature(String name) { - if (FEATURE_PROCESS_NAMESPACES.equals(name)) { - return true; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) { - return true; - } - return false; - } - public void setProperty(String name, Object value) throws XmlPullParserException { - throw new XmlPullParserException("setProperty() not supported"); - } - public Object getProperty(String name) { - return null; - } - public void setInput(Reader in) throws XmlPullParserException { - throw new XmlPullParserException("setInput() not supported"); - } - public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException { - throw new XmlPullParserException("setInput() not supported"); - } - public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException { - throw new XmlPullParserException("defineEntityReplacementText() not supported"); - } - public String getNamespacePrefix(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespacePrefix() not supported"); - } - public String getInputEncoding() { - return null; - } - public String getNamespace(String prefix) { - throw new RuntimeException("getNamespace() not supported"); - } - public int getNamespaceCount(int depth) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceCount() not supported"); - } - public String getPositionDescription() { - return "Binary XML file line #" + getLineNumber(); - } - public String getNamespaceUri(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceUri() not supported"); - } - public int getColumnNumber() { - return -1; - } - public int getDepth() { - return mDepth; - } - public String getText() { - int id = nativeGetText(mParseState); - return id >= 0 ? mStrings.get(id).toString() : null; - } - public int getLineNumber() { - return nativeGetLineNumber(mParseState); - } - public int getEventType() throws XmlPullParserException { - return mEventType; - } - public boolean isWhitespace() throws XmlPullParserException { - // whitespace was stripped by aapt. - return false; - } - public String getPrefix() { - throw new RuntimeException("getPrefix not supported"); - } - public char[] getTextCharacters(int[] holderForStartAndLength) { - String txt = getText(); - char[] chars = null; - if (txt != null) { - holderForStartAndLength[0] = 0; - holderForStartAndLength[1] = txt.length(); - chars = new char[txt.length()]; - txt.getChars(0, txt.length(), chars, 0); - } - return chars; - } - public String getNamespace() { - int id = nativeGetNamespace(mParseState); - return id >= 0 ? mStrings.get(id).toString() : ""; - } - public String getName() { - int id = nativeGetName(mParseState); - return id >= 0 ? mStrings.get(id).toString() : null; - } - public String getAttributeNamespace(int index) { - int id = nativeGetAttributeNamespace(mParseState, index); - if (DEBUG) System.out.println("getAttributeNamespace of " + index + " = " + id); - if (id >= 0) return mStrings.get(id).toString(); - else if (id == -1) return ""; - throw new IndexOutOfBoundsException(String.valueOf(index)); - } - public String getAttributeName(int index) { - int id = nativeGetAttributeName(mParseState, index); - if (DEBUG) System.out.println("getAttributeName of " + index + " = " + id); - if (id >= 0) return mStrings.get(id).toString(); - throw new IndexOutOfBoundsException(String.valueOf(index)); - } - public String getAttributePrefix(int index) { - throw new RuntimeException("getAttributePrefix not supported"); - } - public boolean isEmptyElementTag() throws XmlPullParserException { - // XXX Need to detect this. - return false; - } - public int getAttributeCount() { - return mEventType == START_TAG ? nativeGetAttributeCount(mParseState) : -1; - } - public String getAttributeValue(int index) { - int id = nativeGetAttributeStringValue(mParseState, index); - if (DEBUG) System.out.println("getAttributeValue of " + index + " = " + id); - if (id >= 0) return mStrings.get(id).toString(); - - // May be some other type... check and try to convert if so. - int t = nativeGetAttributeDataType(mParseState, index); - if (t == TypedValue.TYPE_NULL) { - throw new IndexOutOfBoundsException(String.valueOf(index)); - } - - int v = nativeGetAttributeData(mParseState, index); - return TypedValue.coerceToString(t, v); - } - public String getAttributeType(int index) { - return "CDATA"; - } - public boolean isAttributeDefault(int index) { - return false; - } - public int nextToken() throws XmlPullParserException,IOException { - return next(); - } - public String getAttributeValue(String namespace, String name) { - int idx = nativeGetAttributeIndex(mParseState, namespace, name); - if (idx >= 0) { - if (DEBUG) System.out.println("getAttributeName of " - + namespace + ":" + name + " index = " + idx); - if (DEBUG) System.out.println( - "Namespace=" + getAttributeNamespace(idx) - + "Name=" + getAttributeName(idx) - + ", Value=" + getAttributeValue(idx)); - return getAttributeValue(idx); - } - return null; - } - public int next() throws XmlPullParserException,IOException { - if (!mStarted) { - mStarted = true; - return START_DOCUMENT; - } - if (mParseState == 0) { - return END_DOCUMENT; - } - int ev = nativeNext(mParseState); - if (mDecNextDepth) { - mDepth--; - mDecNextDepth = false; - } - switch (ev) { - case START_TAG: - mDepth++; - break; - case END_TAG: - mDecNextDepth = true; - break; - } - mEventType = ev; - if (ev == END_DOCUMENT) { - // Automatically close the parse when we reach the end of - // a document, since the standard XmlPullParser interface - // doesn't have such an API so most clients will leave us - // dangling. - close(); - } - return ev; - } - public void require(int type, String namespace, String name) throws XmlPullParserException,IOException { - if (type != getEventType() - || (namespace != null && !namespace.equals( getNamespace () ) ) - || (name != null && !name.equals( getName() ) ) ) - throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription()); - } - public String nextText() throws XmlPullParserException,IOException { - if(getEventType() != START_TAG) { - throw new XmlPullParserException( - getPositionDescription() - + ": parser must be on START_TAG to read next text", this, null); - } - int eventType = next(); - if(eventType == TEXT) { - String result = getText(); - eventType = next(); - if(eventType != END_TAG) { - throw new XmlPullParserException( - getPositionDescription() - + ": event TEXT it must be immediately followed by END_TAG", this, null); - } - return result; - } else if(eventType == END_TAG) { - return ""; - } else { - throw new XmlPullParserException( - getPositionDescription() - + ": parser must be on START_TAG or TEXT to read text", this, null); - } - } - public int nextTag() throws XmlPullParserException,IOException { - int eventType = next(); - if(eventType == TEXT && isWhitespace()) { // skip whitespace - eventType = next(); - } - if (eventType != START_TAG && eventType != END_TAG) { - throw new XmlPullParserException( - getPositionDescription() - + ": expected start or end tag", this, null); - } - return eventType; - } - - public int getAttributeNameResource(int index) { - return nativeGetAttributeResource(mParseState, index); - } - - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); - if (idx >= 0) { - return getAttributeListValue(idx, options, defaultValue); - } - return defaultValue; - } - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); - if (idx >= 0) { - return getAttributeBooleanValue(idx, defaultValue); - } - return defaultValue; - } - public int getAttributeResourceValue(String namespace, String attribute, - int defaultValue) { - int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); - if (idx >= 0) { - return getAttributeResourceValue(idx, defaultValue); - } - return defaultValue; - } - public int getAttributeIntValue(String namespace, String attribute, - int defaultValue) { - int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); - if (idx >= 0) { - return getAttributeIntValue(idx, defaultValue); - } - return defaultValue; - } - public int getAttributeUnsignedIntValue(String namespace, String attribute, - int defaultValue) - { - int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); - if (idx >= 0) { - return getAttributeUnsignedIntValue(idx, defaultValue); - } - return defaultValue; - } - public float getAttributeFloatValue(String namespace, String attribute, - float defaultValue) { - int idx = nativeGetAttributeIndex(mParseState, namespace, attribute); - if (idx >= 0) { - return getAttributeFloatValue(idx, defaultValue); - } - return defaultValue; - } - - public int getAttributeListValue(int idx, - String[] options, int defaultValue) { - int t = nativeGetAttributeDataType(mParseState, idx); - int v = nativeGetAttributeData(mParseState, idx); - if (t == TypedValue.TYPE_STRING) { - return XmlUtils.convertValueToList( - mStrings.get(v), options, defaultValue); - } - return v; - } - public boolean getAttributeBooleanValue(int idx, - boolean defaultValue) { - int t = nativeGetAttributeDataType(mParseState, idx); - // Note: don't attempt to convert any other types, because - // we want to count on appt doing the conversion for us. - if (t >= TypedValue.TYPE_FIRST_INT && - t <= TypedValue.TYPE_LAST_INT) { - return nativeGetAttributeData(mParseState, idx) != 0; - } - return defaultValue; - } - public int getAttributeResourceValue(int idx, int defaultValue) { - int t = nativeGetAttributeDataType(mParseState, idx); - // Note: don't attempt to convert any other types, because - // we want to count on appt doing the conversion for us. - if (t == TypedValue.TYPE_REFERENCE) { - return nativeGetAttributeData(mParseState, idx); - } - return defaultValue; - } - public int getAttributeIntValue(int idx, int defaultValue) { - int t = nativeGetAttributeDataType(mParseState, idx); - // Note: don't attempt to convert any other types, because - // we want to count on appt doing the conversion for us. - if (t >= TypedValue.TYPE_FIRST_INT && - t <= TypedValue.TYPE_LAST_INT) { - return nativeGetAttributeData(mParseState, idx); - } - return defaultValue; - } - public int getAttributeUnsignedIntValue(int idx, int defaultValue) { - int t = nativeGetAttributeDataType(mParseState, idx); - // Note: don't attempt to convert any other types, because - // we want to count on appt doing the conversion for us. - if (t >= TypedValue.TYPE_FIRST_INT && - t <= TypedValue.TYPE_LAST_INT) { - return nativeGetAttributeData(mParseState, idx); - } - return defaultValue; - } - public float getAttributeFloatValue(int idx, float defaultValue) { - int t = nativeGetAttributeDataType(mParseState, idx); - // Note: don't attempt to convert any other types, because - // we want to count on appt doing the conversion for us. - if (t == TypedValue.TYPE_FLOAT) { - return Float.intBitsToFloat( - nativeGetAttributeData(mParseState, idx)); - } - throw new RuntimeException("not a float!"); - } - - public String getIdAttribute() { - int id = nativeGetIdAttribute(mParseState); - return id >= 0 ? mStrings.get(id).toString() : null; - } - public String getClassAttribute() { - int id = nativeGetClassAttribute(mParseState); - return id >= 0 ? mStrings.get(id).toString() : null; - } - - public int getIdAttributeResourceValue(int defaultValue) { - //todo: create and use native method - return getAttributeResourceValue(null, "id", defaultValue); - } - - public int getStyleAttribute() { - return nativeGetStyleAttribute(mParseState); - } - - public void close() { - synchronized (mBlock) { - if (mParseState != 0) { - nativeDestroyParseState(mParseState); - mParseState = 0; - mBlock.decOpenCountLocked(); - } - } - } - - protected void finalize() throws Throwable { - close(); - } - - /*package*/ final CharSequence getPooledString(int id) { - return mStrings.get(id); - } - - /*package*/ int mParseState; - private final XmlBlock mBlock; - private boolean mStarted = false; - private boolean mDecNextDepth = false; - private int mDepth = 0; - private int mEventType = START_DOCUMENT; - } - - protected void finalize() throws Throwable { - close(); - } - - /** - * Create from an existing xml block native object. This is - * -extremely- dangerous -- only use it if you absolutely know what you - * are doing! The given native object must exist for the entire lifetime - * of this newly creating XmlBlock. - */ - XmlBlock(AssetManager assets, int xmlBlock) { - mAssets = assets; - mNative = xmlBlock; - mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false); - } - - private final AssetManager mAssets; - private final int mNative; - private final StringBlock mStrings; - private boolean mOpen = true; - private int mOpenCount = 1; - - private static final native int nativeCreate(byte[] data, - int offset, - int size); - private static final native int nativeGetStringBlock(int obj); - - private static final native int nativeCreateParseState(int obj); - private static final native int nativeNext(int state); - private static final native int nativeGetNamespace(int state); - private static final native int nativeGetName(int state); - private static final native int nativeGetText(int state); - private static final native int nativeGetLineNumber(int state); - private static final native int nativeGetAttributeCount(int state); - private static final native int nativeGetAttributeNamespace(int state, int idx); - private static final native int nativeGetAttributeName(int state, int idx); - private static final native int nativeGetAttributeResource(int state, int idx); - private static final native int nativeGetAttributeDataType(int state, int idx); - private static final native int nativeGetAttributeData(int state, int idx); - private static final native int nativeGetAttributeStringValue(int state, int idx); - private static final native int nativeGetIdAttribute(int state); - private static final native int nativeGetClassAttribute(int state); - private static final native int nativeGetStyleAttribute(int state); - private static final native int nativeGetAttributeIndex(int state, String namespace, String name); - private static final native void nativeDestroyParseState(int state); - - private static final native void nativeDestroy(int obj); -} diff --git a/core/java/android/content/res/XmlResourceParser.java b/core/java/android/content/res/XmlResourceParser.java deleted file mode 100644 index c59e6d4..0000000 --- a/core/java/android/content/res/XmlResourceParser.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2006 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.res; - -import org.xmlpull.v1.XmlPullParser; - -import android.util.AttributeSet; - -/** - * The XML parsing interface returned for an XML resource. This is a standard - * XmlPullParser interface, as well as an extended AttributeSet interface and - * an additional close() method on this interface for the client to indicate - * when it is done reading the resource. - */ -public interface XmlResourceParser extends XmlPullParser, AttributeSet { - /** - * Close this interface to the resource. Calls on the interface are no - * longer value after this call. - */ - public void close(); -} - diff --git a/core/java/android/content/res/package.html b/core/java/android/content/res/package.html deleted file mode 100644 index bb09dc7..0000000 --- a/core/java/android/content/res/package.html +++ /dev/null @@ -1,8 +0,0 @@ -<HTML> -<BODY> -Contains classes for accessing application resources, -such as raw asset files, colors, drawables, media or other other files -in the package, plus important device configuration details -(orientation, input types, etc.) that affect how the application may behave. -</BODY> -</HTML>
\ No newline at end of file |