1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 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 17 package com.android.systemui.usb; 18 19 import android.app.Notification; 20 import android.app.Notification.Action; 21 import android.app.NotificationManager; 22 import android.app.PendingIntent; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.PackageManager; 28 import android.content.pm.PackageManager.MoveCallback; 29 import android.os.Bundle; 30 import android.os.Handler; 31 import android.os.UserHandle; 32 import android.os.storage.DiskInfo; 33 import android.os.storage.StorageEventListener; 34 import android.os.storage.StorageManager; 35 import android.os.storage.VolumeInfo; 36 import android.os.storage.VolumeRecord; 37 import android.text.TextUtils; 38 import android.text.format.DateUtils; 39 import android.util.Log; 40 import android.util.SparseArray; 41 42 import com.android.internal.R; 43 import com.android.systemui.SystemUI; 44 45 import java.util.List; 46 47 public class StorageNotification extends SystemUI { 48 private static final String TAG = "StorageNotification"; 49 50 private static final int PUBLIC_ID = 0x53505542; // SPUB 51 private static final int PRIVATE_ID = 0x53505256; // SPRV 52 private static final int DISK_ID = 0x5344534b; // SDSK 53 private static final int MOVE_ID = 0x534d4f56; // SMOV 54 55 private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME"; 56 private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD"; 57 58 // TODO: delay some notifications to avoid bumpy fast operations 59 60 private NotificationManager mNotificationManager; 61 private StorageManager mStorageManager; 62 63 private static class MoveInfo { 64 public int moveId; 65 public Bundle extras; 66 public String packageName; 67 public String label; 68 public String volumeUuid; 69 } 70 71 private final SparseArray<MoveInfo> mMoves = new SparseArray<>(); 72 73 private final StorageEventListener mListener = new StorageEventListener() { 74 @Override 75 public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { 76 onVolumeStateChangedInternal(vol); 77 } 78 79 @Override 80 public void onVolumeRecordChanged(VolumeRecord rec) { 81 // Avoid kicking notifications when getting early metadata before 82 // mounted. If already mounted, we're being kicked because of a 83 // nickname or init'ed change. 84 final VolumeInfo vol = mStorageManager.findVolumeByUuid(rec.getFsUuid()); 85 if (vol != null && vol.isMountedReadable()) { 86 onVolumeStateChangedInternal(vol); 87 } 88 } 89 90 @Override 91 public void onVolumeForgotten(String fsUuid) { 92 // Stop annoying the user 93 mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL); 94 } 95 96 @Override 97 public void onDiskScanned(DiskInfo disk, int volumeCount) { 98 onDiskScannedInternal(disk, volumeCount); 99 } 100 }; 101 102 private final BroadcastReceiver mSnoozeReceiver = new BroadcastReceiver() { 103 @Override 104 public void onReceive(Context context, Intent intent) { 105 // TODO: kick this onto background thread 106 final String fsUuid = intent.getStringExtra(VolumeRecord.EXTRA_FS_UUID); 107 mStorageManager.setVolumeSnoozed(fsUuid, true); 108 } 109 }; 110 111 private final BroadcastReceiver mFinishReceiver = new BroadcastReceiver() { 112 @Override 113 public void onReceive(Context context, Intent intent) { 114 // When finishing the adoption wizard, clean up any notifications 115 // for moving primary storage 116 mNotificationManager.cancelAsUser(null, MOVE_ID, UserHandle.ALL); 117 } 118 }; 119 120 private final MoveCallback mMoveCallback = new MoveCallback() { 121 @Override 122 public void onCreated(int moveId, Bundle extras) { 123 final MoveInfo move = new MoveInfo(); 124 move.moveId = moveId; 125 move.extras = extras; 126 if (extras != null) { 127 move.packageName = extras.getString(Intent.EXTRA_PACKAGE_NAME); 128 move.label = extras.getString(Intent.EXTRA_TITLE); 129 move.volumeUuid = extras.getString(VolumeRecord.EXTRA_FS_UUID); 130 } 131 mMoves.put(moveId, move); 132 } 133 134 @Override 135 public void onStatusChanged(int moveId, int status, long estMillis) { 136 final MoveInfo move = mMoves.get(moveId); 137 if (move == null) { 138 Log.w(TAG, "Ignoring unknown move " + moveId); 139 return; 140 } 141 142 if (PackageManager.isMoveStatusFinished(status)) { 143 onMoveFinished(move, status); 144 } else { 145 onMoveProgress(move, status, estMillis); 146 } 147 } 148 }; 149 150 @Override 151 public void start() { 152 mNotificationManager = mContext.getSystemService(NotificationManager.class); 153 154 mStorageManager = mContext.getSystemService(StorageManager.class); 155 mStorageManager.registerListener(mListener); 156 157 mContext.registerReceiver(mSnoozeReceiver, new IntentFilter(ACTION_SNOOZE_VOLUME), 158 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null); 159 mContext.registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_WIZARD), 160 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null); 161 162 // Kick current state into place 163 final List<DiskInfo> disks = mStorageManager.getDisks(); 164 for (DiskInfo disk : disks) { 165 onDiskScannedInternal(disk, disk.volumeCount); 166 } 167 168 final List<VolumeInfo> vols = mStorageManager.getVolumes(); 169 for (VolumeInfo vol : vols) { 170 onVolumeStateChangedInternal(vol); 171 } 172 173 mContext.getPackageManager().registerMoveCallback(mMoveCallback, new Handler()); 174 175 updateMissingPrivateVolumes(); 176 } 177 178 private void updateMissingPrivateVolumes() { 179 final List<VolumeRecord> recs = mStorageManager.getVolumeRecords(); 180 for (VolumeRecord rec : recs) { 181 if (rec.getType() != VolumeInfo.TYPE_PRIVATE) continue; 182 183 final String fsUuid = rec.getFsUuid(); 184 final VolumeInfo info = mStorageManager.findVolumeByUuid(fsUuid); 185 if ((info != null && info.isMountedWritable()) || rec.isSnoozed()) { 186 // Yay, private volume is here, or user snoozed 187 mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL); 188 189 } else { 190 // Boo, annoy the user to reinsert the private volume 191 final CharSequence title = mContext.getString(R.string.ext_media_missing_title, 192 rec.getNickname()); 193 final CharSequence text = mContext.getString(R.string.ext_media_missing_message); 194 195 final Notification notif = new Notification.Builder(mContext) 196 .setSmallIcon(R.drawable.ic_sd_card_48dp) 197 .setColor(mContext.getColor(R.color.system_notification_accent_color)) 198 .setContentTitle(title) 199 .setContentText(text) 200 .setContentIntent(buildForgetPendingIntent(rec)) 201 .setStyle(new Notification.BigTextStyle().bigText(text)) 202 .setVisibility(Notification.VISIBILITY_PUBLIC) 203 .setLocalOnly(true) 204 .setCategory(Notification.CATEGORY_SYSTEM) 205 .setDeleteIntent(buildSnoozeIntent(fsUuid)) 206 .build(); 207 208 mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, notif, UserHandle.ALL); 209 } 210 } 211 } 212 213 private void onDiskScannedInternal(DiskInfo disk, int volumeCount) { 214 if (volumeCount == 0 && disk.size > 0) { 215 // No supported volumes found, give user option to format 216 final CharSequence title = mContext.getString( 217 R.string.ext_media_unsupported_notification_title, disk.getDescription()); 218 final CharSequence text = mContext.getString( 219 R.string.ext_media_unsupported_notification_message, disk.getDescription()); 220 221 final Notification notif = new Notification.Builder(mContext) 222 .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE)) 223 .setColor(mContext.getColor(R.color.system_notification_accent_color)) 224 .setContentTitle(title) 225 .setContentText(text) 226 .setContentIntent(buildInitPendingIntent(disk)) 227 .setStyle(new Notification.BigTextStyle().bigText(text)) 228 .setVisibility(Notification.VISIBILITY_PUBLIC) 229 .setLocalOnly(true) 230 .setCategory(Notification.CATEGORY_ERROR) 231 .build(); 232 233 mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, notif, UserHandle.ALL); 234 235 } else { 236 // Yay, we have volumes! 237 mNotificationManager.cancelAsUser(disk.getId(), DISK_ID, UserHandle.ALL); 238 } 239 } 240 241 private void onVolumeStateChangedInternal(VolumeInfo vol) { 242 switch (vol.getType()) { 243 case VolumeInfo.TYPE_PRIVATE: 244 onPrivateVolumeStateChangedInternal(vol); 245 break; 246 case VolumeInfo.TYPE_PUBLIC: 247 onPublicVolumeStateChangedInternal(vol); 248 break; 249 } 250 } 251 252 private void onPrivateVolumeStateChangedInternal(VolumeInfo vol) { 253 Log.d(TAG, "Notifying about private volume: " + vol.toString()); 254 255 updateMissingPrivateVolumes(); 256 } 257 258 private void onPublicVolumeStateChangedInternal(VolumeInfo vol) { 259 Log.d(TAG, "Notifying about public volume: " + vol.toString()); 260 261 final Notification notif; 262 switch (vol.getState()) { 263 case VolumeInfo.STATE_UNMOUNTED: 264 notif = onVolumeUnmounted(vol); 265 break; 266 case VolumeInfo.STATE_CHECKING: 267 notif = onVolumeChecking(vol); 268 break; 269 case VolumeInfo.STATE_MOUNTED: 270 case VolumeInfo.STATE_MOUNTED_READ_ONLY: 271 notif = onVolumeMounted(vol); 272 break; 273 case VolumeInfo.STATE_FORMATTING: 274 notif = onVolumeFormatting(vol); 275 break; 276 case VolumeInfo.STATE_EJECTING: 277 notif = onVolumeEjecting(vol); 278 break; 279 case VolumeInfo.STATE_UNMOUNTABLE: 280 notif = onVolumeUnmountable(vol); 281 break; 282 case VolumeInfo.STATE_REMOVED: 283 notif = onVolumeRemoved(vol); 284 break; 285 case VolumeInfo.STATE_BAD_REMOVAL: 286 notif = onVolumeBadRemoval(vol); 287 break; 288 default: 289 notif = null; 290 break; 291 } 292 293 if (notif != null) { 294 mNotificationManager.notifyAsUser(vol.getId(), PUBLIC_ID, notif, UserHandle.ALL); 295 } else { 296 mNotificationManager.cancelAsUser(vol.getId(), PUBLIC_ID, UserHandle.ALL); 297 } 298 } 299 300 private Notification onVolumeUnmounted(VolumeInfo vol) { 301 // Ignored 302 return null; 303 } 304 305 private Notification onVolumeChecking(VolumeInfo vol) { 306 final DiskInfo disk = vol.getDisk(); 307 final CharSequence title = mContext.getString( 308 R.string.ext_media_checking_notification_title, disk.getDescription()); 309 final CharSequence text = mContext.getString( 310 R.string.ext_media_checking_notification_message, disk.getDescription()); 311 312 return buildNotificationBuilder(vol, title, text) 313 .setCategory(Notification.CATEGORY_PROGRESS) 314 .setPriority(Notification.PRIORITY_LOW) 315 .setOngoing(true) 316 .build(); 317 } 318 319 private Notification onVolumeMounted(VolumeInfo vol) { 320 final VolumeRecord rec = mStorageManager.findRecordByUuid(vol.getFsUuid()); 321 final DiskInfo disk = vol.getDisk(); 322 323 // Don't annoy when user dismissed in past. (But make sure the disk is adoptable; we 324 // used to allow snoozing non-adoptable disks too.) 325 if (rec.isSnoozed() && disk.isAdoptable()) { 326 return null; 327 } 328 329 if (disk.isAdoptable() && !rec.isInited()) { 330 final CharSequence title = disk.getDescription(); 331 final CharSequence text = mContext.getString( 332 R.string.ext_media_new_notification_message, disk.getDescription()); 333 334 final PendingIntent initIntent = buildInitPendingIntent(vol); 335 return buildNotificationBuilder(vol, title, text) 336 .addAction(new Action(R.drawable.ic_settings_24dp, 337 mContext.getString(R.string.ext_media_init_action), initIntent)) 338 .addAction(new Action(R.drawable.ic_eject_24dp, 339 mContext.getString(R.string.ext_media_unmount_action), 340 buildUnmountPendingIntent(vol))) 341 .setContentIntent(initIntent) 342 .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid())) 343 .setCategory(Notification.CATEGORY_SYSTEM) 344 .build(); 345 346 } else { 347 final CharSequence title = disk.getDescription(); 348 final CharSequence text = mContext.getString( 349 R.string.ext_media_ready_notification_message, disk.getDescription()); 350 351 final PendingIntent browseIntent = buildBrowsePendingIntent(vol); 352 final Notification.Builder builder = buildNotificationBuilder(vol, title, text) 353 .addAction(new Action(R.drawable.ic_folder_24dp, 354 mContext.getString(R.string.ext_media_browse_action), 355 browseIntent)) 356 .addAction(new Action(R.drawable.ic_eject_24dp, 357 mContext.getString(R.string.ext_media_unmount_action), 358 buildUnmountPendingIntent(vol))) 359 .setContentIntent(browseIntent) 360 .setCategory(Notification.CATEGORY_SYSTEM) 361 .setPriority(Notification.PRIORITY_LOW); 362 // Non-adoptable disks can't be snoozed. 363 if (disk.isAdoptable()) { 364 builder.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid())); 365 } 366 367 return builder.build(); 368 } 369 } 370 371 private Notification onVolumeFormatting(VolumeInfo vol) { 372 // Ignored 373 return null; 374 } 375 376 private Notification onVolumeEjecting(VolumeInfo vol) { 377 final DiskInfo disk = vol.getDisk(); 378 final CharSequence title = mContext.getString( 379 R.string.ext_media_unmounting_notification_title, disk.getDescription()); 380 final CharSequence text = mContext.getString( 381 R.string.ext_media_unmounting_notification_message, disk.getDescription()); 382 383 return buildNotificationBuilder(vol, title, text) 384 .setCategory(Notification.CATEGORY_PROGRESS) 385 .setPriority(Notification.PRIORITY_LOW) 386 .setOngoing(true) 387 .build(); 388 } 389 390 private Notification onVolumeUnmountable(VolumeInfo vol) { 391 final DiskInfo disk = vol.getDisk(); 392 final CharSequence title = mContext.getString( 393 R.string.ext_media_unmountable_notification_title, disk.getDescription()); 394 final CharSequence text = mContext.getString( 395 R.string.ext_media_unmountable_notification_message, disk.getDescription()); 396 397 return buildNotificationBuilder(vol, title, text) 398 .setContentIntent(buildInitPendingIntent(vol)) 399 .setCategory(Notification.CATEGORY_ERROR) 400 .build(); 401 } 402 403 private Notification onVolumeRemoved(VolumeInfo vol) { 404 if (!vol.isPrimary()) { 405 // Ignore non-primary media 406 return null; 407 } 408 409 final DiskInfo disk = vol.getDisk(); 410 final CharSequence title = mContext.getString( 411 R.string.ext_media_nomedia_notification_title, disk.getDescription()); 412 final CharSequence text = mContext.getString( 413 R.string.ext_media_nomedia_notification_message, disk.getDescription()); 414 415 return buildNotificationBuilder(vol, title, text) 416 .setCategory(Notification.CATEGORY_ERROR) 417 .build(); 418 } 419 420 private Notification onVolumeBadRemoval(VolumeInfo vol) { 421 if (!vol.isPrimary()) { 422 // Ignore non-primary media 423 return null; 424 } 425 426 final DiskInfo disk = vol.getDisk(); 427 final CharSequence title = mContext.getString( 428 R.string.ext_media_badremoval_notification_title, disk.getDescription()); 429 final CharSequence text = mContext.getString( 430 R.string.ext_media_badremoval_notification_message, disk.getDescription()); 431 432 return buildNotificationBuilder(vol, title, text) 433 .setCategory(Notification.CATEGORY_ERROR) 434 .build(); 435 } 436 437 private void onMoveProgress(MoveInfo move, int status, long estMillis) { 438 final CharSequence title; 439 if (!TextUtils.isEmpty(move.label)) { 440 title = mContext.getString(R.string.ext_media_move_specific_title, move.label); 441 } else { 442 title = mContext.getString(R.string.ext_media_move_title); 443 } 444 445 final CharSequence text; 446 if (estMillis < 0) { 447 text = null; 448 } else { 449 text = DateUtils.formatDuration(estMillis); 450 } 451 452 final PendingIntent intent; 453 if (move.packageName != null) { 454 intent = buildWizardMovePendingIntent(move); 455 } else { 456 intent = buildWizardMigratePendingIntent(move); 457 } 458 459 final Notification notif = new Notification.Builder(mContext) 460 .setSmallIcon(R.drawable.ic_sd_card_48dp) 461 .setColor(mContext.getColor(R.color.system_notification_accent_color)) 462 .setContentTitle(title) 463 .setContentText(text) 464 .setContentIntent(intent) 465 .setStyle(new Notification.BigTextStyle().bigText(text)) 466 .setVisibility(Notification.VISIBILITY_PUBLIC) 467 .setLocalOnly(true) 468 .setCategory(Notification.CATEGORY_PROGRESS) 469 .setPriority(Notification.PRIORITY_LOW) 470 .setProgress(100, status, false) 471 .setOngoing(true) 472 .build(); 473 474 mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, notif, UserHandle.ALL); 475 } 476 477 private void onMoveFinished(MoveInfo move, int status) { 478 if (move.packageName != null) { 479 // We currently ignore finished app moves; just clear the last 480 // published progress 481 mNotificationManager.cancelAsUser(move.packageName, MOVE_ID, UserHandle.ALL); 482 return; 483 } 484 485 final VolumeInfo privateVol = mContext.getPackageManager().getPrimaryStorageCurrentVolume(); 486 final String descrip = mStorageManager.getBestVolumeDescription(privateVol); 487 488 final CharSequence title; 489 final CharSequence text; 490 if (status == PackageManager.MOVE_SUCCEEDED) { 491 title = mContext.getString(R.string.ext_media_move_success_title); 492 text = mContext.getString(R.string.ext_media_move_success_message, descrip); 493 } else { 494 title = mContext.getString(R.string.ext_media_move_failure_title); 495 text = mContext.getString(R.string.ext_media_move_failure_message); 496 } 497 498 // Jump back into the wizard flow if we moved to a real disk 499 final PendingIntent intent; 500 if (privateVol != null && privateVol.getDisk() != null) { 501 intent = buildWizardReadyPendingIntent(privateVol.getDisk()); 502 } else if (privateVol != null) { 503 intent = buildVolumeSettingsPendingIntent(privateVol); 504 } else { 505 intent = null; 506 } 507 508 final Notification notif = new Notification.Builder(mContext) 509 .setSmallIcon(R.drawable.ic_sd_card_48dp) 510 .setColor(mContext.getColor(R.color.system_notification_accent_color)) 511 .setContentTitle(title) 512 .setContentText(text) 513 .setContentIntent(intent) 514 .setStyle(new Notification.BigTextStyle().bigText(text)) 515 .setVisibility(Notification.VISIBILITY_PUBLIC) 516 .setLocalOnly(true) 517 .setCategory(Notification.CATEGORY_SYSTEM) 518 .setPriority(Notification.PRIORITY_LOW) 519 .setAutoCancel(true) 520 .build(); 521 522 mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, notif, UserHandle.ALL); 523 } 524 525 private int getSmallIcon(DiskInfo disk, int state) { 526 if (disk.isSd()) { 527 switch (state) { 528 case VolumeInfo.STATE_CHECKING: 529 case VolumeInfo.STATE_EJECTING: 530 return R.drawable.ic_sd_card_48dp; 531 default: 532 return R.drawable.ic_sd_card_48dp; 533 } 534 } else if (disk.isUsb()) { 535 return R.drawable.ic_usb_48dp; 536 } else { 537 return R.drawable.ic_sd_card_48dp; 538 } 539 } 540 541 private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title, 542 CharSequence text) { 543 return new Notification.Builder(mContext) 544 .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState())) 545 .setColor(mContext.getColor(R.color.system_notification_accent_color)) 546 .setContentTitle(title) 547 .setContentText(text) 548 .setStyle(new Notification.BigTextStyle().bigText(text)) 549 .setVisibility(Notification.VISIBILITY_PUBLIC) 550 .setLocalOnly(true); 551 } 552 553 private PendingIntent buildInitPendingIntent(DiskInfo disk) { 554 final Intent intent = new Intent(); 555 intent.setClassName("com.android.settings", 556 "com.android.settings.deviceinfo.StorageWizardInit"); 557 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId()); 558 559 final int requestKey = disk.getId().hashCode(); 560 return PendingIntent.getActivityAsUser(mContext, requestKey, intent, 561 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 562 } 563 564 private PendingIntent buildInitPendingIntent(VolumeInfo vol) { 565 final Intent intent = new Intent(); 566 intent.setClassName("com.android.settings", 567 "com.android.settings.deviceinfo.StorageWizardInit"); 568 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); 569 570 final int requestKey = vol.getId().hashCode(); 571 return PendingIntent.getActivityAsUser(mContext, requestKey, intent, 572 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 573 } 574 575 private PendingIntent buildUnmountPendingIntent(VolumeInfo vol) { 576 final Intent intent = new Intent(); 577 intent.setClassName("com.android.settings", 578 "com.android.settings.deviceinfo.StorageUnmountReceiver"); 579 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); 580 581 final int requestKey = vol.getId().hashCode(); 582 return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent, 583 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT); 584 } 585 586 private PendingIntent buildBrowsePendingIntent(VolumeInfo vol) { 587 final Intent intent = vol.buildBrowseIntent(); 588 589 final int requestKey = vol.getId().hashCode(); 590 return PendingIntent.getActivityAsUser(mContext, requestKey, intent, 591 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 592 } 593 594 private PendingIntent buildVolumeSettingsPendingIntent(VolumeInfo vol) { 595 final Intent intent = new Intent(); 596 switch (vol.getType()) { 597 case VolumeInfo.TYPE_PRIVATE: 598 intent.setClassName("com.android.settings", 599 "com.android.settings.Settings$PrivateVolumeSettingsActivity"); 600 break; 601 case VolumeInfo.TYPE_PUBLIC: 602 intent.setClassName("com.android.settings", 603 "com.android.settings.Settings$PublicVolumeSettingsActivity"); 604 break; 605 default: 606 return null; 607 } 608 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); 609 610 final int requestKey = vol.getId().hashCode(); 611 return PendingIntent.getActivityAsUser(mContext, requestKey, intent, 612 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 613 } 614 615 private PendingIntent buildSnoozeIntent(String fsUuid) { 616 final Intent intent = new Intent(ACTION_SNOOZE_VOLUME); 617 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, fsUuid); 618 619 final int requestKey = fsUuid.hashCode(); 620 return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent, 621 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT); 622 } 623 624 private PendingIntent buildForgetPendingIntent(VolumeRecord rec) { 625 final Intent intent = new Intent(); 626 intent.setClassName("com.android.settings", 627 "com.android.settings.Settings$PrivateVolumeForgetActivity"); 628 intent.putExtra(VolumeRecord.EXTRA_FS_UUID, rec.getFsUuid()); 629 630 final int requestKey = rec.getFsUuid().hashCode(); 631 return PendingIntent.getActivityAsUser(mContext, requestKey, intent, 632 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 633 } 634 635 private PendingIntent buildWizardMigratePendingIntent(MoveInfo move) { 636 final Intent intent = new Intent(); 637 intent.setClassName("com.android.settings", 638 "com.android.settings.deviceinfo.StorageWizardMigrateProgress"); 639 intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId); 640 641 final VolumeInfo vol = mStorageManager.findVolumeByQualifiedUuid(move.volumeUuid); 642 intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); 643 644 return PendingIntent.getActivityAsUser(mContext, move.moveId, intent, 645 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 646 } 647 648 private PendingIntent buildWizardMovePendingIntent(MoveInfo move) { 649 final Intent intent = new Intent(); 650 intent.setClassName("com.android.settings", 651 "com.android.settings.deviceinfo.StorageWizardMoveProgress"); 652 intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId); 653 654 return PendingIntent.getActivityAsUser(mContext, move.moveId, intent, 655 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 656 } 657 658 private PendingIntent buildWizardReadyPendingIntent(DiskInfo disk) { 659 final Intent intent = new Intent(); 660 intent.setClassName("com.android.settings", 661 "com.android.settings.deviceinfo.StorageWizardReady"); 662 intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId()); 663 664 final int requestKey = disk.getId().hashCode(); 665 return PendingIntent.getActivityAsUser(mContext, requestKey, intent, 666 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); 667 } 668 } 669