1 /* 2 * Copyright (C) 2016 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.settings.deviceinfo.storage; 18 19 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PERSONAL_TAB; 20 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PRIVATE_TAB; 21 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.WORK_TAB; 22 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.content.pm.UserInfo; 27 import android.content.res.TypedArray; 28 import android.graphics.drawable.Drawable; 29 import android.net.Uri; 30 import android.os.Build; 31 import android.os.Bundle; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.os.storage.VolumeInfo; 35 import android.util.DataUnit; 36 import android.util.Log; 37 import android.util.SparseArray; 38 import android.widget.Toast; 39 40 import androidx.annotation.Nullable; 41 import androidx.annotation.VisibleForTesting; 42 import androidx.fragment.app.Fragment; 43 import androidx.preference.Preference; 44 import androidx.preference.PreferenceCategory; 45 import androidx.preference.PreferenceScreen; 46 47 import com.android.settings.R; 48 import com.android.settings.Settings; 49 import com.android.settings.SettingsActivity; 50 import com.android.settings.Utils; 51 import com.android.settings.applications.manageapplications.ManageApplications; 52 import com.android.settings.core.PreferenceControllerMixin; 53 import com.android.settings.core.SubSettingLauncher; 54 import com.android.settings.dashboard.profileselector.ProfileSelectFragment; 55 import com.android.settings.deviceinfo.StorageItemPreference; 56 import com.android.settings.deviceinfo.storage.StorageUtils.SystemInfoFragment; 57 import com.android.settings.deviceinfo.storage.StorageUtils.TemporaryFilesInfoFragment; 58 import com.android.settings.overlay.FeatureFactory; 59 import com.android.settingslib.core.AbstractPreferenceController; 60 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 61 import com.android.settingslib.deviceinfo.StorageMeasurement; 62 import com.android.settingslib.deviceinfo.StorageVolumeProvider; 63 64 import java.util.ArrayList; 65 import java.util.Collections; 66 import java.util.Comparator; 67 import java.util.List; 68 import java.util.Map; 69 70 /** 71 * StorageItemPreferenceController handles the storage line items which summarize the storage 72 * categorization breakdown. 73 */ 74 public class StorageItemPreferenceController extends AbstractPreferenceController implements 75 PreferenceControllerMixin, 76 EmptyTrashFragment.OnEmptyTrashCompleteListener { 77 private static final String TAG = "StorageItemPreference"; 78 79 private static final String SYSTEM_FRAGMENT_TAG = "SystemInfo"; 80 private static final String TEMPORARY_FILES_FRAGMENT_TAG = "TemporaryFilesInfo"; 81 82 @VisibleForTesting 83 static final String PUBLIC_STORAGE_KEY = "pref_public_storage"; 84 @VisibleForTesting 85 static final String IMAGES_KEY = "pref_images"; 86 @VisibleForTesting 87 static final String VIDEOS_KEY = "pref_videos"; 88 @VisibleForTesting 89 static final String AUDIO_KEY = "pref_audio"; 90 @VisibleForTesting 91 static final String APPS_KEY = "pref_apps"; 92 @VisibleForTesting 93 static final String GAMES_KEY = "pref_games"; 94 @VisibleForTesting 95 static final String DOCUMENTS_KEY = "pref_documents"; 96 @VisibleForTesting 97 static final String OTHER_KEY = "pref_other"; 98 @VisibleForTesting 99 static final String SYSTEM_KEY = "pref_system"; 100 @VisibleForTesting 101 static final String TEMPORARY_FILES_KEY = "temporary_files"; 102 @VisibleForTesting 103 static final String CATEGORY_SPLITTER = "storage_category_splitter"; 104 @VisibleForTesting 105 static final String TRASH_KEY = "pref_trash"; 106 107 @VisibleForTesting 108 final Uri mImagesUri; 109 @VisibleForTesting 110 final Uri mVideosUri; 111 @VisibleForTesting 112 final Uri mAudioUri; 113 @VisibleForTesting 114 final Uri mDocumentsUri; 115 @VisibleForTesting 116 final Uri mOtherUri; 117 118 // This value should align with the design of storage_dashboard_fragment.xml 119 private static final int LAST_STORAGE_CATEGORY_PREFERENCE_ORDER = 200; 120 121 private PackageManager mPackageManager; 122 private UserManager mUserManager; 123 private final Fragment mFragment; 124 private final MetricsFeatureProvider mMetricsFeatureProvider; 125 private final StorageVolumeProvider mSvp; 126 @Nullable private VolumeInfo mVolume; 127 private int mUserId; 128 private long mUsedBytes; 129 private long mTotalSize; 130 131 @Nullable private List<StorageItemPreference> mPrivateStorageItemPreferences; 132 @Nullable private PreferenceScreen mScreen; 133 @VisibleForTesting 134 @Nullable Preference mPublicStoragePreference; 135 @VisibleForTesting 136 @Nullable StorageItemPreference mImagesPreference; 137 @VisibleForTesting 138 @Nullable StorageItemPreference mVideosPreference; 139 @VisibleForTesting 140 @Nullable StorageItemPreference mAudioPreference; 141 @VisibleForTesting 142 @Nullable StorageItemPreference mAppsPreference; 143 @VisibleForTesting 144 @Nullable StorageItemPreference mGamesPreference; 145 @VisibleForTesting 146 @Nullable StorageItemPreference mDocumentsPreference; 147 @VisibleForTesting 148 @Nullable StorageItemPreference mOtherPreference; 149 @VisibleForTesting 150 @Nullable StorageItemPreference mTrashPreference; 151 @VisibleForTesting 152 @Nullable StorageItemPreference mSystemPreference; 153 @VisibleForTesting 154 @Nullable StorageItemPreference mTemporaryFilesPreference; 155 @VisibleForTesting 156 @Nullable PreferenceCategory mCategorySplitterPreferenceCategory; 157 158 private final int mProfileType; 159 160 private StorageCacheHelper mStorageCacheHelper; 161 // The mIsDocumentsPrefShown being used here is to prevent a flicker problem from displaying 162 // the Document entry. 163 private boolean mIsDocumentsPrefShown; 164 private boolean mIsPreferenceOrderedBySize; 165 StorageItemPreferenceController( Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp)166 public StorageItemPreferenceController( 167 Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) { 168 this(context, hostFragment, volume, svp, ProfileSelectFragment.ProfileType.PERSONAL); 169 } 170 StorageItemPreferenceController( Context context, Fragment hostFragment, @Nullable VolumeInfo volume, StorageVolumeProvider svp, @ProfileSelectFragment.ProfileType int profileType)171 public StorageItemPreferenceController( 172 Context context, 173 Fragment hostFragment, 174 @Nullable VolumeInfo volume, 175 StorageVolumeProvider svp, 176 @ProfileSelectFragment.ProfileType int profileType) { 177 super(context); 178 mPackageManager = context.getPackageManager(); 179 mUserManager = context.getSystemService(UserManager.class); 180 mFragment = hostFragment; 181 mVolume = volume; 182 mSvp = svp; 183 mProfileType = profileType; 184 mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); 185 mUserId = getCurrentUserId(); 186 mIsDocumentsPrefShown = isDocumentsPrefShown(); 187 mStorageCacheHelper = new StorageCacheHelper(mContext, mUserId); 188 189 mImagesUri = Uri.parse(context.getResources() 190 .getString(R.string.config_images_storage_category_uri)); 191 mVideosUri = Uri.parse(context.getResources() 192 .getString(R.string.config_videos_storage_category_uri)); 193 mAudioUri = Uri.parse(context.getResources() 194 .getString(R.string.config_audio_storage_category_uri)); 195 mDocumentsUri = Uri.parse(context.getResources() 196 .getString(R.string.config_documents_storage_category_uri)); 197 mOtherUri = Uri.parse(context.getResources() 198 .getString(R.string.config_other_storage_category_uri)); 199 } 200 201 @VisibleForTesting getCurrentUserId()202 int getCurrentUserId() { 203 return Utils.getCurrentUserIdOfType(mUserManager, mProfileType); 204 } 205 206 @Override isAvailable()207 public boolean isAvailable() { 208 return true; 209 } 210 211 @Override handlePreferenceTreeClick(Preference preference)212 public boolean handlePreferenceTreeClick(Preference preference) { 213 if (preference.getKey() == null) { 214 return false; 215 } 216 switch (preference.getKey()) { 217 case PUBLIC_STORAGE_KEY: 218 launchPublicStorageIntent(); 219 return true; 220 case IMAGES_KEY: 221 launchActivityWithUri(mImagesUri); 222 return true; 223 case VIDEOS_KEY: 224 launchActivityWithUri(mVideosUri); 225 return true; 226 case AUDIO_KEY: 227 launchActivityWithUri(mAudioUri); 228 return true; 229 case APPS_KEY: 230 launchAppsIntent(); 231 return true; 232 case GAMES_KEY: 233 launchGamesIntent(); 234 return true; 235 case DOCUMENTS_KEY: 236 launchActivityWithUri(mDocumentsUri); 237 return true; 238 case OTHER_KEY: 239 launchActivityWithUri(mOtherUri); 240 return true; 241 case SYSTEM_KEY: 242 final SystemInfoFragment dialog = new SystemInfoFragment(); 243 dialog.setTargetFragment(mFragment, 0); 244 dialog.show(mFragment.getFragmentManager(), SYSTEM_FRAGMENT_TAG); 245 return true; 246 case TEMPORARY_FILES_KEY: 247 final TemporaryFilesInfoFragment temporaryFilesDialog = 248 new TemporaryFilesInfoFragment(); 249 temporaryFilesDialog.setTargetFragment(mFragment, 0); 250 temporaryFilesDialog.show(mFragment.getFragmentManager(), 251 TEMPORARY_FILES_FRAGMENT_TAG); 252 return true; 253 case TRASH_KEY: 254 launchTrashIntent(); 255 return true; 256 default: 257 // Do nothing. 258 } 259 return super.handlePreferenceTreeClick(preference); 260 } 261 262 @Override getPreferenceKey()263 public String getPreferenceKey() { 264 return null; 265 } 266 267 /** 268 * Sets the storage volume to use for when handling taps. 269 */ setVolume(VolumeInfo volume)270 public void setVolume(VolumeInfo volume) { 271 mVolume = volume; 272 273 if (mPublicStoragePreference != null) { 274 mPublicStoragePreference.setVisible( 275 isValidPublicVolume() 276 && mProfileType == ProfileSelectFragment.ProfileType.PERSONAL); 277 } 278 279 // If isValidPrivateVolume() is true, these preferences will become visible at 280 // onLoadFinished. 281 if (isValidPrivateVolume()) { 282 mIsDocumentsPrefShown = isDocumentsPrefShown(); 283 } else { 284 setPrivateStorageCategoryPreferencesVisibility(false); 285 } 286 } 287 288 // Stats data is only available on private volumes. isValidPrivateVolume()289 private boolean isValidPrivateVolume() { 290 return mVolume != null 291 && mVolume.getType() == VolumeInfo.TYPE_PRIVATE 292 && (mVolume.getState() == VolumeInfo.STATE_MOUNTED 293 || mVolume.getState() == VolumeInfo.STATE_MOUNTED_READ_ONLY); 294 } 295 isValidPublicVolume()296 private boolean isValidPublicVolume() { 297 // Stub volume is a volume that is maintained by external party such as the ChromeOS 298 // processes in ARC++. 299 return mVolume != null 300 && (mVolume.getType() == VolumeInfo.TYPE_PUBLIC 301 || mVolume.getType() == VolumeInfo.TYPE_STUB) 302 && (mVolume.getState() == VolumeInfo.STATE_MOUNTED 303 || mVolume.getState() == VolumeInfo.STATE_MOUNTED_READ_ONLY); 304 } 305 306 @VisibleForTesting setPrivateStorageCategoryPreferencesVisibility(boolean visible)307 void setPrivateStorageCategoryPreferencesVisibility(boolean visible) { 308 if (mScreen == null) { 309 return; 310 } 311 312 mImagesPreference.setVisible(visible); 313 mVideosPreference.setVisible(visible); 314 mAudioPreference.setVisible(visible); 315 mAppsPreference.setVisible(visible); 316 mGamesPreference.setVisible(visible); 317 mSystemPreference.setVisible(visible); 318 mTemporaryFilesPreference.setVisible(visible); 319 mCategorySplitterPreferenceCategory.setVisible(visible); 320 mTrashPreference.setVisible(visible); 321 322 // If we don't have a shared volume for our internal storage (or the shared volume isn't 323 // mounted as readable for whatever reason), we should hide the File preference. 324 if (visible) { 325 mDocumentsPreference.setVisible(mIsDocumentsPrefShown); 326 mOtherPreference.setVisible(mIsDocumentsPrefShown); 327 } else { 328 mDocumentsPreference.setVisible(false); 329 mOtherPreference.setVisible(false); 330 } 331 } 332 isDocumentsPrefShown()333 private boolean isDocumentsPrefShown() { 334 VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume); 335 return sharedVolume != null && sharedVolume.isMountedReadable(); 336 } 337 updatePrivateStorageCategoryPreferencesOrder()338 private void updatePrivateStorageCategoryPreferencesOrder() { 339 if (mScreen == null || !isValidPrivateVolume()) { 340 return; 341 } 342 343 if (mPrivateStorageItemPreferences == null) { 344 mPrivateStorageItemPreferences = new ArrayList<>(); 345 346 // Adding categories in the reverse order so that 347 // They would be in the right order after sorting 348 mPrivateStorageItemPreferences.add(mTrashPreference); 349 mPrivateStorageItemPreferences.add(mOtherPreference); 350 mPrivateStorageItemPreferences.add(mDocumentsPreference); 351 mPrivateStorageItemPreferences.add(mGamesPreference); 352 mPrivateStorageItemPreferences.add(mAppsPreference); 353 mPrivateStorageItemPreferences.add(mAudioPreference); 354 mPrivateStorageItemPreferences.add(mVideosPreference); 355 mPrivateStorageItemPreferences.add(mImagesPreference); 356 } 357 mScreen.removePreference(mImagesPreference); 358 mScreen.removePreference(mVideosPreference); 359 mScreen.removePreference(mAudioPreference); 360 mScreen.removePreference(mAppsPreference); 361 mScreen.removePreference(mGamesPreference); 362 mScreen.removePreference(mDocumentsPreference); 363 mScreen.removePreference(mOtherPreference); 364 mScreen.removePreference(mTrashPreference); 365 366 // Sort display order by size. 367 Collections.sort(mPrivateStorageItemPreferences, 368 Comparator.comparingLong(StorageItemPreference::getStorageSize)); 369 int orderIndex = LAST_STORAGE_CATEGORY_PREFERENCE_ORDER; 370 for (StorageItemPreference preference : mPrivateStorageItemPreferences) { 371 preference.setOrder(orderIndex--); 372 mScreen.addPreference(preference); 373 } 374 } 375 376 /** 377 * Sets the user id for which this preference controller is handling. 378 */ setUserId(UserHandle userHandle)379 public void setUserId(UserHandle userHandle) { 380 if (mProfileType == ProfileSelectFragment.ProfileType.WORK 381 && !mUserManager.isManagedProfile(userHandle.getIdentifier())) { 382 throw new IllegalArgumentException("Only accept work profile userHandle"); 383 } 384 385 UserInfo userInfo = mUserManager.getUserInfo(userHandle.getIdentifier()); 386 if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE 387 && (userInfo == null || userInfo.isPrivateProfile())) { 388 throw new IllegalArgumentException("Only accept private profile userHandle"); 389 } 390 mUserId = userHandle.getIdentifier(); 391 392 tintPreference(mPublicStoragePreference); 393 tintPreference(mImagesPreference); 394 tintPreference(mVideosPreference); 395 tintPreference(mAudioPreference); 396 tintPreference(mAppsPreference); 397 tintPreference(mGamesPreference); 398 tintPreference(mDocumentsPreference); 399 tintPreference(mOtherPreference); 400 tintPreference(mSystemPreference); 401 tintPreference(mTemporaryFilesPreference); 402 tintPreference(mTrashPreference); 403 } 404 tintPreference(Preference preference)405 private void tintPreference(Preference preference) { 406 if (preference != null) { 407 preference.setIcon(applyTint(mContext, preference.getIcon())); 408 } 409 } 410 applyTint(Context context, Drawable icon)411 private static Drawable applyTint(Context context, Drawable icon) { 412 TypedArray array = 413 context.obtainStyledAttributes(new int[]{android.R.attr.colorControlNormal}); 414 icon = icon.mutate(); 415 icon.setTint(array.getColor(0, 0)); 416 array.recycle(); 417 return icon; 418 } 419 420 @Override displayPreference(PreferenceScreen screen)421 public void displayPreference(PreferenceScreen screen) { 422 mScreen = screen; 423 mPublicStoragePreference = screen.findPreference(PUBLIC_STORAGE_KEY); 424 mImagesPreference = screen.findPreference(IMAGES_KEY); 425 mVideosPreference = screen.findPreference(VIDEOS_KEY); 426 mAudioPreference = screen.findPreference(AUDIO_KEY); 427 mAppsPreference = screen.findPreference(APPS_KEY); 428 mGamesPreference = screen.findPreference(GAMES_KEY); 429 mDocumentsPreference = screen.findPreference(DOCUMENTS_KEY); 430 mOtherPreference = screen.findPreference(OTHER_KEY); 431 mCategorySplitterPreferenceCategory = screen.findPreference(CATEGORY_SPLITTER); 432 mSystemPreference = screen.findPreference(SYSTEM_KEY); 433 mTemporaryFilesPreference = screen.findPreference(TEMPORARY_FILES_KEY); 434 mTrashPreference = screen.findPreference(TRASH_KEY); 435 } 436 437 /** 438 * Fragments use it to set storage result and update UI of this controller. 439 * @param result The StorageResult from StorageAsyncLoader. This allows a nullable result. 440 * When it's null, the cached storage size info will be used instead. 441 * @param userId User ID to get the storage size info 442 */ onLoadFinished(@ullable SparseArray<StorageAsyncLoader.StorageResult> result, int userId)443 public void onLoadFinished(@Nullable SparseArray<StorageAsyncLoader.StorageResult> result, 444 int userId) { 445 // Enable animation when the storage size info is from StorageAsyncLoader whereas disable 446 // animation when the cached storage size info is used instead. 447 boolean animate = result != null && mIsPreferenceOrderedBySize; 448 // Calculate the size info for each category 449 StorageCacheHelper.StorageCache storageCache = getSizeInfo(result, userId); 450 // Set size info to each preference 451 mImagesPreference.setStorageSize(storageCache.imagesSize, mTotalSize, animate); 452 mVideosPreference.setStorageSize(storageCache.videosSize, mTotalSize, animate); 453 mAudioPreference.setStorageSize(storageCache.audioSize, mTotalSize, animate); 454 mAppsPreference.setStorageSize(storageCache.allAppsExceptGamesSize, mTotalSize, animate); 455 mGamesPreference.setStorageSize(storageCache.gamesSize, mTotalSize, animate); 456 mDocumentsPreference.setStorageSize(storageCache.documentsSize, mTotalSize, animate); 457 mOtherPreference.setStorageSize(storageCache.otherSize, mTotalSize, animate); 458 mTrashPreference.setStorageSize(storageCache.trashSize, mTotalSize, animate); 459 if (mSystemPreference != null) { 460 mSystemPreference.setStorageSize(storageCache.systemSize, mTotalSize, animate); 461 mSystemPreference.setTitle(mContext.getString(R.string.storage_os_name, 462 Build.VERSION.RELEASE)); 463 } 464 if (mTemporaryFilesPreference != null) { 465 mTemporaryFilesPreference.setStorageSize(storageCache.temporaryFilesSize, mTotalSize, 466 animate); 467 } 468 // Cache the size info 469 if (result != null) { 470 mStorageCacheHelper.cacheSizeInfo(storageCache); 471 } 472 473 // Sort the preference according to size info in descending order 474 if (!mIsPreferenceOrderedBySize) { 475 updatePrivateStorageCategoryPreferencesOrder(); 476 mIsPreferenceOrderedBySize = true; 477 } 478 setPrivateStorageCategoryPreferencesVisibility(true); 479 } 480 getSizeInfo( SparseArray<StorageAsyncLoader.StorageResult> result, int userId)481 private StorageCacheHelper.StorageCache getSizeInfo( 482 SparseArray<StorageAsyncLoader.StorageResult> result, int userId) { 483 if (result == null) { 484 return mStorageCacheHelper.retrieveCachedSize(); 485 } 486 StorageAsyncLoader.StorageResult data = result.get(userId); 487 StorageCacheHelper.StorageCache storageCache = new StorageCacheHelper.StorageCache(); 488 storageCache.imagesSize = data.imagesSize; 489 storageCache.videosSize = data.videosSize; 490 storageCache.audioSize = data.audioSize; 491 storageCache.allAppsExceptGamesSize = data.allAppsExceptGamesSize; 492 storageCache.gamesSize = data.gamesSize; 493 storageCache.documentsSize = data.documentsSize; 494 storageCache.otherSize = data.otherSize; 495 storageCache.trashSize = data.trashSize; 496 storageCache.systemSize = data.systemSize; 497 // Everything else that hasn't already been attributed is tracked as 498 // belonging to system. 499 long attributedSize = 0; 500 for (int i = 0; i < result.size(); i++) { 501 final StorageAsyncLoader.StorageResult otherData = result.valueAt(i); 502 attributedSize += 503 otherData.gamesSize 504 + otherData.audioSize 505 + otherData.videosSize 506 + otherData.imagesSize 507 + otherData.documentsSize 508 + otherData.otherSize 509 + otherData.trashSize 510 + otherData.allAppsExceptGamesSize; 511 attributedSize -= otherData.duplicateCodeSize; 512 } 513 // System size is equal for each user and should be added only once 514 attributedSize += data.systemSize; 515 storageCache.temporaryFilesSize = Math.max(DataUnit.GIBIBYTES.toBytes(1), 516 mUsedBytes - attributedSize); 517 return storageCache; 518 } 519 setUsedSize(long usedSizeBytes)520 public void setUsedSize(long usedSizeBytes) { 521 mUsedBytes = usedSizeBytes; 522 } 523 setTotalSize(long totalSizeBytes)524 public void setTotalSize(long totalSizeBytes) { 525 mTotalSize = totalSizeBytes; 526 } 527 launchPublicStorageIntent()528 private void launchPublicStorageIntent() { 529 final Intent intent = mVolume.buildBrowseIntent(); 530 if (intent == null) { 531 return; 532 } 533 mContext.startActivityAsUser(intent, new UserHandle(mUserId)); 534 } 535 launchActivityWithUri(Uri dataUri)536 private void launchActivityWithUri(Uri dataUri) { 537 final Intent intent = new Intent(Intent.ACTION_VIEW); 538 intent.setData(dataUri); 539 mContext.startActivityAsUser(intent, new UserHandle(mUserId)); 540 } 541 launchAppsIntent()542 private void launchAppsIntent() { 543 final Bundle args = getWorkAnnotatedBundle(3); 544 args.putString(ManageApplications.EXTRA_CLASSNAME, 545 Settings.StorageUseActivity.class.getName()); 546 args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid()); 547 args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription()); 548 final Intent intent = new SubSettingLauncher(mContext) 549 .setDestination(ManageApplications.class.getName()) 550 .setTitleRes(R.string.apps_storage) 551 .setArguments(args) 552 .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment)) 553 .toIntent(); 554 intent.putExtra(Intent.EXTRA_USER_ID, mUserId); 555 Utils.launchIntent(mFragment, intent); 556 } 557 launchGamesIntent()558 private void launchGamesIntent() { 559 final Bundle args = getWorkAnnotatedBundle(1); 560 args.putString(ManageApplications.EXTRA_CLASSNAME, 561 Settings.GamesStorageActivity.class.getName()); 562 final Intent intent = new SubSettingLauncher(mContext) 563 .setDestination(ManageApplications.class.getName()) 564 .setTitleRes(R.string.game_storage_settings) 565 .setArguments(args) 566 .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment)) 567 .toIntent(); 568 intent.putExtra(Intent.EXTRA_USER_ID, mUserId); 569 Utils.launchIntent(mFragment, intent); 570 } 571 getWorkAnnotatedBundle(int additionalCapacity)572 private Bundle getWorkAnnotatedBundle(int additionalCapacity) { 573 final Bundle args = new Bundle(1 + additionalCapacity); 574 if (mProfileType == ProfileSelectFragment.ProfileType.WORK) { 575 args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, WORK_TAB); 576 } else if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE) { 577 args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PRIVATE_TAB); 578 } else { 579 args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB); 580 } 581 return args; 582 } 583 launchTrashIntent()584 private void launchTrashIntent() { 585 final Intent intent = new Intent("android.settings.VIEW_TRASH"); 586 587 if (mPackageManager.resolveActivityAsUser(intent, 0 /* flags */, mUserId) == null) { 588 final long trashSize = mTrashPreference.getStorageSize(); 589 if (trashSize > 0) { 590 new EmptyTrashFragment(mFragment, mUserId, trashSize, 591 this /* onEmptyTrashCompleteListener */).show(); 592 } else { 593 Toast.makeText(mContext, R.string.storage_trash_dialog_empty_message, 594 Toast.LENGTH_SHORT).show(); 595 } 596 } else { 597 mContext.startActivityAsUser(intent, new UserHandle(mUserId)); 598 } 599 } 600 601 @Override onEmptyTrashComplete()602 public void onEmptyTrashComplete() { 603 if (mTrashPreference == null) { 604 return; 605 } 606 mTrashPreference.setStorageSize(0, mTotalSize, true /* animate */); 607 updatePrivateStorageCategoryPreferencesOrder(); 608 } 609 totalValues(StorageMeasurement.MeasurementDetails details, int userId, String... keys)610 private static long totalValues(StorageMeasurement.MeasurementDetails details, int userId, 611 String... keys) { 612 long total = 0; 613 Map<String, Long> map = details.mediaSize.get(userId); 614 if (map != null) { 615 for (String key : keys) { 616 if (map.containsKey(key)) { 617 total += map.get(key); 618 } 619 } 620 } else { 621 Log.w(TAG, "MeasurementDetails mediaSize array does not have key for user " + userId); 622 } 623 return total; 624 } 625 } 626