Merge "Cleanup Storage Settings" into sc-dev

This commit is contained in:
Arc Wang
2021-05-05 03:13:37 +00:00
committed by Android (Google) Code Review
12 changed files with 76 additions and 709 deletions

View File

@@ -1,25 +0,0 @@
<!--
Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M19,15v3c0,0.55 -0.45,1 -1,1h-1v-4H19M7,15v4H6c-0.55,0 -1,-0.45 -1,-1v-3H7M12,2c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7C21,6.03 16.97,2 12,2L12,2z"/>
</vector>

View File

@@ -3574,8 +3574,6 @@
<!-- Body of dialog confirming that user wants to forget an internal storage device [CHAR LIMIT=NONE]-->
<string name="storage_internal_forget_confirm">All the apps, photos, and data stored on this <xliff:g id="name" example="SD card">^1</xliff:g> will be lost forever.</string>
<!-- Item title describing storage used by images [CHAR LIMIT=48]-->
<string name="storage_detail_images">Images</string>
<!-- Body of dialog informing user about the storage used by the Android System [CHAR LIMIT=NONE]-->
<string name="storage_detail_dialog_system">System includes files used to run Android version <xliff:g id="version" example="8.0">%s</xliff:g></string>
@@ -7604,10 +7602,6 @@
<string name="help_uri_apps_manage_sources" translatable="false"></string>
<!-- Help URI, manage apps games [DO NOT TRANSLATE] -->
<string name="help_uri_apps_games" translatable="false"></string>
<!-- Help URI, manage apps movies [DO NOT TRANSLATE] -->
<string name="help_uri_apps_movies" translatable="false"></string>
<!-- Help URI, manage apps photography [DO NOT TRANSLATE] -->
<string name="help_uri_apps_photography" translatable="false"></string>
<!-- Help URI, manage apps wifi access [DO NOT TRANSLATE] -->
<string name="help_uri_apps_wifi_access" translatable="false"></string>
<!-- Help URI, manage apps that have access to all files [DO NOT TRANSLATE] -->
@@ -11926,9 +11920,6 @@
<!-- Title of games app storage screen [CHAR LIMIT=30] -->
<string name="game_storage_settings">Games</string>
<!-- Title for audio files preference. [CHAR LIMIT=50] -->
<string name="audio_files_title">Audio files</string>
<!-- Title for the installed app info storage page. The total storage space taken up by this app. [CHAR LIMIT=40]-->
<string name="app_info_storage_title">Space used</string>

View File

