summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2015-04-18 21:38:05 -0700
committerJeff Sharkey <jsharkey@android.com>2015-04-18 23:11:00 -0700
commite6c04f9417cc4bff0f5f9e72f0d6d66d2aab6e80 (patch)
treecd544b7655f5a41228bfd1690cbd5164cf0e0bc5
parent722743667110718acf473c92727b55581c0b9309 (diff)
downloadframeworks_base-e6c04f9417cc4bff0f5f9e72f0d6d66d2aab6e80.zip
frameworks_base-e6c04f9417cc4bff0f5f9e72f0d6d66d2aab6e80.tar.gz
frameworks_base-e6c04f9417cc4bff0f5f9e72f0d6d66d2aab6e80.tar.bz2
Broadcast hidden volumes, notification polish.
Send limited broadcast intent when certain volume state changes occur; the only customer for now is ExternalStorageProvider. Change notification flow to be less bumpy. Pick USB icon based on disk type, and avoid using "generic" disk labels. Bug: 19993667 Change-Id: I263bc9e9aae2ae57eb4d1afe76da686aee5475fb
-rw-r--r--core/java/android/os/storage/DiskInfo.java22
-rw-r--r--core/java/android/os/storage/VolumeInfo.java5
-rw-r--r--packages/ExternalStorageProvider/AndroidManifest.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java105
-rw-r--r--services/core/java/com/android/server/MountService.java33
5 files changed, 108 insertions, 61 deletions
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 2f63988..9f38de8 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -64,19 +64,29 @@ public class DiskInfo implements Parcelable {
return id;
}
+ private boolean isInteresting(String label) {
+ if (TextUtils.isEmpty(label)) {
+ return false;
+ }
+ if (label.toLowerCase().contains("generic")) {
+ return false;
+ }
+ return true;
+ }
+
public String getDescription() {
final Resources res = Resources.getSystem();
if ((flags & FLAG_SD) != 0) {
- if (TextUtils.isEmpty(label)) {
- return res.getString(com.android.internal.R.string.storage_sd_card);
- } else {
+ if (isInteresting(label)) {
return res.getString(com.android.internal.R.string.storage_sd_card_label, label);
+ } else {
+ return res.getString(com.android.internal.R.string.storage_sd_card);
}
} else if ((flags & FLAG_USB) != 0) {
- if (TextUtils.isEmpty(label)) {
- return res.getString(com.android.internal.R.string.storage_usb_drive);
- } else {
+ if (isInteresting(label)) {
return res.getString(com.android.internal.R.string.storage_usb_drive_label, label);
+ } else {
+ return res.getString(com.android.internal.R.string.storage_usb_drive);
}
} else {
return null;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 375a86a..f3498d5 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -49,7 +49,10 @@ import java.util.Objects;
* @hide
*/
public class VolumeInfo implements Parcelable {
- public static final String EXTRA_VOLUME_ID = "android.os.storage.extra.VOLUME_ID";
+ public static final String ACTION_VOLUME_STATE_CHANGED =
+ "android.os.storage.action.VOLUME_STATE_CHANGED";
+ public static final String EXTRA_VOLUME_ID =
+ "android.os.storage.extra.VOLUME_ID";
/** Stub volume representing internal private storage */
public static final String ID_PRIVATE_INTERNAL = "private";
diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml
index edd6255..3185917 100644
--- a/packages/ExternalStorageProvider/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/AndroidManifest.xml
@@ -19,9 +19,7 @@
<receiver android:name=".MountReceiver">
<intent-filter>
- <action android:name="android.intent.action.MEDIA_MOUNTED" />
- <action android:name="android.intent.action.MEDIA_UNMOUNTED" />
- <data android:scheme="file" />
+ <action android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
</intent-filter>
</receiver>
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index ecd1a2f..240c210 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -100,72 +100,75 @@ public class StorageNotification extends SystemUI {
Log.d(TAG, vol.toString());
- // New state means we tear down any old notifications
- mNotificationManager.cancelAsUser(vol.getId(), NOTIF_ID, UserHandle.ALL);
-
+ final Notification notif;
switch (newState) {
case VolumeInfo.STATE_UNMOUNTED:
- onVolumeUnmounted(vol);
+ notif = onVolumeUnmounted(vol);
break;
case VolumeInfo.STATE_CHECKING:
- onVolumeChecking(vol);
+ notif = onVolumeChecking(vol);
break;
case VolumeInfo.STATE_MOUNTED:
case VolumeInfo.STATE_MOUNTED_READ_ONLY:
- onVolumeMounted(vol);
+ notif = onVolumeMounted(vol);
break;
case VolumeInfo.STATE_FORMATTING:
- onVolumeFormatting(vol);
+ notif = onVolumeFormatting(vol);
break;
case VolumeInfo.STATE_EJECTING:
- onVolumeEjecting(vol);
+ notif = onVolumeEjecting(vol);
break;
case VolumeInfo.STATE_UNMOUNTABLE:
- onVolumeUnmountable(vol);
+ notif = onVolumeUnmountable(vol);
break;
case VolumeInfo.STATE_REMOVED:
- onVolumeRemoved(vol);
+ notif = onVolumeRemoved(vol);
break;
case VolumeInfo.STATE_BAD_REMOVAL:
- onVolumeBadRemoval(vol);
+ notif = onVolumeBadRemoval(vol);
+ break;
+ default:
+ notif = null;
break;
}
+
+ if (notif != null) {
+ mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
+ } else {
+ mNotificationManager.cancelAsUser(vol.getId(), NOTIF_ID, UserHandle.ALL);
+ }
}
- private void onVolumeUnmounted(VolumeInfo vol) {
+ private Notification onVolumeUnmounted(VolumeInfo vol) {
// Ignored
+ return null;
}
- private void onVolumeChecking(VolumeInfo vol) {
+ private Notification onVolumeChecking(VolumeInfo vol) {
final DiskInfo disk = vol.getDisk();
final CharSequence title = mContext.getString(
R.string.ext_media_checking_notification_title, disk.getDescription());
final CharSequence text = mContext.getString(
R.string.ext_media_checking_notification_message, disk.getDescription());
- final Notification notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard_prepare)
+ return buildNotificationBuilder(vol, title, text)
.setCategory(Notification.CATEGORY_PROGRESS)
.setPriority(Notification.PRIORITY_LOW)
.setOngoing(true)
.build();
-
- mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
}
- private void onVolumeMounted(VolumeInfo vol) {
+ private Notification onVolumeMounted(VolumeInfo vol) {
// Don't annoy when user dismissed in past
- if (vol.isSnoozed()) return;
+ if (vol.isSnoozed()) return null;
final DiskInfo disk = vol.getDisk();
- final Notification notif;
if (disk.isAdoptable() && !vol.isInited()) {
final CharSequence title = disk.getDescription();
final CharSequence text = mContext.getString(
R.string.ext_media_new_notification_message, disk.getDescription());
- notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard)
+ return buildNotificationBuilder(vol, title, text)
.addAction(new Action(0, mContext.getString(R.string.ext_media_init_action),
buildInitPendingIntent(vol)))
.addAction(new Action(0, mContext.getString(R.string.ext_media_unmount_action),
@@ -179,8 +182,7 @@ public class StorageNotification extends SystemUI {
final CharSequence text = mContext.getString(
R.string.ext_media_ready_notification_message, disk.getDescription());
- notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard)
+ return buildNotificationBuilder(vol, title, text)
.addAction(new Action(0, mContext.getString(R.string.ext_media_browse_action),
buildBrowsePendingIntent(vol)))
.addAction(new Action(0, mContext.getString(R.string.ext_media_unmount_action),
@@ -190,51 +192,44 @@ public class StorageNotification extends SystemUI {
.setPriority(Notification.PRIORITY_LOW)
.build();
}
-
- mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
}
- private void onVolumeFormatting(VolumeInfo vol) {
+ private Notification onVolumeFormatting(VolumeInfo vol) {
// Ignored
+ return null;
}
- private void onVolumeEjecting(VolumeInfo vol) {
+ private Notification onVolumeEjecting(VolumeInfo vol) {
final DiskInfo disk = vol.getDisk();
final CharSequence title = mContext.getString(
R.string.ext_media_unmounting_notification_title, disk.getDescription());
final CharSequence text = mContext.getString(
R.string.ext_media_unmounting_notification_message, disk.getDescription());
- final Notification notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard_prepare)
+ return buildNotificationBuilder(vol, title, text)
.setCategory(Notification.CATEGORY_PROGRESS)
.setPriority(Notification.PRIORITY_LOW)
.setOngoing(true)
.build();
-
- mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
}
- private void onVolumeUnmountable(VolumeInfo vol) {
+ private Notification onVolumeUnmountable(VolumeInfo vol) {
final DiskInfo disk = vol.getDisk();
final CharSequence title = mContext.getString(
R.string.ext_media_unmountable_notification_title, disk.getDescription());
final CharSequence text = mContext.getString(
R.string.ext_media_unmountable_notification_message, disk.getDescription());
- final Notification notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard)
+ return buildNotificationBuilder(vol, title, text)
.setContentIntent(buildDetailsPendingIntent(vol))
.setCategory(Notification.CATEGORY_ERROR)
.build();
-
- mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
}
- private void onVolumeRemoved(VolumeInfo vol) {
+ private Notification onVolumeRemoved(VolumeInfo vol) {
if (!vol.isPrimary()) {
// Ignore non-primary media
- return;
+ return null;
}
final DiskInfo disk = vol.getDisk();
@@ -243,18 +238,15 @@ public class StorageNotification extends SystemUI {
final CharSequence text = mContext.getString(
R.string.ext_media_nomedia_notification_message, disk.getDescription());
- final Notification notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard)
+ return buildNotificationBuilder(vol, title, text)
.setCategory(Notification.CATEGORY_ERROR)
.build();
-
- mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
}
- private void onVolumeBadRemoval(VolumeInfo vol) {
+ private Notification onVolumeBadRemoval(VolumeInfo vol) {
if (!vol.isPrimary()) {
// Ignore non-primary media
- return;
+ return null;
}
final DiskInfo disk = vol.getDisk();
@@ -263,16 +255,31 @@ public class StorageNotification extends SystemUI {
final CharSequence text = mContext.getString(
R.string.ext_media_badremoval_notification_message, disk.getDescription());
- final Notification notif = buildNotificationBuilder(title, text)
- .setSmallIcon(R.drawable.stat_notify_sdcard)
+ return buildNotificationBuilder(vol, title, text)
.setCategory(Notification.CATEGORY_ERROR)
.build();
+ }
- mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
+ private int getSmallIcon(VolumeInfo vol) {
+ if (vol.disk.isSd()) {
+ switch (vol.getState()) {
+ case VolumeInfo.STATE_CHECKING:
+ case VolumeInfo.STATE_EJECTING:
+ return R.drawable.stat_notify_sdcard_prepare;
+ default:
+ return R.drawable.stat_notify_sdcard;
+ }
+ } else if (vol.disk.isUsb()) {
+ return R.drawable.stat_sys_data_usb;
+ } else {
+ return R.drawable.stat_notify_sdcard;
+ }
}
- private Notification.Builder buildNotificationBuilder(CharSequence title, CharSequence text) {
+ private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
+ CharSequence text) {
return new Notification.Builder(mContext)
+ .setSmallIcon(getSmallIcon(vol))
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentText(text)
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index cc27cfc..868d3d8 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -861,7 +861,7 @@ class MountService extends IMountService.Stub
final int oldState = vol.state;
final int newState = Integer.parseInt(cooked[2]);
vol.state = newState;
- onVolumeStateChangedLocked(vol, oldState, newState);
+ onVolumeStateChangedLocked(vol.clone(), oldState, newState);
}
break;
}
@@ -955,8 +955,37 @@ class MountService extends IMountService.Stub
}
}
+ private boolean isBroadcastWorthy(VolumeInfo vol) {
+ switch (vol.getType()) {
+ case VolumeInfo.TYPE_PUBLIC:
+ case VolumeInfo.TYPE_EMULATED:
+ break;
+ default:
+ return false;
+ }
+
+ switch (vol.getState()) {
+ case VolumeInfo.STATE_MOUNTED:
+ case VolumeInfo.STATE_MOUNTED_READ_ONLY:
+ case VolumeInfo.STATE_EJECTING:
+ case VolumeInfo.STATE_UNMOUNTED:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
- mCallbacks.notifyVolumeStateChanged(vol.clone(), oldState, newState);
+ mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
+
+ if (isBroadcastWorthy(vol)) {
+ final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ // TODO: require receiver to hold permission
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);