diff options
author | Jeff Sharkey <jsharkey@android.com> | 2015-04-18 21:38:05 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2015-04-18 23:11:00 -0700 |
commit | e6c04f9417cc4bff0f5f9e72f0d6d66d2aab6e80 (patch) | |
tree | cd544b7655f5a41228bfd1690cbd5164cf0e0bc5 | |
parent | 722743667110718acf473c92727b55581c0b9309 (diff) | |
download | frameworks_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
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); |