@@ -234,10 +234,6 @@ public class Settings extends SettingsActivity {
public static class ManageDomainUrlsActivity extends SettingsActivity { /* empty */ }
public static class AutomaticStorageManagerSettingsActivity extends SettingsActivity { /* empty */ }
public static class GamesStorageActivity extends SettingsActivity { /* empty */ }
public static class MoviesStorageActivity extends SettingsActivity { /* empty */ }
public static class PhotosStorageActivity extends SettingsActivity {
/* empty */
}
public static class GestureNavigationSettingsActivity extends SettingsActivity { /* empty */ }
public static class InteractAcrossProfilesSettingsActivity extends SettingsActivity {
/* empty */

View File

@@ -1,49 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.manageapplications;
import androidx.fragment.app.Fragment;
/**
* FileViewHolderController handles adapting the AppViewHolder to work as a general purpose
* storage categorization preference in the ManageApplications view.
*/
public interface FileViewHolderController {
/**
* Begins a synchronous query for statistics for the files.
*/
void queryStats();
/**
* Returns if the preference should be shown.
*/
boolean shouldShow();
/**
* Initializes the view within an AppViewHolder.
*
* @param holder The holder to use to initialize.
*/
void setupView(ApplicationViewHolder holder);
/**
* Handles the behavior when the view is clicked.
*
* @param fragment Fragment where the click originated.
*/
void onClick(Fragment fragment);
}

View File

@@ -83,7 +83,6 @@ import com.android.settings.Settings;
import com.android.settings.Settings.GamesStorageActivity;
import com.android.settings.Settings.HighPowerApplicationsActivity;
import com.android.settings.Settings.ManageExternalSourcesActivity;
import com.android.settings.Settings.MoviesStorageActivity;
import com.android.settings.Settings.OverlaySettingsActivity;
import com.android.settings.Settings.StorageUseActivity;
import com.android.settings.Settings.UsageAccessSettingsActivity;
@@ -130,7 +129,6 @@ import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import com.android.settingslib.applications.ApplicationsState.CompoundFilter;
import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.settingsspinner.SettingsSpinnerAdapter;
@@ -182,9 +180,7 @@ public class ManageApplications extends InstrumentedFragment
// Storage types. Used to determine what the extra item in the list of preferences is.
public static final int STORAGE_TYPE_DEFAULT = 0; // Show all apps that are not categorized.
public static final int STORAGE_TYPE_MUSIC = 1;
public static final int STORAGE_TYPE_LEGACY = 2; // Show apps even if they can be categorized.
public static final int STORAGE_TYPE_PHOTOS_VIDEOS = 3;
public static final int STORAGE_TYPE_LEGACY = 1; // Show apps even if they can be categorized.
/**
* Intents with action {@code android.settings.MANAGE_APP_OVERLAY_PERMISSION}
@@ -230,12 +226,10 @@ public class ManageApplications extends InstrumentedFragment
public static final int LIST_TYPE_WRITE_SETTINGS = 7;
public static final int LIST_TYPE_MANAGE_SOURCES = 8;
public static final int LIST_TYPE_GAMES = 9;
public static final int LIST_TYPE_MOVIES = 10;
public static final int LIST_TYPE_PHOTOGRAPHY = 11;
public static final int LIST_TYPE_WIFI_ACCESS = 13;
public static final int LIST_MANAGE_EXTERNAL_STORAGE = 14;
public static final int LIST_TYPE_ALARMS_AND_REMINDERS = 15;
public static final int LIST_TYPE_MEDIA_MANAGEMENT_APPS = 16;
public static final int LIST_TYPE_WIFI_ACCESS = 10;
public static final int LIST_MANAGE_EXTERNAL_STORAGE = 11;
public static final int LIST_TYPE_ALARMS_AND_REMINDERS = 12;
public static final int LIST_TYPE_MEDIA_MANAGEMENT_APPS = 13;
// List types that should show instant apps.
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
@@ -314,13 +308,6 @@ public class ManageApplications extends InstrumentedFragment
} else if (className.equals(GamesStorageActivity.class.getName())) {
mListType = LIST_TYPE_GAMES;
mSortOrder = R.id.sort_order_size;
} else if (className.equals(MoviesStorageActivity.class.getName())) {
mListType = LIST_TYPE_MOVIES;
mSortOrder = R.id.sort_order_size;
} else if (className.equals(Settings.PhotosStorageActivity.class.getName())) {
mListType = LIST_TYPE_PHOTOGRAPHY;
mSortOrder = R.id.sort_order_size;
mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
} else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
mListType = LIST_TYPE_WIFI_ACCESS;
screenTitle = R.string.change_wifi_state_title;
@@ -429,24 +416,6 @@ public class ManageApplications extends InstrumentedFragment
mApplications.mHasReceivedBridgeCallback =
savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false);
}
int userId = mIsWorkOnly ? mWorkUserId : UserHandle.myUserId();
if (mStorageType == STORAGE_TYPE_MUSIC) {
Context context = getContext();
mApplications.setExtraViewController(
new MusicViewHolderController(
context,
new StorageStatsSource(context),
mVolumeUuid,
UserHandle.of(userId)));
} else if (mStorageType == STORAGE_TYPE_PHOTOS_VIDEOS) {
Context context = getContext();
mApplications.setExtraViewController(
new PhotosViewHolderController(
context,
new StorageStatsSource(context),
mVolumeUuid,
UserHandle.of(userId)));
}
mRecyclerView = mListContainer.findViewById(R.id.apps_list);
mRecyclerView.setItemAnimator(null);
mRecyclerView.setLayoutManager(new LinearLayoutManager(
@@ -508,19 +477,13 @@ public class ManageApplications extends InstrumentedFragment
static AppFilter getCompositeFilter(int listType, int storageType, String volumeUuid) {
AppFilter filter = new VolumeFilter(volumeUuid);
if (listType == LIST_TYPE_STORAGE) {
if (storageType == STORAGE_TYPE_MUSIC) {
filter = new CompoundFilter(ApplicationsState.FILTER_AUDIO, filter);
} else if (storageType == STORAGE_TYPE_DEFAULT) {
if (storageType == STORAGE_TYPE_DEFAULT) {
filter = new CompoundFilter(ApplicationsState.FILTER_APPS_EXCEPT_GAMES, filter);
}
return filter;
}
if (listType == LIST_TYPE_GAMES) {
return new CompoundFilter(ApplicationsState.FILTER_GAMES, filter);
} else if (listType == LIST_TYPE_MOVIES) {
return new CompoundFilter(ApplicationsState.FILTER_MOVIES, filter);
} else if (listType == LIST_TYPE_PHOTOGRAPHY) {
return new CompoundFilter(ApplicationsState.FILTER_PHOTOS, filter);
}
return null;
}
@@ -533,16 +496,9 @@ public class ManageApplications extends InstrumentedFragment
case LIST_TYPE_NOTIFICATION:
return SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS;
case LIST_TYPE_STORAGE:
if (mStorageType == STORAGE_TYPE_MUSIC) {
return SettingsEnums.APPLICATIONS_STORAGE_MUSIC;
}
return SettingsEnums.APPLICATIONS_STORAGE_APPS;
case LIST_TYPE_GAMES:
return SettingsEnums.APPLICATIONS_STORAGE_GAMES;
case LIST_TYPE_MOVIES:
return SettingsEnums.APPLICATIONS_STORAGE_MOVIES;
case LIST_TYPE_PHOTOGRAPHY:
return SettingsEnums.APPLICATIONS_STORAGE_PHOTOS;
case LIST_TYPE_USAGE_ACCESS:
return SettingsEnums.USAGE_ACCESS;
case LIST_TYPE_HIGH_POWER:
@@ -668,12 +624,6 @@ public class ManageApplications extends InstrumentedFragment
case LIST_TYPE_GAMES:
startAppInfoFragment(AppStorageSettings.class, R.string.game_storage_settings);
break;
case LIST_TYPE_MOVIES:
startAppInfoFragment(AppStorageSettings.class, R.string.storage_movies_tv);
break;
case LIST_TYPE_PHOTOGRAPHY:
startAppInfoFragment(AppStorageSettings.class, R.string.storage_photos_videos);
break;
case LIST_TYPE_WIFI_ACCESS:
startAppInfoFragment(ChangeWifiStateDetails.class,
R.string.change_wifi_state_title);
@@ -760,10 +710,6 @@ public class ManageApplications extends InstrumentedFragment
return R.string.help_uri_apps_manage_sources;
case LIST_TYPE_GAMES:
return R.string.help_uri_apps_overlay;
case LIST_TYPE_MOVIES:
return R.string.help_uri_apps_movies;
case LIST_TYPE_PHOTOGRAPHY:
return R.string.help_uri_apps_photography;
case LIST_TYPE_WIFI_ACCESS:
return R.string.help_uri_apps_wifi_access;
case LIST_MANAGE_EXTERNAL_STORAGE:
@@ -856,8 +802,6 @@ public class ManageApplications extends InstrumentedFragment
mCurrentPkgName = entry.info.packageName;
mCurrentUid = entry.info.uid;
startApplicationDetailsActivity();
} else {
mApplications.mExtraViewController.onClick(this);
}
}
@@ -1046,7 +990,6 @@ public class ManageApplications extends InstrumentedFragment
private AppFilter mCompositeFilter;
private boolean mHasReceivedLoadEntries;
private boolean mHasReceivedBridgeCallback;
private FileViewHolderController mExtraViewController;
private SearchFilter mSearchFilter;
private PowerAllowlistBackend mBackend;
@@ -1146,18 +1089,6 @@ public class ManageApplications extends InstrumentedFragment
}
}
public void setExtraViewController(FileViewHolderController extraViewController) {
mExtraViewController = extraViewController;
// Start to query extra view's stats on background, and once done post result to main
// thread.
ThreadUtils.postOnBackgroundThread(() -> {
mExtraViewController.queryStats();
ThreadUtils.postOnMainThread(() -> {
onExtraViewCompleted();
});
});
}
public void resume(int sort) {
if (DEBUG) Log.i(TAG, "Resume! mResumed=" + mResumed);
if (!mResumed) {
@@ -1219,10 +1150,7 @@ public class ManageApplications extends InstrumentedFragment
@Override
public int getItemViewType(int position) {
boolean isLastItem = (getItemCount() - 1) == position;
return hasExtraView() && isLastItem
? VIEW_TYPE_EXTRA_VIEW
: VIEW_TYPE_APP;
return VIEW_TYPE_APP;
}
public void rebuild() {
@@ -1454,20 +1382,12 @@ public class ManageApplications extends InstrumentedFragment
}
}
public void onExtraViewCompleted() {
if (!hasExtraView()) {
return;
}
// Update last item - this is assumed to be the extra view.
notifyItemChanged(getItemCount() - 1);
}
@Override
public int getItemCount() {
if (mEntries == null) {
return 0;
}
return mEntries.size() + (hasExtraView() ? 1 : 0);
return mEntries.size();
}
public int getApplicationCount() {
@@ -1499,24 +1419,20 @@ public class ManageApplications extends InstrumentedFragment
@Override
public void onBindViewHolder(ApplicationViewHolder holder, int position) {
if (mEntries != null && mExtraViewController != null && position == mEntries.size()) {
// set up view for extra view controller
mExtraViewController.setupView(holder);
} else {
// Bind the data efficiently with the holder
ApplicationsState.AppEntry entry = mEntries.get(position);
synchronized (entry) {
holder.setTitle(entry.label);
mState.ensureLabelDescription(entry);
holder.itemView.setContentDescription(entry.labelDescription);
mState.ensureIcon(entry);
holder.setIcon(entry.icon);
updateSummary(holder, entry);
updateSwitch(holder, entry);
holder.updateDisableView(entry.info);
}
holder.setEnabled(isEnabled(position));
// Bind the data efficiently with the holder
final ApplicationsState.AppEntry entry = mEntries.get(position);
synchronized (entry) {
holder.setTitle(entry.label);
mState.ensureLabelDescription(entry);
holder.itemView.setContentDescription(entry.labelDescription);
mState.ensureIcon(entry);
holder.setIcon(entry.icon);
updateSummary(holder, entry);
updateSwitch(holder, entry);
holder.updateDisableView(entry.info);
}
holder.setEnabled(isEnabled(position));
holder.itemView.setOnClickListener(mManageApplications);
}
@@ -1589,11 +1505,6 @@ public class ManageApplications extends InstrumentedFragment
}
}
private boolean hasExtraView() {
return mExtraViewController != null
&& mExtraViewController.shouldShow();
}
public static class OnScrollListener extends RecyclerView.OnScrollListener {
private int mScrollState = SCROLL_STATE_IDLE;
private boolean mDelayNotifyDataChange;

View File

@@ -1,90 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.manageapplications;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.provider.DocumentsContract;
import android.text.format.Formatter;
import android.util.Log;
import androidx.annotation.WorkerThread;
import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.applications.StorageStatsSource;
import java.io.IOException;
/**
* MusicViewHolderController controls an Audio/Music file view in the ManageApplications view.
*/
public class MusicViewHolderController implements FileViewHolderController {
private static final String TAG = "MusicViewHolderCtrl";
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
private Context mContext;
private StorageStatsSource mSource;
private String mVolumeUuid;
private long mMusicSize;
private UserHandle mUser;
public MusicViewHolderController(
Context context, StorageStatsSource source, String volumeUuid, UserHandle user) {
mContext = context;
mSource = source;
mVolumeUuid = volumeUuid;
mUser = user;
}
@Override
@WorkerThread
public void queryStats() {
try {
mMusicSize = mSource.getExternalStorageStats(mVolumeUuid, mUser).audioBytes;
} catch (IOException e) {
mMusicSize = 0;
Log.w(TAG, e);
}
}
@Override
public boolean shouldShow() {
return true;
}
@Override
public void setupView(ApplicationViewHolder holder) {
holder.setIcon(R.drawable.ic_headset_24dp);
holder.setTitle(mContext.getText(R.string.audio_files_title));
holder.setSummary(Formatter.formatFileSize(mContext, mMusicSize));
}
@Override
public void onClick(Fragment fragment) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"),
DocumentsContract.Root.MIME_TYPE_ITEM);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra(Intent.EXTRA_USER_ID, mUser.getIdentifier());
Utils.launchIntent(fragment, intent);
}
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.manageapplications;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.text.format.Formatter;
import android.util.Log;
import androidx.annotation.WorkerThread;
import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.applications.StorageStatsSource;
import java.io.IOException;
/** PhotosViewHolderController controls an Audio/Music file view in the ManageApplications view. */
public class PhotosViewHolderController implements FileViewHolderController {
private static final String TAG = "PhotosViewHolderCtrl";
private static final String IMAGE_MIME_TYPE = "image/*";
private Context mContext;
private StorageStatsSource mSource;
private String mVolumeUuid;
private long mFilesSize;
private UserHandle mUser;
public PhotosViewHolderController(
Context context, StorageStatsSource source, String volumeUuid, UserHandle user) {
mContext = context;
mSource = source;
mVolumeUuid = volumeUuid;
mUser = user;
}
@Override
@WorkerThread
public void queryStats() {
try {
StorageStatsSource.ExternalStorageStats stats =
mSource.getExternalStorageStats(mVolumeUuid, mUser);
mFilesSize = stats.imageBytes + stats.videoBytes;
} catch (IOException e) {
mFilesSize = 0;
Log.w(TAG, e);
}
}
@Override
public boolean shouldShow() {
return true;
}
@Override
public void setupView(ApplicationViewHolder holder) {
holder.setIcon(R.drawable.ic_photo_library);
holder.setTitle(mContext.getText(R.string.storage_detail_images));
holder.setSummary(Formatter.formatFileSize(mContext, mFilesSize));
}
@Override
public void onClick(Fragment fragment) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.setType(IMAGE_MIME_TYPE);
intent.putExtra(Intent.EXTRA_FROM_STORAGE, true);
intent.putExtra(Intent.EXTRA_USER_ID, mUser.getIdentifier());
Utils.launchIntent(fragment, intent);
}
}

