Merge tag 'android-4.4.3_r1.1' into kitkat-staging
Android 4.4.3 release 1.1
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7d48a4a..1fc63be 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -48,6 +48,10 @@
<receiver android:name="MediaScannerReceiver">
<intent-filter>
+ <action android:name="com.android.providers.media.SCAN_ALL" />
+ <action android:name="com.android.providers.media.DISMISS_SCAN" />
+ </intent-filter>
+ <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
diff --git a/res/drawable-hdpi/ask_scan.png b/res/drawable-hdpi/ask_scan.png
new file mode 100644
index 0000000..a1d9855
--- /dev/null
+++ b/res/drawable-hdpi/ask_scan.png
Binary files differ
diff --git a/res/drawable-mdpi/ask_scan.png b/res/drawable-mdpi/ask_scan.png
new file mode 100644
index 0000000..864926f
--- /dev/null
+++ b/res/drawable-mdpi/ask_scan.png
Binary files differ
diff --git a/res/drawable-xhdpi/ask_scan.png b/res/drawable-xhdpi/ask_scan.png
new file mode 100644
index 0000000..0a67738
--- /dev/null
+++ b/res/drawable-xhdpi/ask_scan.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ask_scan.png b/res/drawable-xxhdpi/ask_scan.png
new file mode 100644
index 0000000..957c2f6
--- /dev/null
+++ b/res/drawable-xxhdpi/ask_scan.png
Binary files differ
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 593a2c7..326659e 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -24,5 +24,4 @@
<string name="notification_sound_default" msgid="5309766396223094324">"Märguande vaikeheli"</string>
<string name="alarm_sound_default" msgid="6854264112790616066">"Äratuse vaikeheli"</string>
<string name="root_images" msgid="7098113056247445324">"Pildid"</string>
- <string name="root_music" msgid="4663573634162145060">"Muusika"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 7f2ae5b..bb7429d 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -24,5 +24,4 @@
<string name="notification_sound_default" msgid="5309766396223094324">"Bunyi pemberitahuan lalai"</string>
<string name="alarm_sound_default" msgid="6854264112790616066">"Bunyi penggera lalai"</string>
<string name="root_images" msgid="7098113056247445324">"Imej"</string>
- <string name="root_music" msgid="4663573634162145060">"Muzik"</string>
</resources>
diff --git a/res/values/slim_strings.xml b/res/values/slim_strings.xml
new file mode 100644
index 0000000..37fbb26
--- /dev/null
+++ b/res/values/slim_strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 SlimRoms 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Ask to scan on boot -->
+ <string name="ask_scan_title">Scan for new media?</string>
+ <string name="ask_scan_text">Click to manually trigger media scan</string>
+
+</resources>
diff --git a/src/com/android/providers/media/MediaScannerReceiver.java b/src/com/android/providers/media/MediaScannerReceiver.java
index 89635b9..65dc83a 100644
--- a/src/com/android/providers/media/MediaScannerReceiver.java
+++ b/src/com/android/providers/media/MediaScannerReceiver.java
@@ -17,58 +17,151 @@
package com.android.providers.media;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
+import android.os.Handler;
+import android.provider.Settings;
import android.util.Log;
import java.io.File;
import java.io.IOException;
public class MediaScannerReceiver extends BroadcastReceiver {
+ private final static int BOOT_SCAN_ENABLE = 0;
+ private final static int BOOT_SCAN_ASK = 1;
+ private final static int BOOT_SCAN_DISABLE = 2;
+
+ private final static int NOTIFICATION_ID = 1;
+
+ // This delay prevents a scan on boot from mounting the sdcard
+ private final static int DELAY_MS = 120000; // 2m
+
private final static String TAG = "MediaScannerReceiver";
+ private final static String SCAN_ALL = "com.android.providers.media.SCAN_ALL";
+ private final static String DISMISS_SCAN = "com.android.providers.media.DISMISS_SCAN";
+
+ private Handler mDelayScan = new Handler();
+
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
final Uri uri = intent.getData();
+
+ // MediaScanner behavior on boot
+ final int msob = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.MEDIA_SCANNER_ON_BOOT, 0);
+
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- // Scan both internal and external storage
+ switch (msob) {
+ case BOOT_SCAN_ENABLE:
+ // Scan both internal and external storage
+
+ scan(context, MediaProvider.INTERNAL_VOLUME);
+ scan(context, MediaProvider.EXTERNAL_VOLUME);
+ break;
+ case BOOT_SCAN_ASK:
+ askToScan(context, true);
+ break;
+ case BOOT_SCAN_DISABLE:
+ askToScan(context, false);
+ removeAsk(context, DELAY_MS);
+ break;
+ }
+ } else if (SCAN_ALL.equals(action)) {
+ removeAsk(context, DELAY_MS);
+
scan(context, MediaProvider.INTERNAL_VOLUME);
scan(context, MediaProvider.EXTERNAL_VOLUME);
-
+ } else if (DISMISS_SCAN.equals(action)) {
+ removeAsk(context, DELAY_MS);
} else {
if (uri.getScheme().equals("file")) {
- // handle intents related to external storage
- String path = uri.getPath();
- String externalStoragePath = Environment.getExternalStorageDirectory().getPath();
- String legacyPath = Environment.getLegacyExternalStorageDirectory().getPath();
+ if (!checkAsk(context)) {
+ // handle intents related to external storage
+ String path = uri.getPath();
+ String externalStoragePath = Environment.getExternalStorageDirectory().getPath();
+ String legacyPath = Environment.getLegacyExternalStorageDirectory().getPath();
- try {
- path = new File(path).getCanonicalPath();
- } catch (IOException e) {
- Log.e(TAG, "couldn't canonicalize " + path);
- return;
- }
- if (path.startsWith(legacyPath)) {
- path = externalStoragePath + path.substring(legacyPath.length());
- }
+ try {
+ path = new File(path).getCanonicalPath();
+ } catch (IOException e) {
+ Log.e(TAG, "couldn't canonicalize " + path);
+ return;
+ }
+ if (path.startsWith(legacyPath)) {
+ path = externalStoragePath + path.substring(legacyPath.length());
+ }
- Log.d(TAG, "action: " + action + " path: " + path);
- if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
- // scan whenever any volume is mounted
- scan(context, MediaProvider.EXTERNAL_VOLUME);
- } else if (Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action) &&
- path != null && path.startsWith(externalStoragePath + "/")) {
- scanFile(context, path);
+ Log.d(TAG, "action: " + action + " path: " + path);
+ if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
+ // scan whenever any volume is mounted
+ scan(context, MediaProvider.EXTERNAL_VOLUME);
+ } else if (Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action) &&
+ path != null && path.startsWith(externalStoragePath + "/")) {
+ scanFile(context, path);
+ }
}
}
}
}
+ private boolean checkAsk(Context context) {
+ final Intent intent = new Intent(SCAN_ALL);
+ boolean askExists = (PendingIntent.getBroadcast(context,
+ 1, intent, PendingIntent.FLAG_NO_CREATE) != null);
+ return askExists;
+ }
+
+ private void removeAsk(final Context context, final int delay) {
+ mDelayScan.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent(SCAN_ALL);
+ PendingIntent.getBroadcast(context, 1, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT).cancel();
+ }
+ }, delay);
+ }
+
+ public void askToScan(Context context, boolean startNotify) {
+
+ Intent intent = new Intent(SCAN_ALL);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
+ 1, intent, 0);
+
+ if (!startNotify) {
+ return;
+ }
+
+ Notification.Builder mBuilder = new Notification.Builder(context)
+ .setContentTitle(context.getString(R.string.ask_scan_title))
+ .setContentText(context.getString(R.string.ask_scan_text))
+ .setSmallIcon(R.drawable.ask_scan);
+
+ mBuilder.setContentIntent(pendingIntent);
+
+ intent = new Intent(DISMISS_SCAN);
+ pendingIntent = PendingIntent.getBroadcast(context,
+ 2, intent, 0);
+ mBuilder.setDeleteIntent(pendingIntent);
+
+ NotificationManager notificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ Notification notif = mBuilder.build();
+ notif.flags |= Notification.FLAG_AUTO_CANCEL;
+ notif.priority = Notification.PRIORITY_HIGH;
+
+ notificationManager.notify(NOTIFICATION_ID, notif);
+ }
+
private void scan(Context context, String volume) {
Bundle args = new Bundle();
args.putString("volume", volume);
diff --git a/src/com/android/providers/media/MediaScannerService.java b/src/com/android/providers/media/MediaScannerService.java
index 40bb10a..81a4289 100644
--- a/src/com/android/providers/media/MediaScannerService.java
+++ b/src/com/android/providers/media/MediaScannerService.java
@@ -186,13 +186,18 @@
Looper.loop();
}
- private Uri scanFile(String path, String mimeType) {
+ private Uri scanFileOrDirectory(String path, String mimeType) {
String volumeName = MediaProvider.EXTERNAL_VOLUME;
openDatabase(volumeName);
MediaScanner scanner = createMediaScanner();
try {
// make sure the file path is in canonical form
- String canonicalPath = new File(path).getCanonicalPath();
+ File file = new File(path);
+ String canonicalPath = file.getCanonicalPath();
+ if (file.isDirectory() && isExternalVolumeDirectory(canonicalPath)) {
+ scanner.scanDirectories(new String[]{canonicalPath}, volumeName);
+ return Uri.fromFile(file);
+ }
return scanner.scanSingleFile(canonicalPath, volumeName, mimeType);
} catch (Exception e) {
Log.e(TAG, "bad path " + path + " in scanFile()", e);
@@ -200,6 +205,15 @@
}
}
+ private boolean isExternalVolumeDirectory(String path) {
+ for (String directory : mExternalStoragePaths) {
+ if (path.startsWith(directory)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public IBinder onBind(Intent intent)
{
@@ -243,7 +257,7 @@
(binder == null ? null : IMediaScannerListener.Stub.asInterface(binder));
Uri uri = null;
try {
- uri = scanFile(filePath, arguments.getString("mimetype"));
+ uri = scanFileOrDirectory(filePath, arguments.getString("mimetype"));
} catch (Exception e) {
Log.e(TAG, "Exception scanning file", e);
}
diff --git a/src/com/android/providers/media/RingtonePickerActivity.java b/src/com/android/providers/media/RingtonePickerActivity.java
index 3075bbb..d37af4a 100644
--- a/src/com/android/providers/media/RingtonePickerActivity.java
+++ b/src/com/android/providers/media/RingtonePickerActivity.java
@@ -18,6 +18,9 @@
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
import android.database.Cursor;
import android.media.Ringtone;
import android.media.RingtoneManager;
@@ -129,6 +132,21 @@
Intent intent = getIntent();
+ // Set custom theme
+ int themeExtra = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_DIALOG_THEME, 0);
+ if (themeExtra != 0) {
+ try {
+ Resources resources = getPackageManager().getResourcesForApplication(
+ getCallingPackage());
+ Theme theme = resources.newTheme();
+ theme.applyStyle(themeExtra, true);
+ getTheme().setTo(theme);
+
+ } catch (NameNotFoundException e) {
+ // Resource not available. Fall-through default theme
+ }
+ }
+
/*
* Get whether to show the 'Default' item, and the URI to play when the
* default is clicked