diff --git a/api/current.xml b/api/current.xml index 3da6b72e1dda5..a8f710946e742 100644 --- a/api/current.xml +++ b/api/current.xml @@ -32785,6 +32785,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Consider for example how this interacts with + * {@ #registerReceiver(BroadcastReceiver, IntentFilter)}: + *
    + *
  • If used from an Activity context, the receiver is being registered + * within that activity. This means that you are expected to unregister + * before the activity is done being destroyed; in fact if you do not do + * so, the framework will clean up your leaked registration as it removes + * the activity and log an error. Thus, if you use the Activity context + * to register a receiver that is static (global to the process, not + * associated with an Activity instance) then that registration will be + * removed on you at whatever point the activity you used is destroyed. + *

  • If used from the Context returned here, the receiver is being + * registered with the global state associated with your application. Thus + * it will never be unregistered for you. This is necessary if the receiver + * is associated with static data, not a particular component. However + * using the ApplicationContext elsewhere can easily lead to serious leaks + * if you forget to unregister, unbind, etc. + *

*/ public abstract Context getApplicationContext(); @@ -392,12 +414,85 @@ public abstract class Context { */ public abstract File getFilesDir(); + /** + * Returns the absolute path to the directory on the external filesystem + * (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory() + * Environment.getExternalStorageDirectory()} where the application can + * place persistent files it owns. These files are private to the + * applications, and not typically visible to the user as media. + * + *

This is like {@link #getFilesDir()} in that these + * files will be deleted when the application is uninstalled, however there + * are some important differences: + * + *

    + *
  • External files are not always available: they will disappear if the + * user mounts the external storage on a computer or removes it. See the + * APIs on {@link android.os.Environment} for information in the storage state. + *
  • There is no security enforced with these files. All applications + * can read and write files placed here. + *
+ * + *

Here is an example of typical code to manipulate a file in + * an application's private storage:

+ * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * private_file} + * + *

If you install a non-null type to this function, the returned + * file will be a path to a sub-directory of the given type. Though these files + * are not automatically scanned by the media scanner, you can explicitly + * add them to the media database with + * {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], + * ScanResultListener) MediaScannerConnection.scanFile}. + * Note that this is not the same as + * {@link android.os.Environment#getExternalStoragePublicDirectory + * Environment.getExternalStoragePublicDirectory()}, which provides + * directories of media shared by all applications. The + * directories returned here are + * owned by the application, and its contents will be removed when the + * application is uninstalled. Unlike + * {@link android.os.Environment#getExternalStoragePublicDirectory + * Environment.getExternalStoragePublicDirectory()}, the directory + * returned here will be automatically created for you. + * + *

Here is an example of typical code to manipulate a picture in + * an application's private storage and add it to the media database:

+ * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * private_picture} + * + * @param type The type of files directory to return. May be null for + * the root of the files directory or one of + * the following Environment constants for a subdirectory: + * {@link android.os.Environment#DIRECTORY_MUSIC}, + * {@link android.os.Environment#DIRECTORY_PODCASTS}, + * {@link android.os.Environment#DIRECTORY_RINGTONES}, + * {@link android.os.Environment#DIRECTORY_ALARMS}, + * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS}, + * {@link android.os.Environment#DIRECTORY_PICTURES}, or + * {@link android.os.Environment#DIRECTORY_MOVIES}. + * + * @return Returns the path of the directory holding application files + * on external storage. Returns null if external storage is not currently + * mounted so it could not ensure the path exists; you will need to call + * this method again when it is available. + * + * @see #getFilesDir + */ + public abstract File getExternalFilesDir(String type); + /** * 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 + * device runs low on storage. * There is no guarantee when these files will be deleted. - * + * + * Note: you should not rely on the system deleting these + * files for you; you should always have a reasonable maximum, such as 1 MB, + * for the amount of space you consume with cache files, and prune those + * files when exceeding that space. + * * @return Returns the path of the directory holding application cache files. * * @see #openFileOutput @@ -406,6 +501,37 @@ public abstract class Context { */ public abstract File getCacheDir(); + /** + * Returns the absolute path to the directory on the external filesystem + * (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory() + * Environment.getExternalStorageDirectory()} where the application can + * place cache files it owns. + * + *

This is like {@link #getCacheDir()} in that these + * files will be deleted when the application is uninstalled, however there + * are some important differences: + * + *

    + *
  • The platform does not monitor the space available in external storage, + * and thus will not automatically delete these files. Note that you should + * be managing the maximum space you will use for these anyway, just like + * with {@link #getCacheDir()}. + *
  • External files are not always available: they will disappear if the + * user mounts the external storage on a computer or removes it. See the + * APIs on {@link android.os.Environment} for information in the storage state. + *
  • There is no security enforced with these files. All applications + * can read and write files placed here. + *
+ * + * @return Returns the path of the directory holding application cache files + * on external storage. Returns null if external storage is not currently + * mounted so it could not ensure the path exists; you will need to call + * this method again when it is available. + * + * @see #getCacheDir + */ + public abstract File getExternalCacheDir(); + /** * Returns an array of strings naming the private files associated with * this Context's application package. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 1b34320cab1fc..a447108a99fb7 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -178,11 +178,21 @@ public class ContextWrapper extends Context { return mBase.getFilesDir(); } + @Override + public File getExternalFilesDir(String type) { + return mBase.getExternalFilesDir(type); + } + @Override public File getCacheDir() { return mBase.getCacheDir(); } + @Override + public File getExternalCacheDir() { + return mBase.getExternalCacheDir(); + } + @Override public File getDir(String name, int mode) { return mBase.getDir(name, mode); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 54db5e04c7d29..2c8c112fe7b4c 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -305,4 +305,5 @@ interface IPackageManager { */ void updateExternalMediaStatus(boolean mounted); + String nextPackageToClean(String lastPackage); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e3b16945b1c7b..fca858869e9d8 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -621,6 +621,13 @@ public abstract class PackageManager { @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper"; + /** + * Action to external storage service to clean out removed apps. + * @hide + */ + public static final String ACTION_CLEAN_EXTERNAL_STORAGE + = "android.content.pm.CLEAN_EXTERNAL_STORAGE"; + /** * Determines best place to install an application: either SD or internal FLASH. * Tweak the algorithm for best results. diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index ef1f3bed2c3e9..a9831aa0fd568 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -91,6 +91,14 @@ public class Environment { private static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "/sdcard"); + private static final File EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY + = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"), + "Android"), "data"); + + private static final File EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY + = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"), + "Android"), "media"); + private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache"); @@ -102,12 +110,182 @@ public class Environment { } /** - * Gets the Android external storage directory. + * Gets the Android external storage directory. This directory may not + * currently be accessible if it has been mounted by the user on their + * computer, has been removed from the device, or some other problem has + * happened. You can determine its current state with + * {@link #getExternalStorageState()}. + * + *

Here is an example of typical code to monitor the state of + * external storage:

+ * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * monitor_storage} */ public static File getExternalStorageDirectory() { return EXTERNAL_STORAGE_DIRECTORY; } + /** + * Standard directory in which to place any audio files that should be + * in the regular list of music for the user. + * This may be combined with + * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, + * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_MUSIC = "Music"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of podcasts that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_NOTIFICATIONS}, + * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_PODCASTS = "Podcasts"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of ringtones that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and + * {@link #DIRECTORY_ALARMS} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_RINGTONES = "Ringtones"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of alarms that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, + * and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_ALARMS = "Alarms"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of notifications that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_PODCASTS}, + * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_NOTIFICATIONS = "Notifications"; + + /** + * Standard directory in which to place pictures that are available to + * the user. Note that this is primarily a convention for the top-level + * public directory, as the media scanner will find and collect pictures + * in any directory. + */ + public static String DIRECTORY_PICTURES = "Pictures"; + + /** + * Standard directory in which to place movies that are available to + * the user. Note that this is primarily a convention for the top-level + * public directory, as the media scanner will find and collect movies + * in any directory. + */ + public static String DIRECTORY_MOVIES = "Movies"; + + /** + * Standard directory in which to place files that have been downloaded by + * the user. Note that this is primarily a convention for the top-level + * public directory, you are free to download files anywhere in your own + * private directories. + */ + public static String DIRECTORY_DOWNLOADS = "Downloads"; + + /** + * The traditional location for pictures and videos when mounting the + * device as a camera. Note that this is primarily a convention for the + * top-level public directory, as this convention makes no sense elsewhere. + */ + public static String DIRECTORY_DCIM = "DCIM"; + + /** + * Get a top-level public external storage directory for placing files of + * a particular type. This is where the user will typically place and + * manage their own files, so you should be careful about what you put here + * to ensure you don't erase their files or get in the way of their own + * organization. + * + *

Here is an example of typical code to manipulate a picture on + * the public external storage:

+ * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * public_picture} + * + * @param type The type of storage directory to return. Should be one of + * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS}, + * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS}, + * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES}, + * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or + * {@link #DIRECTORY_DCIM}. May not be null. + * + * @return Returns the File path for the directory. Note that this + * directory may not yet exist, so you must make sure it exists before + * using it such as with {@link File#mkdirs File.mkdirs()}. + */ + public static File getExternalStoragePublicDirectory(String type) { + return new File(getExternalStorageDirectory(), type); + } + + /** + * Returns the path for android-specific data on the SD card. + * @hide + */ + public static File getExternalStorageAndroidDataDir() { + return EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY; + } + + /** + * Generates the raw path to an application's data + * @hide + */ + public static File getExternalStorageAppDataDirectory(String packageName) { + return new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, packageName); + } + + /** + * Generates the raw path to an application's media + * @hide + */ + public static File getExternalStorageAppMediaDirectory(String packageName) { + return new File(EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY, packageName); + } + + /** + * Generates the path to an application's files. + * @hide + */ + public static File getExternalStorageAppFilesDirectory(String packageName) { + return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, + packageName), "files"); + } + + /** + * Generates the path to an application's cache. + * @hide + */ + public static File getExternalStorageAppCacheDirectory(String packageName) { + return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, + packageName), "cache"); + } + /** * Gets the Android Download/Cache content directory. */ @@ -173,6 +351,8 @@ public class Environment { * Gets the current state of the external storage device. * Note: This call should be deprecated as it doesn't support * multiple volumes. + * + *

See {@link #getExternalStorageDirectory()} for an example of its use. */ public static String getExternalStorageState() { try { diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java index d2596b89b13c6..65b67a1eed021 100644 --- a/media/java/android/media/MediaScannerConnection.java +++ b/media/java/android/media/MediaScannerConnection.java @@ -56,18 +56,33 @@ public class MediaScannerConnection implements ServiceConnection { } }; + /** + * Interface for notifying clients of the result of scanning a + * requested media file. + */ + public interface ScanResultListener { + /** + * Called to notify the client when the media scanner has finished + * scanning a file. + * @param path the path to the file that has been scanned. + * @param uri the Uri for the file if the scanning operation succeeded + * and the file was added to the media database, or null if scanning failed. + */ + public void onScanCompleted(String path, Uri uri); + } + /** * An interface for notifying clients of MediaScannerConnection * when a connection to the MediaScanner service has been established * and when the scanning of a file has completed. */ - public interface MediaScannerConnectionClient { + public interface MediaScannerConnectionClient extends ScanResultListener { /** * Called to notify the client when a connection to the * MediaScanner service has been established. */ public void onMediaScannerConnected(); - + /** * Called to notify the client when the media scanner has finished * scanning a file. @@ -136,11 +151,12 @@ public class MediaScannerConnection implements ServiceConnection { /** * Requests the media scanner to scan a file. + * Success or failure of the scanning operation cannot be determined until + * {@link MediaScannerConnectionClient#onScanCompleted(String, Uri)} is called. + * * @param path the path to the file to be scanned. * @param mimeType an optional mimeType for the file. * If mimeType is null, then the mimeType will be inferred from the file extension. - * Success or failure of the scanning operation cannot be determined until - * {@link MediaScannerConnectionClient#onScanCompleted(String, Uri)} is called. */ public void scanFile(String path, String mimeType) { synchronized (this) { @@ -159,7 +175,67 @@ public class MediaScannerConnection implements ServiceConnection { } } } - + + static class ClientProxy implements MediaScannerConnectionClient { + final String[] mPaths; + final String[] mMimeTypes; + final ScanResultListener mClient; + MediaScannerConnection mConnection; + int mNextPath; + + ClientProxy(String[] paths, String[] mimeTypes, ScanResultListener client) { + mPaths = paths; + mMimeTypes = mimeTypes; + mClient = client; + } + + public void onMediaScannerConnected() { + scanNextPath(); + } + + public void onScanCompleted(String path, Uri uri) { + if (mClient != null) { + mClient.onScanCompleted(path, uri); + } + scanNextPath(); + } + + void scanNextPath() { + if (mNextPath >= mPaths.length) { + mConnection.disconnect(); + return; + } + String mimeType = mMimeTypes != null ? mMimeTypes[mNextPath] : null; + mConnection.scanFile(mPaths[mNextPath], mimeType); + mNextPath++; + } + } + + /** + * Convenience for constructing a {@link MediaScannerConnection}, calling + * {@link #connect} on it, and calling {@link #scanFile} with the given + * path and mimeType when the connection is + * established. + * @param context The caller's Context, required for establishing a connection to + * the media scanner service. + * Success or failure of the scanning operation cannot be determined until + * {@link MediaScannerConnectionClient#onScanCompleted(String, Uri)} is called. + * @param paths Array of paths to be scanned. + * @param mimeTypes Optional array of MIME types for each path. + * If mimeType is null, then the mimeType will be inferred from the file extension. + * @param callback Optional callback through which you can receive the + * scanned URI and MIME type; If null, the file will be scanned but + * you will not get a result back. + * @see scanFile(String, String) + */ + public static void scanFile(Context context, String[] paths, String[] mimeTypes, + ScanResultListener callback) { + ClientProxy client = new ClientProxy(paths, mimeTypes, callback); + MediaScannerConnection connection = new MediaScannerConnection(context, client); + client.mConnection = connection; + connection.connect(); + } + /** * Part of the ServiceConnection interface. Do not call. */ diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml index 3d720174bb207..5ec72df156f04 100755 --- a/packages/DefaultContainerService/AndroidManifest.xml +++ b/packages/DefaultContainerService/AndroidManifest.xml @@ -5,9 +5,9 @@ + - + 0 + ? mSettings.mPackagesToBeCleaned.get(0) : null; + } + } + void schedulePackageCleaning(String packageName) { + mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName)); + } + + void startCleaningPackages() { + synchronized (mPackages) { + if (!mMediaMounted) { + return; + } + if (mSettings.mPackagesToBeCleaned.size() <= 0) { + return; + } + } + Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE); + intent.setComponent(DEFAULT_CONTAINER_COMPONENT); + IActivityManager am = ActivityManagerNative.getDefault(); + if (am != null) { + try { + am.startService(null, intent, null); + } catch (RemoteException e) { + } + } + } + private final class AppDirObserver extends FileObserver { public AppDirObserver(String path, int mask, boolean isrom) { super(path, mask); @@ -5224,7 +5279,6 @@ class PackageManagerService extends IPackageManager.Stub { * persisting settings for later use * sending a broadcast if necessary */ - private boolean deletePackageX(String packageName, boolean sendBroadCast, boolean deleteCodeAndResources, int flags) { PackageRemovedInfo info = new PackageRemovedInfo(); @@ -5316,6 +5370,7 @@ class PackageManagerService extends IPackageManager.Stub { File dataDir = new File(pkg.applicationInfo.dataDir); dataDir.delete(); } + schedulePackageCleaning(packageName); synchronized (mPackages) { if (outInfo != null) { outInfo.removedUid = mSettings.removePackageLP(packageName); @@ -5328,7 +5383,7 @@ class PackageManagerService extends IPackageManager.Stub { mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids); } // Save settings now - mSettings.writeLP (); + mSettings.writeLP(); } } @@ -6817,6 +6872,10 @@ class PackageManagerService extends IPackageManager.Stub { final HashMap mPermissionTrees = new HashMap(); + // Packages that have been uninstalled and still need their external + // storage data deleted. + final ArrayList mPackagesToBeCleaned = new ArrayList(); + private final StringBuilder mReadMessages = new StringBuilder(); private static final class PendingPackage extends PackageSettingBase { @@ -7380,6 +7439,14 @@ class PackageManagerService extends IPackageManager.Stub { serializer.endTag(null, "shared-user"); } + if (mPackagesToBeCleaned.size() > 0) { + for (int i=0; i: " + parser.getName()); @@ -7765,7 +7837,7 @@ class PackageManagerService extends IPackageManager.Stub { } private void readDisabledSysPackageLP(XmlPullParser parser) - throws XmlPullParserException, IOException { + throws XmlPullParserException, IOException { String name = parser.getAttributeValue(null, "name"); String codePathStr = parser.getAttributeValue(null, "codePath"); String resourcePathStr = parser.getAttributeValue(null, "resourcePath"); @@ -8435,19 +8507,21 @@ class PackageManagerService extends IPackageManager.Stub { } public void updateExternalMediaStatus(final boolean mediaStatus) { - if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + - mediaStatus+", mMediaMounted=" + mMediaMounted); - if (mediaStatus == mMediaMounted) { - return; - } - mMediaMounted = mediaStatus; - // Queue up an async operation since the package installation may take a little while. - mHandler.post(new Runnable() { - public void run() { - mHandler.removeCallbacks(this); - updateExternalMediaStatusInner(mediaStatus); + synchronized (mPackages) { + if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + + mediaStatus+", mMediaMounted=" + mMediaMounted); + if (mediaStatus == mMediaMounted) { + return; } - }); + mMediaMounted = mediaStatus; + // Queue up an async operation since the package installation may take a little while. + mHandler.post(new Runnable() { + public void run() { + mHandler.removeCallbacks(this); + updateExternalMediaStatusInner(mediaStatus); + } + }); + } } void updateExternalMediaStatusInner(boolean mediaStatus) { @@ -8505,6 +8579,7 @@ class PackageManagerService extends IPackageManager.Stub { if (mediaStatus) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); loadMediaPackages(processCids, uidArr); + startCleaningPackages(); } else { if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages"); unloadMediaPackages(processCids, uidArr); diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java index 57b22f87453a3..ffd757c85b71a 100644 --- a/test-runner/android/test/mock/MockContext.java +++ b/test-runner/android/test/mock/MockContext.java @@ -157,11 +157,21 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } + @Override + public File getExternalFilesDir(String type) { + throw new UnsupportedOperationException(); + } + @Override public File getCacheDir() { throw new UnsupportedOperationException(); } + @Override + public File getExternalCacheDir() { + throw new UnsupportedOperationException(); + } + @Override public File getDir(String name, int mode) { throw new UnsupportedOperationException(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java index b670eee1998a7..57b5d4e1e3d72 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java @@ -927,6 +927,12 @@ public final class BridgeContext extends Context { return null; } + @Override + public File getExternalCacheDir() { + // TODO Auto-generated method stub + return null; + } + @Override public ContentResolver getContentResolver() { if (mContentResolver == null) { @@ -959,6 +965,12 @@ public final class BridgeContext extends Context { return null; } + @Override + public File getExternalFilesDir(String type) { + // TODO Auto-generated method stub + return null; + } + @Override public String getPackageCodePath() { // TODO Auto-generated method stub