View File

@@ -88,10 +88,14 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
@VisibleForTesting
static final String TRASH_KEY = "pref_trash";
private final Uri mImagesUri;
private final Uri mVideosUri;
private final Uri mAudiosUri;
private final Uri mDocumentsAndOtherUri;
@VisibleForTesting
final Uri mImagesUri;
@VisibleForTesting
final Uri mVideosUri;
@VisibleForTesting
final Uri mAudiosUri;
@VisibleForTesting
final Uri mDocumentsAndOtherUri;
// This value should align with the design of storage_dashboard_fragment.xml
private static final int LAST_STORAGE_CATEGORY_PREFERENCE_ORDER = 200;
@@ -175,13 +179,13 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
launchPublicStorageIntent();
return true;
case IMAGES_KEY:
launchImagesIntent();
launchActivityWithUri(mImagesUri);
return true;
case VIDEOS_KEY:
launchVideosIntent();
launchActivityWithUri(mVideosUri);
return true;
case AUDIOS_KEY:
launchAudiosIntent();
launchActivityWithUri(mAudiosUri);
return true;
case APPS_KEY:
launchAppsIntent();
@@ -190,7 +194,7 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
launchGamesIntent();
return true;
case DOCUMENTS_AND_OTHER_KEY:
launchDocumentsAndOtherIntent();
launchActivityWithUri(mDocumentsAndOtherUri);
return true;
case SYSTEM_KEY:
final SystemInfoFragment dialog = new SystemInfoFragment();
@@ -405,29 +409,10 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
}
}
// TODO(b/183078080): To simplify StorageItemPreferenceController, move launchxxxIntent to a
// utility object.
private void launchImagesIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(mImagesUri);
if (intent.resolveActivity(mPackageManager) == null) {
final Bundle args = getWorkAnnotatedBundle(2);
args.putString(ManageApplications.EXTRA_CLASSNAME,
Settings.PhotosStorageActivity.class.getName());
args.putInt(ManageApplications.EXTRA_STORAGE_TYPE,
ManageApplications.STORAGE_TYPE_PHOTOS_VIDEOS);
intent = new SubSettingLauncher(mContext)
.setDestination(ManageApplications.class.getName())
.setTitleRes(R.string.storage_photos_videos)
.setArguments(args)
.setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
.toIntent();
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
Utils.launchIntent(mFragment, intent);
} else {
mContext.startActivity(intent);
}
private void launchActivityWithUri(Uri dataUri) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(dataUri);
mContext.startActivity(intent);
}
private long getImagesSize(StorageAsyncLoader.AppsStorageResult data,
@@ -443,27 +428,6 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
}
}
private void launchVideosIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(mVideosUri);
if (intent.resolveActivity(mPackageManager) == null) {
final Bundle args = getWorkAnnotatedBundle(1);
args.putString(ManageApplications.EXTRA_CLASSNAME,
Settings.MoviesStorageActivity.class.getName());
intent = new SubSettingLauncher(mContext)
.setDestination(ManageApplications.class.getName())
.setTitleRes(R.string.storage_movies_tv)
.setArguments(args)
.setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
.toIntent();
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
Utils.launchIntent(mFragment, intent);
} else {
mContext.startActivity(intent);
}
}
private long getVideosSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
@@ -473,31 +437,6 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
}
}
private void launchAudiosIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(mAudiosUri);
if (intent.resolveActivity(mPackageManager) == null) {
final Bundle args = getWorkAnnotatedBundle(4);
args.putString(ManageApplications.EXTRA_CLASSNAME,
Settings.StorageUseActivity.class.getName());
args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
args.putInt(ManageApplications.EXTRA_STORAGE_TYPE,
ManageApplications.STORAGE_TYPE_MUSIC);
intent = new SubSettingLauncher(mContext)
.setDestination(ManageApplications.class.getName())
.setTitleRes(R.string.storage_music_audio)
.setArguments(args)
.setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
.toIntent();
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
Utils.launchIntent(mFragment, intent);
} else {
mContext.startActivity(intent);
}
}
private long getAudiosSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
@@ -563,19 +502,6 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
return args;
}
private void launchDocumentsAndOtherIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(mDocumentsAndOtherUri);
if (intent.resolveActivity(mPackageManager) == null) {
intent = mSvp.findEmulatedForPrivate(mVolume).buildBrowseIntent();
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
Utils.launchIntent(mFragment, intent);
} else {
mContext.startActivity(intent);
}
}
private long getDocumentsAndOtherSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {

View File

@@ -1,104 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.manageapplications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
import android.text.format.Formatter;
import android.view.View;
import android.widget.FrameLayout;
import androidx.fragment.app.Fragment;
import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class MusicViewHolderControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
@Mock
private StorageStatsSource mSource;
private Context mContext;
private MusicViewHolderController mController;
private ApplicationViewHolder mHolder;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
final String fsUuid = new VolumeInfo("id", 0, null, "id").fsUuid;
mController = new MusicViewHolderController(mContext, mSource, fsUuid, UserHandle.of(-1));
View view = ApplicationViewHolder.newView(new FrameLayout(mContext));
mHolder = new ApplicationViewHolder(view);
}
@Test
public void storageShouldBeZeroBytesIfQueriedBeforeStorageQueryFinishes() {
mController.setupView(mHolder);
assertThat(mHolder.mSummary.getText().toString()).isEqualTo(
Formatter.formatFileSize(mContext, 0));
}
@Test
public void storageShouldRepresentStorageStatsQuery() throws Exception {
when(mSource.getExternalStorageStats(nullable(String.class), nullable(UserHandle.class)))
.thenReturn(new StorageStatsSource.ExternalStorageStats(1, 1, 0, 0, 0));
mController.queryStats();
mController.setupView(mHolder);
assertThat(mHolder.mSummary.getText().toString()).isEqualTo(
Formatter.formatFileSize(mContext, 1));
}
@Test
public void clickingShouldIntentIntoFilesApp() {
mController.onClick(mFragment);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment).startActivity(argumentCaptor.capture());
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(intent.getData()).isEqualTo(DocumentsContract.buildRootUri(
"com.android.providers.media.documents",
"audio_root"));
assertThat(intent.getType()).isEqualTo(DocumentsContract.Root.MIME_TYPE_ITEM);
}
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.manageapplications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.text.format.Formatter;
import android.view.View;
import android.widget.FrameLayout;
import androidx.fragment.app.Fragment;
import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class PhotosViewHolderControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
@Mock
private StorageStatsSource mSource;
private Context mContext;
private PhotosViewHolderController mController;
private ApplicationViewHolder mHolder;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
final String fsUuid = new VolumeInfo("id", 0, null, "id").fsUuid;
mController = new PhotosViewHolderController(mContext, mSource, fsUuid, UserHandle.of(-1));
final View view = ApplicationViewHolder.newView(new FrameLayout(mContext));
mHolder = new ApplicationViewHolder(view);
}
@Test
public void storageShouldBeZeroBytesIfQueriedBeforeStorageQueryFinishes() {
mController.setupView(mHolder);
assertThat(mHolder.mSummary.getText().toString())
.isEqualTo(Formatter.formatFileSize(mContext, 0));
}
@Test
public void storageShouldRepresentStorageStatsQuery() throws Exception {
when(mSource.getExternalStorageStats(nullable(String.class), nullable(UserHandle.class)))
.thenReturn(new StorageStatsSource.ExternalStorageStats(1, 0, 1, 10, 0));
mController.queryStats();
mController.setupView(mHolder);
assertThat(mHolder.mSummary.getText().toString())
.isEqualTo(Formatter.formatFileSize(mContext, 11));
}
@Test
public void clickingShouldIntentIntoFilesApp() {
mController.onClick(mFragment);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment).startActivity(argumentCaptor.capture());
Intent intent = argumentCaptor.getValue();
assertThat(intent.getType()).isEqualTo("image/*");
assertThat(intent.getAction()).isEqualTo(android.content.Intent.ACTION_VIEW);
assertThat(intent.getBooleanExtra(Intent.EXTRA_FROM_STORAGE, false)).isTrue();
}
}

