blob: b36b53125f2f4f5fae3db578a163da3cdd546613 [file] [log] [blame]
San Mehat64e6a452010-02-04 20:53:48 -08001/*
Jeff Sharkey56bd3122015-04-14 10:30:34 -07002 * Copyright (C) 2015 The Android Open Source Project
San Mehat64e6a452010-02-04 20:53:48 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Joe Onoratofe4f3ae2010-06-04 11:25:26 -070017package com.android.systemui.usb;
San Mehat64e6a452010-02-04 20:53:48 -080018
Philip P. Moltmann75b230b2016-04-11 15:27:58 -070019import android.annotation.NonNull;
San Mehat64e6a452010-02-04 20:53:48 -080020import android.app.Notification;
Jeff Sharkey56bd3122015-04-14 10:30:34 -070021import android.app.Notification.Action;
San Mehat64e6a452010-02-04 20:53:48 -080022import android.app.NotificationManager;
23import android.app.PendingIntent;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070024import android.content.BroadcastReceiver;
25import android.content.Context;
San Mehat64e6a452010-02-04 20:53:48 -080026import android.content.Intent;
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070027import android.content.IntentFilter;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070028import android.content.pm.PackageManager;
29import android.content.pm.PackageManager.MoveCallback;
Jeff Sharkey50a05452015-04-29 11:24:52 -070030import android.os.Bundle;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070031import android.os.Handler;
Jeff Sharkeye3644412019-04-27 17:13:57 -060032import android.os.StrictMode;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -070033import android.os.UserHandle;
Jeff Sharkey56bd3122015-04-14 10:30:34 -070034import android.os.storage.DiskInfo;
San Mehatb1043402010-02-05 08:26:50 -080035import android.os.storage.StorageEventListener;
36import android.os.storage.StorageManager;
Jeff Sharkey56bd3122015-04-14 10:30:34 -070037import android.os.storage.VolumeInfo;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070038import android.os.storage.VolumeRecord;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -080039import android.provider.Settings;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070040import android.text.TextUtils;
41import android.text.format.DateUtils;
John Spurlockcd686b52013-06-05 10:13:46 -040042import android.util.Log;
Jeff Sharkey50a05452015-04-29 11:24:52 -070043import android.util.SparseArray;
San Mehat64e6a452010-02-04 20:53:48 -080044
Jeff Sharkey56bd3122015-04-14 10:30:34 -070045import com.android.internal.R;
Chris Wren5e6c0ff2017-01-05 12:57:06 -050046import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
John Spurlock3e309b22013-06-25 11:01:29 -040047import com.android.systemui.SystemUI;
Dan Sandler8e032e12017-01-25 13:41:38 -050048import com.android.systemui.util.NotificationChannels;
John Spurlock3e309b22013-06-25 11:01:29 -040049
Jeff Sharkey56bd3122015-04-14 10:30:34 -070050import java.util.List;
51
John Spurlock3e309b22013-06-25 11:01:29 -040052public class StorageNotification extends SystemUI {
San Mehat64e6a452010-02-04 20:53:48 -080053 private static final String TAG = "StorageNotification";
54
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070055 private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME";
Jeff Sharkeydf27d3b2015-06-16 13:51:48 -070056 private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD";
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070057
Jeff Sharkey56bd3122015-04-14 10:30:34 -070058 // TODO: delay some notifications to avoid bumpy fast operations
San Mehat64e6a452010-02-04 20:53:48 -080059
Jeff Sharkey56bd3122015-04-14 10:30:34 -070060 private NotificationManager mNotificationManager;
San Mehatb1043402010-02-05 08:26:50 -080061 private StorageManager mStorageManager;
San Mehat64e6a452010-02-04 20:53:48 -080062
Dave Mankoffa5d8a392019-10-10 12:21:09 -040063 public StorageNotification(Context context) {
64 super(context);
65 }
66
Jeff Sharkey50a05452015-04-29 11:24:52 -070067 private static class MoveInfo {
68 public int moveId;
69 public Bundle extras;
70 public String packageName;
71 public String label;
72 public String volumeUuid;
73 }
74
75 private final SparseArray<MoveInfo> mMoves = new SparseArray<>();
76
Jeff Sharkey56bd3122015-04-14 10:30:34 -070077 private final StorageEventListener mListener = new StorageEventListener() {
78 @Override
79 public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070080 onVolumeStateChangedInternal(vol);
John Spurlock3e309b22013-06-25 11:01:29 -040081 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070082
83 @Override
Jeff Sharkey50a05452015-04-29 11:24:52 -070084 public void onVolumeRecordChanged(VolumeRecord rec) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070085 // Avoid kicking notifications when getting early metadata before
86 // mounted. If already mounted, we're being kicked because of a
87 // nickname or init'ed change.
Jeff Sharkey50a05452015-04-29 11:24:52 -070088 final VolumeInfo vol = mStorageManager.findVolumeByUuid(rec.getFsUuid());
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070089 if (vol != null && vol.isMountedReadable()) {
90 onVolumeStateChangedInternal(vol);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -070091 }
Jeff Sharkey50a05452015-04-29 11:24:52 -070092 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070093
Jeff Sharkey50a05452015-04-29 11:24:52 -070094 @Override
95 public void onVolumeForgotten(String fsUuid) {
96 // Stop annoying the user
Chris Wren5e6c0ff2017-01-05 12:57:06 -050097 mNotificationManager.cancelAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
98 UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -070099 }
100
101 @Override
102 public void onDiskScanned(DiskInfo disk, int volumeCount) {
103 onDiskScannedInternal(disk, volumeCount);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700104 }
Philip P. Moltmann75b230b2016-04-11 15:27:58 -0700105
106 @Override
107 public void onDiskDestroyed(DiskInfo disk) {
108 onDiskDestroyedInternal(disk);
109 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700110 };
111
112 private final BroadcastReceiver mSnoozeReceiver = new BroadcastReceiver() {
113 @Override
114 public void onReceive(Context context, Intent intent) {
115 // TODO: kick this onto background thread
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700116 final String fsUuid = intent.getStringExtra(VolumeRecord.EXTRA_FS_UUID);
117 mStorageManager.setVolumeSnoozed(fsUuid, true);
118 }
119 };
120
Jeff Sharkeydf27d3b2015-06-16 13:51:48 -0700121 private final BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {
122 @Override
123 public void onReceive(Context context, Intent intent) {
124 // When finishing the adoption wizard, clean up any notifications
125 // for moving primary storage
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500126 mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_STORAGE_MOVE,
127 UserHandle.ALL);
Jeff Sharkeydf27d3b2015-06-16 13:51:48 -0700128 }
129 };
130
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700131 private final MoveCallback mMoveCallback = new MoveCallback() {
132 @Override
Jeff Sharkey50a05452015-04-29 11:24:52 -0700133 public void onCreated(int moveId, Bundle extras) {
134 final MoveInfo move = new MoveInfo();
135 move.moveId = moveId;
136 move.extras = extras;
137 if (extras != null) {
138 move.packageName = extras.getString(Intent.EXTRA_PACKAGE_NAME);
139 move.label = extras.getString(Intent.EXTRA_TITLE);
140 move.volumeUuid = extras.getString(VolumeRecord.EXTRA_FS_UUID);
141 }
142 mMoves.put(moveId, move);
143 }
144
145 @Override
146 public void onStatusChanged(int moveId, int status, long estMillis) {
147 final MoveInfo move = mMoves.get(moveId);
148 if (move == null) {
149 Log.w(TAG, "Ignoring unknown move " + moveId);
150 return;
151 }
152
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700153 if (PackageManager.isMoveStatusFinished(status)) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700154 onMoveFinished(move, status);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700155 } else {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700156 onMoveProgress(move, status, estMillis);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700157 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700158 }
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700159 };
San Mehat64e6a452010-02-04 20:53:48 -0800160
John Spurlock3e309b22013-06-25 11:01:29 -0400161 @Override
162 public void start() {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700163 mNotificationManager = mContext.getSystemService(NotificationManager.class);
John Spurlock3e309b22013-06-25 11:01:29 -0400164
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700165 mStorageManager = mContext.getSystemService(StorageManager.class);
166 mStorageManager.registerListener(mListener);
Daniel Sandler5b8743f2010-11-03 09:43:46 -0400167
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700168 mContext.registerReceiver(mSnoozeReceiver, new IntentFilter(ACTION_SNOOZE_VOLUME),
169 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
Jeff Sharkeydf27d3b2015-06-16 13:51:48 -0700170 mContext.registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_WIZARD),
171 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700172
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700173 // Kick current state into place
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -0700174 final List<DiskInfo> disks = mStorageManager.getDisks();
175 for (DiskInfo disk : disks) {
176 onDiskScannedInternal(disk, disk.volumeCount);
177 }
178
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700179 final List<VolumeInfo> vols = mStorageManager.getVolumes();
180 for (VolumeInfo vol : vols) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700181 onVolumeStateChangedInternal(vol);
182 }
183
184 mContext.getPackageManager().registerMoveCallback(mMoveCallback, new Handler());
185
186 updateMissingPrivateVolumes();
187 }
188
189 private void updateMissingPrivateVolumes() {
Agatha Man3f287f22020-03-26 09:53:56 -0700190 if (isTv() || isAutomotive()) {
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800191 // On TV, TvSettings displays a modal full-screen activity in this case.
Agatha Man3f287f22020-03-26 09:53:56 -0700192 // Not applicable for automotive.
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800193 return;
194 }
195
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700196 final List<VolumeRecord> recs = mStorageManager.getVolumeRecords();
197 for (VolumeRecord rec : recs) {
198 if (rec.getType() != VolumeInfo.TYPE_PRIVATE) continue;
199
200 final String fsUuid = rec.getFsUuid();
201 final VolumeInfo info = mStorageManager.findVolumeByUuid(fsUuid);
Jeff Sharkey52fc3c0f2015-06-14 20:58:54 -0700202 if ((info != null && info.isMountedWritable()) || rec.isSnoozed()) {
203 // Yay, private volume is here, or user snoozed
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500204 mNotificationManager.cancelAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
205 UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700206
207 } else {
208 // Boo, annoy the user to reinsert the private volume
209 final CharSequence title = mContext.getString(R.string.ext_media_missing_title,
210 rec.getNickname());
211 final CharSequence text = mContext.getString(R.string.ext_media_missing_message);
212
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500213 Notification.Builder builder =
214 new Notification.Builder(mContext, NotificationChannels.STORAGE)
215 .setSmallIcon(R.drawable.ic_sd_card_48dp)
216 .setColor(mContext.getColor(
217 R.color.system_notification_accent_color))
218 .setContentTitle(title)
219 .setContentText(text)
220 .setContentIntent(buildForgetPendingIntent(rec))
221 .setStyle(new Notification.BigTextStyle().bigText(text))
222 .setVisibility(Notification.VISIBILITY_PUBLIC)
223 .setLocalOnly(true)
224 .setCategory(Notification.CATEGORY_SYSTEM)
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800225 .setDeleteIntent(buildSnoozeIntent(fsUuid))
226 .extend(new Notification.TvExtender());
Julia Reynolds037d8082018-03-18 15:25:19 -0400227 SystemUI.overrideNotificationAppName(mContext, builder, false);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700228
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500229 mNotificationManager.notifyAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
230 builder.build(), UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700231 }
San Mehat64e6a452010-02-04 20:53:48 -0800232 }
233 }
234
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700235 private void onDiskScannedInternal(DiskInfo disk, int volumeCount) {
Jeff Sharkeyf5a6bd72015-05-19 14:42:38 -0700236 if (volumeCount == 0 && disk.size > 0) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700237 // No supported volumes found, give user option to format
238 final CharSequence title = mContext.getString(
Jeff Sharkey52fc3c0f2015-06-14 20:58:54 -0700239 R.string.ext_media_unsupported_notification_title, disk.getDescription());
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700240 final CharSequence text = mContext.getString(
Jeff Sharkey52fc3c0f2015-06-14 20:58:54 -0700241 R.string.ext_media_unsupported_notification_message, disk.getDescription());
San Mehat64e6a452010-02-04 20:53:48 -0800242
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500243 Notification.Builder builder =
244 new Notification.Builder(mContext, NotificationChannels.STORAGE)
245 .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
246 .setColor(mContext.getColor(R.color.system_notification_accent_color))
247 .setContentTitle(title)
248 .setContentText(text)
249 .setContentIntent(buildInitPendingIntent(disk))
250 .setStyle(new Notification.BigTextStyle().bigText(text))
251 .setVisibility(Notification.VISIBILITY_PUBLIC)
252 .setLocalOnly(true)
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800253 .setCategory(Notification.CATEGORY_ERROR)
254 .extend(new Notification.TvExtender());
Julia Reynolds037d8082018-03-18 15:25:19 -0400255 SystemUI.overrideNotificationAppName(mContext, builder, false);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700256
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500257 mNotificationManager.notifyAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
258 builder.build(), UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700259
260 } else {
261 // Yay, we have volumes!
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500262 mNotificationManager.cancelAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
263 UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700264 }
265 }
266
Philip P. Moltmann75b230b2016-04-11 15:27:58 -0700267 /**
268 * Remove all notifications for a disk when it goes away.
269 *
270 * @param disk The disk that went away.
271 */
272 private void onDiskDestroyedInternal(@NonNull DiskInfo disk) {
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500273 mNotificationManager.cancelAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
274 UserHandle.ALL);
Philip P. Moltmann75b230b2016-04-11 15:27:58 -0700275 }
276
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700277 private void onVolumeStateChangedInternal(VolumeInfo vol) {
278 switch (vol.getType()) {
279 case VolumeInfo.TYPE_PRIVATE:
280 onPrivateVolumeStateChangedInternal(vol);
281 break;
282 case VolumeInfo.TYPE_PUBLIC:
283 onPublicVolumeStateChangedInternal(vol);
284 break;
285 }
286 }
287
288 private void onPrivateVolumeStateChangedInternal(VolumeInfo vol) {
289 Log.d(TAG, "Notifying about private volume: " + vol.toString());
290
291 updateMissingPrivateVolumes();
292 }
293
294 private void onPublicVolumeStateChangedInternal(VolumeInfo vol) {
295 Log.d(TAG, "Notifying about public volume: " + vol.toString());
San Mehat64e6a452010-02-04 20:53:48 -0800296
Agatha Man74d8c092020-05-28 09:30:47 -0700297 // Volume state change event may come from removed user, in this case, mountedUserId will
298 // equals to UserHandle.USER_NULL (-10000) which will do nothing when call cancelAsUser(),
299 // but cause crash when call notifyAsUser(). Here we return directly for USER_NULL, and
300 // leave all notifications belong to removed user to NotificationManagerService, the latter
301 // will remove all notifications of the removed user when handles user stopped broadcast.
302 if (isAutomotive() && vol.getMountUserId() == UserHandle.USER_NULL) {
303 Log.d(TAG, "Ignore public volume state change event of removed user");
304 return;
305 }
306
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700307 final Notification notif;
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700308 switch (vol.getState()) {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700309 case VolumeInfo.STATE_UNMOUNTED:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700310 notif = onVolumeUnmounted(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700311 break;
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700312 case VolumeInfo.STATE_CHECKING:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700313 notif = onVolumeChecking(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700314 break;
315 case VolumeInfo.STATE_MOUNTED:
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700316 case VolumeInfo.STATE_MOUNTED_READ_ONLY:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700317 notif = onVolumeMounted(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700318 break;
319 case VolumeInfo.STATE_FORMATTING:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700320 notif = onVolumeFormatting(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700321 break;
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700322 case VolumeInfo.STATE_EJECTING:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700323 notif = onVolumeEjecting(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700324 break;
325 case VolumeInfo.STATE_UNMOUNTABLE:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700326 notif = onVolumeUnmountable(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700327 break;
328 case VolumeInfo.STATE_REMOVED:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700329 notif = onVolumeRemoved(vol);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700330 break;
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700331 case VolumeInfo.STATE_BAD_REMOVAL:
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700332 notif = onVolumeBadRemoval(vol);
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700333 break;
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700334 default:
335 notif = null;
336 break;
337 }
338
339 if (notif != null) {
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500340 mNotificationManager.notifyAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
Jeff Sharkeyf8543802018-03-28 10:31:55 -0600341 notif, UserHandle.of(vol.getMountUserId()));
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700342 } else {
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500343 mNotificationManager.cancelAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
Jeff Sharkeyf8543802018-03-28 10:31:55 -0600344 UserHandle.of(vol.getMountUserId()));
San Mehat64e6a452010-02-04 20:53:48 -0800345 }
346 }
347
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700348 private Notification onVolumeUnmounted(VolumeInfo vol) {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700349 // Ignored
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700350 return null;
San Mehat64e6a452010-02-04 20:53:48 -0800351 }
352
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700353 private Notification onVolumeChecking(VolumeInfo vol) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700354 final DiskInfo disk = vol.getDisk();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700355 final CharSequence title = mContext.getString(
356 R.string.ext_media_checking_notification_title, disk.getDescription());
357 final CharSequence text = mContext.getString(
358 R.string.ext_media_checking_notification_message, disk.getDescription());
San Mehat64e6a452010-02-04 20:53:48 -0800359
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700360 return buildNotificationBuilder(vol, title, text)
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700361 .setCategory(Notification.CATEGORY_PROGRESS)
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700362 .setOngoing(true)
363 .build();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700364 }
San Mehat64e6a452010-02-04 20:53:48 -0800365
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700366 private Notification onVolumeMounted(VolumeInfo vol) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700367 final VolumeRecord rec = mStorageManager.findRecordByUuid(vol.getFsUuid());
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700368 final DiskInfo disk = vol.getDisk();
Makoto Onukib138cb22015-06-23 17:32:02 -0700369
370 // Don't annoy when user dismissed in past. (But make sure the disk is adoptable; we
371 // used to allow snoozing non-adoptable disks too.)
372 if (rec.isSnoozed() && disk.isAdoptable()) {
373 return null;
374 }
375
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700376 if (disk.isAdoptable() && !rec.isInited()) {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700377 final CharSequence title = disk.getDescription();
378 final CharSequence text = mContext.getString(
379 R.string.ext_media_new_notification_message, disk.getDescription());
San Mehat64e6a452010-02-04 20:53:48 -0800380
Jeff Sharkey50a05452015-04-29 11:24:52 -0700381 final PendingIntent initIntent = buildInitPendingIntent(vol);
Heemin Seog1791d982020-05-07 16:38:40 -0700382 final PendingIntent unmountIntent = buildUnmountPendingIntent(vol);
John Spurlock209bede2013-07-17 12:23:27 -0400383
Heemin Seog1791d982020-05-07 16:38:40 -0700384 if (isAutomotive()) {
385 return buildNotificationBuilder(vol, title, text)
386 .setContentIntent(unmountIntent)
387 .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
388 .build();
389 } else {
390 return buildNotificationBuilder(vol, title, text)
391 .addAction(new Action(R.drawable.ic_settings_24dp,
392 mContext.getString(R.string.ext_media_init_action), initIntent))
393 .addAction(new Action(R.drawable.ic_eject_24dp,
394 mContext.getString(R.string.ext_media_unmount_action),
395 unmountIntent))
396 .setContentIntent(initIntent)
397 .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
398 .build();
399 }
San Mehat64e6a452010-02-04 20:53:48 -0800400 } else {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700401 final CharSequence title = disk.getDescription();
402 final CharSequence text = mContext.getString(
403 R.string.ext_media_ready_notification_message, disk.getDescription());
404
Jeff Sharkey50a05452015-04-29 11:24:52 -0700405 final PendingIntent browseIntent = buildBrowsePendingIntent(vol);
Makoto Onukib138cb22015-06-23 17:32:02 -0700406 final Notification.Builder builder = buildNotificationBuilder(vol, title, text)
Jeff Sharkeya49d5fc2015-05-13 11:40:30 -0700407 .addAction(new Action(R.drawable.ic_folder_24dp,
408 mContext.getString(R.string.ext_media_browse_action),
Jeff Sharkey50a05452015-04-29 11:24:52 -0700409 browseIntent))
Jeff Sharkeya49d5fc2015-05-13 11:40:30 -0700410 .addAction(new Action(R.drawable.ic_eject_24dp,
411 mContext.getString(R.string.ext_media_unmount_action),
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700412 buildUnmountPendingIntent(vol)))
Dmitri Plotnikovb2653e62017-04-11 11:45:00 -0700413 .setContentIntent(browseIntent)
Dan Sandler8e032e12017-01-25 13:41:38 -0500414 .setCategory(Notification.CATEGORY_SYSTEM);
Makoto Onukib138cb22015-06-23 17:32:02 -0700415 // Non-adoptable disks can't be snoozed.
416 if (disk.isAdoptable()) {
417 builder.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()));
418 }
419
420 return builder.build();
San Mehat64e6a452010-02-04 20:53:48 -0800421 }
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700422 }
423
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700424 private Notification onVolumeFormatting(VolumeInfo vol) {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700425 // Ignored
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700426 return null;
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700427 }
428
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700429 private Notification onVolumeEjecting(VolumeInfo vol) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700430 final DiskInfo disk = vol.getDisk();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700431 final CharSequence title = mContext.getString(
432 R.string.ext_media_unmounting_notification_title, disk.getDescription());
433 final CharSequence text = mContext.getString(
434 R.string.ext_media_unmounting_notification_message, disk.getDescription());
435
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700436 return buildNotificationBuilder(vol, title, text)
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700437 .setCategory(Notification.CATEGORY_PROGRESS)
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700438 .setOngoing(true)
439 .build();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700440 }
441
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700442 private Notification onVolumeUnmountable(VolumeInfo vol) {
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700443 final DiskInfo disk = vol.getDisk();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700444 final CharSequence title = mContext.getString(
445 R.string.ext_media_unmountable_notification_title, disk.getDescription());
446 final CharSequence text = mContext.getString(
447 R.string.ext_media_unmountable_notification_message, disk.getDescription());
Heemin Seog1791d982020-05-07 16:38:40 -0700448 PendingIntent action;
449 if (isAutomotive()) {
450 action = buildUnmountPendingIntent(vol);
451 } else {
452 action = buildInitPendingIntent(vol);
453 }
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700454
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700455 return buildNotificationBuilder(vol, title, text)
Heemin Seog1791d982020-05-07 16:38:40 -0700456 .setContentIntent(action)
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700457 .setCategory(Notification.CATEGORY_ERROR)
458 .build();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700459 }
460
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700461 private Notification onVolumeRemoved(VolumeInfo vol) {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700462 if (!vol.isPrimary()) {
463 // Ignore non-primary media
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700464 return null;
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700465 }
466
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700467 final DiskInfo disk = vol.getDisk();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700468 final CharSequence title = mContext.getString(
469 R.string.ext_media_nomedia_notification_title, disk.getDescription());
470 final CharSequence text = mContext.getString(
471 R.string.ext_media_nomedia_notification_message, disk.getDescription());
472
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700473 return buildNotificationBuilder(vol, title, text)
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700474 .setCategory(Notification.CATEGORY_ERROR)
475 .build();
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700476 }
477
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700478 private Notification onVolumeBadRemoval(VolumeInfo vol) {
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700479 if (!vol.isPrimary()) {
480 // Ignore non-primary media
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700481 return null;
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700482 }
483
Jeff Sharkey27de30d2015-04-18 16:20:27 -0700484 final DiskInfo disk = vol.getDisk();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700485 final CharSequence title = mContext.getString(
486 R.string.ext_media_badremoval_notification_title, disk.getDescription());
487 final CharSequence text = mContext.getString(
488 R.string.ext_media_badremoval_notification_message, disk.getDescription());
489
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700490 return buildNotificationBuilder(vol, title, text)
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700491 .setCategory(Notification.CATEGORY_ERROR)
492 .build();
Jeff Sharkey7e92ef32015-04-17 17:35:07 -0700493 }
494
Jeff Sharkey50a05452015-04-29 11:24:52 -0700495 private void onMoveProgress(MoveInfo move, int status, long estMillis) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700496 final CharSequence title;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700497 if (!TextUtils.isEmpty(move.label)) {
498 title = mContext.getString(R.string.ext_media_move_specific_title, move.label);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700499 } else {
500 title = mContext.getString(R.string.ext_media_move_title);
501 }
502
503 final CharSequence text;
504 if (estMillis < 0) {
505 text = null;
506 } else {
507 text = DateUtils.formatDuration(estMillis);
508 }
509
Jeff Sharkey50a05452015-04-29 11:24:52 -0700510 final PendingIntent intent;
511 if (move.packageName != null) {
512 intent = buildWizardMovePendingIntent(move);
513 } else {
514 intent = buildWizardMigratePendingIntent(move);
515 }
516
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500517 Notification.Builder builder =
518 new Notification.Builder(mContext, NotificationChannels.STORAGE)
519 .setSmallIcon(R.drawable.ic_sd_card_48dp)
520 .setColor(mContext.getColor(R.color.system_notification_accent_color))
521 .setContentTitle(title)
522 .setContentText(text)
523 .setContentIntent(intent)
524 .setStyle(new Notification.BigTextStyle().bigText(text))
525 .setVisibility(Notification.VISIBILITY_PUBLIC)
526 .setLocalOnly(true)
527 .setCategory(Notification.CATEGORY_PROGRESS)
528 .setProgress(100, status, false)
529 .setOngoing(true);
Julia Reynolds037d8082018-03-18 15:25:19 -0400530 SystemUI.overrideNotificationAppName(mContext, builder, false);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700531
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500532 mNotificationManager.notifyAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
Adrian Roose25c18d2016-06-17 15:59:49 -0700533 builder.build(), UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700534 }
535
Jeff Sharkey50a05452015-04-29 11:24:52 -0700536 private void onMoveFinished(MoveInfo move, int status) {
537 if (move.packageName != null) {
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700538 // We currently ignore finished app moves; just clear the last
539 // published progress
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500540 mNotificationManager.cancelAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
541 UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700542 return;
543 }
544
Jeff Sharkey50a05452015-04-29 11:24:52 -0700545 final VolumeInfo privateVol = mContext.getPackageManager().getPrimaryStorageCurrentVolume();
546 final String descrip = mStorageManager.getBestVolumeDescription(privateVol);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700547
548 final CharSequence title;
549 final CharSequence text;
550 if (status == PackageManager.MOVE_SUCCEEDED) {
551 title = mContext.getString(R.string.ext_media_move_success_title);
552 text = mContext.getString(R.string.ext_media_move_success_message, descrip);
553 } else {
554 title = mContext.getString(R.string.ext_media_move_failure_title);
555 text = mContext.getString(R.string.ext_media_move_failure_message);
556 }
557
Jeff Sharkey50a05452015-04-29 11:24:52 -0700558 // Jump back into the wizard flow if we moved to a real disk
559 final PendingIntent intent;
560 if (privateVol != null && privateVol.getDisk() != null) {
561 intent = buildWizardReadyPendingIntent(privateVol.getDisk());
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700562 } else if (privateVol != null) {
Jeff Sharkey50a05452015-04-29 11:24:52 -0700563 intent = buildVolumeSettingsPendingIntent(privateVol);
Jeff Sharkeyef10ee02015-07-05 14:17:27 -0700564 } else {
565 intent = null;
Jeff Sharkey50a05452015-04-29 11:24:52 -0700566 }
567
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500568 Notification.Builder builder =
569 new Notification.Builder(mContext, NotificationChannels.STORAGE)
570 .setSmallIcon(R.drawable.ic_sd_card_48dp)
571 .setColor(mContext.getColor(R.color.system_notification_accent_color))
572 .setContentTitle(title)
573 .setContentText(text)
574 .setContentIntent(intent)
575 .setStyle(new Notification.BigTextStyle().bigText(text))
576 .setVisibility(Notification.VISIBILITY_PUBLIC)
577 .setLocalOnly(true)
578 .setCategory(Notification.CATEGORY_SYSTEM)
579 .setAutoCancel(true);
Julia Reynolds037d8082018-03-18 15:25:19 -0400580 SystemUI.overrideNotificationAppName(mContext, builder, false);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700581
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500582 mNotificationManager.notifyAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
583 builder.build(), UserHandle.ALL);
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700584 }
585
586 private int getSmallIcon(DiskInfo disk, int state) {
587 if (disk.isSd()) {
588 switch (state) {
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700589 case VolumeInfo.STATE_CHECKING:
590 case VolumeInfo.STATE_EJECTING:
Jeff Sharkeya49d5fc2015-05-13 11:40:30 -0700591 return R.drawable.ic_sd_card_48dp;
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700592 default:
Jeff Sharkeya49d5fc2015-05-13 11:40:30 -0700593 return R.drawable.ic_sd_card_48dp;
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700594 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700595 } else if (disk.isUsb()) {
Jeff Sharkeya49d5fc2015-05-13 11:40:30 -0700596 return R.drawable.ic_usb_48dp;
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700597 } else {
Jeff Sharkeya49d5fc2015-05-13 11:40:30 -0700598 return R.drawable.ic_sd_card_48dp;
Jeff Sharkeye6c04f92015-04-18 21:38:05 -0700599 }
600 }
601
602 private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
603 CharSequence text) {
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500604 Notification.Builder builder =
605 new Notification.Builder(mContext, NotificationChannels.STORAGE)
606 .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
607 .setColor(mContext.getColor(R.color.system_notification_accent_color))
608 .setContentTitle(title)
609 .setContentText(text)
610 .setStyle(new Notification.BigTextStyle().bigText(text))
611 .setVisibility(Notification.VISIBILITY_PUBLIC)
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800612 .setLocalOnly(true)
613 .extend(new Notification.TvExtender());
Julia Reynolds037d8082018-03-18 15:25:19 -0400614 overrideNotificationAppName(mContext, builder, false);
Adrian Roose25c18d2016-06-17 15:59:49 -0700615 return builder;
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700616 }
617
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700618 private PendingIntent buildInitPendingIntent(DiskInfo disk) {
619 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800620 if (isTv()) {
621 intent.setPackage("com.android.tv.settings");
622 intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
Agatha Man3f287f22020-03-26 09:53:56 -0700623 } else if (isAutomotive()) {
624 // TODO(b/151671685): add intent to handle unsupported usb
625 return null;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800626 } else {
627 intent.setClassName("com.android.settings",
628 "com.android.settings.deviceinfo.StorageWizardInit");
629 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700630 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId());
631
632 final int requestKey = disk.getId().hashCode();
633 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
634 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
635 }
636
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700637 private PendingIntent buildInitPendingIntent(VolumeInfo vol) {
638 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800639 if (isTv()) {
640 intent.setPackage("com.android.tv.settings");
641 intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
Agatha Man3f287f22020-03-26 09:53:56 -0700642 } else if (isAutomotive()) {
643 // TODO(b/151671685): add intent to handle unmountable usb
644 return null;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800645 } else {
646 intent.setClassName("com.android.settings",
647 "com.android.settings.deviceinfo.StorageWizardInit");
648 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700649 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
650
651 final int requestKey = vol.getId().hashCode();
652 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
653 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700654 }
655
656 private PendingIntent buildUnmountPendingIntent(VolumeInfo vol) {
657 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800658 if (isTv()) {
659 intent.setPackage("com.android.tv.settings");
660 intent.setAction("com.android.tv.settings.action.UNMOUNT_STORAGE");
661 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700662
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800663 final int requestKey = vol.getId().hashCode();
664 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
665 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
Heemin Seog91fab5c2019-06-17 15:11:27 -0700666 } else if (isAutomotive()) {
667 intent.setClassName("com.android.car.settings",
668 "com.android.car.settings.storage.StorageUnmountReceiver");
669 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
670
671 final int requestKey = vol.getId().hashCode();
672 return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
673 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800674 } else {
675 intent.setClassName("com.android.settings",
676 "com.android.settings.deviceinfo.StorageUnmountReceiver");
677 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
678
679 final int requestKey = vol.getId().hashCode();
680 return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
681 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
682 }
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700683 }
684
685 private PendingIntent buildBrowsePendingIntent(VolumeInfo vol) {
Jeff Sharkeye3644412019-04-27 17:13:57 -0600686 final StrictMode.VmPolicy oldPolicy = StrictMode.allowVmViolations();
687 try {
688 final Intent intent = vol.buildBrowseIntentForUser(vol.getMountUserId());
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700689
Jeff Sharkeye3644412019-04-27 17:13:57 -0600690 final int requestKey = vol.getId().hashCode();
691 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
692 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
693 } finally {
694 StrictMode.setVmPolicy(oldPolicy);
695 }
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700696 }
697
Jeff Sharkey50a05452015-04-29 11:24:52 -0700698 private PendingIntent buildVolumeSettingsPendingIntent(VolumeInfo vol) {
Jeff Sharkey56bd3122015-04-14 10:30:34 -0700699 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800700 if (isTv()) {
701 intent.setPackage("com.android.tv.settings");
702 intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
Agatha Man3f287f22020-03-26 09:53:56 -0700703 } else if (isAutomotive()) {
704 // TODO(b/151671685): add volume settings intent for automotive
705 return null;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800706 } else {
707 switch (vol.getType()) {
708 case VolumeInfo.TYPE_PRIVATE:
709 intent.setClassName("com.android.settings",
710 "com.android.settings.Settings$PrivateVolumeSettingsActivity");
711 break;
712 case VolumeInfo.TYPE_PUBLIC:
713 intent.setClassName("com.android.settings",
714 "com.android.settings.Settings$PublicVolumeSettingsActivity");
715 break;
716 default:
717 return null;
718 }
Jeff Sharkey50a05452015-04-29 11:24:52 -0700719 }
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700720 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
721
722 final int requestKey = vol.getId().hashCode();
723 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
724 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
725 }
726
Jeff Sharkey52fc3c0f2015-06-14 20:58:54 -0700727 private PendingIntent buildSnoozeIntent(String fsUuid) {
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700728 final Intent intent = new Intent(ACTION_SNOOZE_VOLUME);
Jeff Sharkey52fc3c0f2015-06-14 20:58:54 -0700729 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, fsUuid);
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700730
Jeff Sharkey52fc3c0f2015-06-14 20:58:54 -0700731 final int requestKey = fsUuid.hashCode();
Jeff Sharkeyd95d3bf2015-04-14 21:39:44 -0700732 return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
733 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
San Mehat64e6a452010-02-04 20:53:48 -0800734 }
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700735
736 private PendingIntent buildForgetPendingIntent(VolumeRecord rec) {
Agatha Man3f287f22020-03-26 09:53:56 -0700737 // Not used on TV and Automotive
Jeff Sharkeyb36586a2015-04-27 08:42:28 -0700738 final Intent intent = new Intent();
739 intent.setClassName("com.android.settings",
740 "com.android.settings.Settings$PrivateVolumeForgetActivity");
741 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, rec.getFsUuid());
742
743 final int requestKey = rec.getFsUuid().hashCode();
744 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
745 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
746 }
Jeff Sharkey50a05452015-04-29 11:24:52 -0700747
748 private PendingIntent buildWizardMigratePendingIntent(MoveInfo move) {
749 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800750 if (isTv()) {
751 intent.setPackage("com.android.tv.settings");
752 intent.setAction("com.android.tv.settings.action.MIGRATE_STORAGE");
Agatha Man3f287f22020-03-26 09:53:56 -0700753 } else if (isAutomotive()) {
754 // TODO(b/151671685): add storage migrate intent for automotive
755 return null;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800756 } else {
757 intent.setClassName("com.android.settings",
758 "com.android.settings.deviceinfo.StorageWizardMigrateProgress");
759 }
Jeff Sharkey50a05452015-04-29 11:24:52 -0700760 intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId);
761
762 final VolumeInfo vol = mStorageManager.findVolumeByQualifiedUuid(move.volumeUuid);
Suprabh Shuklaaf6c4192016-04-27 14:05:54 -0700763 if (vol != null) {
764 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
765 }
Jeff Sharkey50a05452015-04-29 11:24:52 -0700766 return PendingIntent.getActivityAsUser(mContext, move.moveId, intent,
767 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
768 }
769
770 private PendingIntent buildWizardMovePendingIntent(MoveInfo move) {
771 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800772 if (isTv()) {
773 intent.setPackage("com.android.tv.settings");
774 intent.setAction("com.android.tv.settings.action.MOVE_APP");
Agatha Man3f287f22020-03-26 09:53:56 -0700775 } else if (isAutomotive()) {
776 // TODO(b/151671685): add storage move intent for automotive
777 return null;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800778 } else {
779 intent.setClassName("com.android.settings",
780 "com.android.settings.deviceinfo.StorageWizardMoveProgress");
781 }
Jeff Sharkey50a05452015-04-29 11:24:52 -0700782 intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId);
783
784 return PendingIntent.getActivityAsUser(mContext, move.moveId, intent,
785 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
786 }
787
788 private PendingIntent buildWizardReadyPendingIntent(DiskInfo disk) {
789 final Intent intent = new Intent();
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800790 if (isTv()) {
791 intent.setPackage("com.android.tv.settings");
792 intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
Agatha Man3f287f22020-03-26 09:53:56 -0700793 } else if (isAutomotive()) {
794 // TODO(b/151671685): add storage ready intent for automotive
795 return null;
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800796 } else {
797 intent.setClassName("com.android.settings",
798 "com.android.settings.deviceinfo.StorageWizardReady");
799 }
Jeff Sharkey50a05452015-04-29 11:24:52 -0700800 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId());
801
802 final int requestKey = disk.getId().hashCode();
803 return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
804 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
805 }
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800806
Heemin Seog91fab5c2019-06-17 15:11:27 -0700807 private boolean isAutomotive() {
808 PackageManager packageManager = mContext.getPackageManager();
809 return packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
810 }
811
Dmitri Plotnikov519c0882017-02-13 14:37:05 -0800812 private boolean isTv() {
813 PackageManager packageManager = mContext.getPackageManager();
814 return packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
815 }
San Mehat64e6a452010-02-04 20:53:48 -0800816}