Merge tag 'android-4.4.1_r1' into kitkat
Android 4.4.1 Release 1
diff --git a/src/com/android/providers/media/MediaDocumentsProvider.java b/src/com/android/providers/media/MediaDocumentsProvider.java
index cb8cc2f..a887a83 100644
--- a/src/com/android/providers/media/MediaDocumentsProvider.java
+++ b/src/com/android/providers/media/MediaDocumentsProvider.java
@@ -476,7 +476,7 @@
try {
cursor = resolver.query(uri, new String[] {
BaseColumns._ID }, null, null, null);
- return (cursor.getCount() == 0);
+ return (cursor == null) || (cursor.getCount() == 0);
} finally {
IoUtils.closeQuietly(cursor);
Binder.restoreCallingIdentity(token);
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 3e03ae6..4528c56 100755
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -60,7 +60,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -127,16 +126,21 @@
private static final String sExternalPath;
/** Resolved canonical path to cache storage. */
private static final String sCachePath;
+ /** Resolved canonical path to legacy storage. */
+ private static final String sLegacyPath;
static {
try {
sExternalPath = Environment.getExternalStorageDirectory().getCanonicalPath();
sCachePath = Environment.getDownloadCacheDirectory().getCanonicalPath();
+ sLegacyPath = Environment.getLegacyExternalStorageDirectory().getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException("Unable to resolve canonical paths", e);
}
}
+ private StorageManager mStorageManager;
+
// In memory cache of path<->id mappings, to speed up inserts during media scan
HashMap<String, Long> mDirectoryCache = new HashMap<String, Long>();
@@ -546,6 +550,8 @@
public boolean onCreate() {
final Context context = getContext();
+ mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+
sArtistAlbumsMap.put(MediaStore.Audio.Albums._ID, "audio.album_id AS " +
MediaStore.Audio.Albums._ID);
sArtistAlbumsMap.put(MediaStore.Audio.Albums.ALBUM, "album");
@@ -4165,8 +4171,11 @@
sGetTableAndWhereParam.where, whereArgs);
if (count > 0) {
// update the paths of any files and folders contained in the directory
- Object[] bindArgs = new Object[] {newPath, oldPath.length() + 1,
- oldPath + "/", oldPath + "0",
+ Object[] bindArgs = new Object[] {
+ newPath,
+ oldPath.length() + 1,
+ oldPath + "/",
+ oldPath + "0",
// update bucket_display_name and bucket_id based on new path
f.getName(),
f.toString().toLowerCase().hashCode()
@@ -4174,8 +4183,8 @@
helper.mNumUpdates++;
db.execSQL("UPDATE files SET _data=?1||SUBSTR(_data, ?2)" +
// also update bucket_display_name
- ",bucket_display_name=?6" +
- ",bucket_id=?7" +
+ ",bucket_display_name=?5" +
+ ",bucket_id=?6" +
" WHERE _data >= ?3 AND _data < ?4;",
bindArgs);
}
@@ -4596,10 +4605,13 @@
throw new IllegalArgumentException("Unable to resolve canonical path for " + file, e);
}
- if (path.startsWith(sExternalPath)) {
- Context c = getContext();
- if (c.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
- != PackageManager.PERMISSION_GRANTED) {
+ Context c = getContext();
+ boolean readGranted =
+ (c.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ == PackageManager.PERMISSION_GRANTED);
+
+ if (path.startsWith(sExternalPath) || path.startsWith(sLegacyPath)) {
+ if (!readGranted) {
c.enforceCallingOrSelfPermission(
READ_EXTERNAL_STORAGE, "External path: " + path);
}
@@ -4613,15 +4625,19 @@
}
} else if (path.startsWith(sCachePath)) {
- getContext().enforceCallingOrSelfPermission(
- ACCESS_CACHE_FILESYSTEM, "Cache path: " + path);
+ if (!readGranted) {
+ c.enforceCallingOrSelfPermission(
+ ACCESS_CACHE_FILESYSTEM, "Cache path: " + path);
+ }
} else if (isWrite) {
// don't write to non-cache, non-sdcard files.
throw new FileNotFoundException("Can't access " + file);
} else if (isSecondaryExternalPath(path)) {
// read access is OK with the appropriate permission
- getContext().enforceCallingOrSelfPermission(
- READ_EXTERNAL_STORAGE, "External path: " + path);
+ if (!readGranted) {
+ c.enforceCallingOrSelfPermission(
+ READ_EXTERNAL_STORAGE, "External path: " + path);
+ }
} else {
checkWorldReadAccess(path);
}
@@ -5225,16 +5241,15 @@
false, mObjectRemovedCallback);
} else if (EXTERNAL_VOLUME.equals(volume)) {
if (Environment.isExternalStorageRemovable()) {
- String path = mExternalStoragePaths[0];
- int volumeID = FileUtils.getFatVolumeId(path);
- if (LOCAL_LOGV) Log.v(TAG, path + " volume ID: " + volumeID);
+ final StorageVolume actualVolume = mStorageManager.getPrimaryVolume();
+ final int volumeId = actualVolume.getFatVolumeId();
// Must check for failure!
// If the volume is not (yet) mounted, this will create a new
// external-ffffffff.db database instead of the one we expect. Then, if
// android.process.media is later killed and respawned, the real external
// database will be attached, containing stale records, or worse, be empty.
- if (volumeID == -1) {
+ if (volumeId == -1) {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
@@ -5253,10 +5268,10 @@
}
// generate database name based on volume ID
- String dbName = "external-" + Integer.toHexString(volumeID) + ".db";
+ String dbName = "external-" + Integer.toHexString(volumeId) + ".db";
helper = new DatabaseHelper(context, dbName, false,
false, mObjectRemovedCallback);
- mVolumeId = volumeID;
+ mVolumeId = volumeId;
} else {
// external database name should be EXTERNAL_DATABASE_NAME
// however earlier releases used the external-XXXXXXXX.db naming