View File

@@ -20,6 +20,7 @@ import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
@@ -30,6 +31,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
@@ -172,38 +174,33 @@ public class StorageItemPreferenceControllerTest {
@Test
public void launchImagesIntent_resolveActionViewNull_settingsIntent() {
mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mActivity).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mockContext).startActivity(argumentCaptor.capture());
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(ManageApplications.class.getName());
assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
.isEqualTo(R.string.storage_photos_videos);
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(intent.getData()).isEqualTo(mController.mImagesUri);
}
@Test
public void launchAudiosIntent_resolveActionViewNull_settingsIntent() {
mPreference.setKey(StorageItemPreferenceController.AUDIOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mockContext).startActivity(argumentCaptor.capture());
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(ManageApplications.class.getName());
assertThat(intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS).getInt(
ManageApplications.EXTRA_STORAGE_TYPE, 0))
.isEqualTo(ManageApplications.STORAGE_TYPE_MUSIC);
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(intent.getData()).isEqualTo(mController.mAudiosUri);
}
@Test
@@ -270,20 +267,18 @@ public class StorageItemPreferenceControllerTest {
@Test
public void launchDocumentsAndOtherIntent_resolveActionViewNull_settingsIntent() {
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(mVolume);
when(mVolume.buildBrowseIntent()).thenReturn(new Intent());
mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
assertThat(mController.handlePreferenceTreeClick(mPreference))
.isTrue();
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mockContext).startActivity(argumentCaptor.capture());
Intent intent = argumentCaptor.getValue();
Intent browseIntent = mVolume.buildBrowseIntent();
assertThat(intent.getAction()).isEqualTo(browseIntent.getAction());
assertThat(intent.getData()).isEqualTo(browseIntent.getData());
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(intent.getData()).isEqualTo(mController.mDocumentsAndOtherUri);
}
@Test
@@ -307,19 +302,17 @@ public class StorageItemPreferenceControllerTest {
@Test
public void launchVideosIntent_resolveActionViewNull_settingsIntent() {
mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mockContext).startActivity(argumentCaptor.capture());
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(ManageApplications.class.getName());
assertThat(intent.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
.isEqualTo(R.string.storage_movies_tv);
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(intent.getData()).isEqualTo(mController.mVideosUri);
}
@Test
@@ -463,4 +456,16 @@ public class StorageItemPreferenceControllerTest {
assertThat(mController.mSystemPreference.isVisible()).isFalse();
assertThat(mController.mTrashPreference.isVisible()).isFalse();
}
/**
* To verify startActivity, these test cases use mock Context because mContext is not an
* activity context and AndroidRuntimeException throws for no FLAG_ACTIVITY_NEW_TASK.
*/
private Context getMockContext() {
final Resources resources = mock(Resources.class);
final Context context = mock(Context.class);
when(context.getResources()).thenReturn(resources);
when(resources.getString(anyInt())).thenReturn("");
return context;
}
}

View File

@@ -31,10 +31,8 @@ import static com.android.settings.applications.manageapplications.ManageApplica
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MAIN;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MANAGE_SOURCES;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MEDIA_MANAGEMENT_APPS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MOVIES;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_OVERLAY;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_PHOTOGRAPHY;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_STORAGE;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_USAGE_ACCESS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_WRITE_SETTINGS;
@@ -75,7 +73,5 @@ public class AppFilterRegistryTest {
assertThat(registry.getDefaultFilterType(LIST_TYPE_STORAGE)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_GAMES)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MOVIES)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_PHOTOGRAPHY)).isEqualTo(FILTER_APPS_ALL);
}
}