Merge "Make photos/videos storage preference normal." into oc-mr1-dev

This commit is contained in:
TreeHugger Robot
2017-09-02 03:29:52 +00:00
committed by Android (Google) Code Review
7 changed files with 239 additions and 17 deletions

View File

@@ -21,7 +21,6 @@ import android.os.Bundle;
import com.android.settings.applications.AppOpsSummary;
import com.android.settings.enterprise.EnterprisePrivacySettings;
import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.fingerprint.FingerprintSettings;
import com.android.settings.password.ChooseLockGeneric;
/**
@@ -128,6 +127,9 @@ public class Settings extends SettingsActivity {
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 TopLevelSettings extends SettingsActivity { /* empty */ }
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }

View File

@@ -59,6 +59,7 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Settings.AllApplicationsActivity;
import com.android.settings.Settings.GamesStorageActivity;
import com.android.settings.Settings.HighPowerApplicationsActivity;
@@ -219,6 +220,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
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;
// sort order
private int mSortOrder = R.id.sort_order_alpha;
@@ -262,6 +264,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
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;
// List types that should show instant apps.
@@ -326,6 +329,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
} 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 {
mListType = LIST_TYPE_MAIN;
}
@@ -378,6 +385,14 @@ public class ManageApplications extends InstrumentedPreferenceFragment
new StorageStatsSource(context),
mVolumeUuid,
UserHandle.of(UserHandle.getUserId(mCurrentUid))));
} else if (mStorageType == STORAGE_TYPE_PHOTOS_VIDEOS) {
Context context = getContext();
mApplications.setExtraViewController(
new PhotosViewHolderController(
context,
new StorageStatsSource(context),
mVolumeUuid,
UserHandle.of(UserHandle.getUserId(mCurrentUid))));
}
mListView.setAdapter(mApplications);
mListView.setRecyclerListener(mApplications);
@@ -450,6 +465,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
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;
@@ -479,6 +496,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
case LIST_TYPE_STORAGE:
case LIST_TYPE_GAMES:
case LIST_TYPE_MOVIES:
case LIST_TYPE_PHOTOGRAPHY:
return mSortOrder == R.id.sort_order_alpha;
default:
return false;
@@ -501,6 +519,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
return MetricsEvent.APPLICATIONS_STORAGE_GAMES;
case LIST_TYPE_MOVIES:
return MetricsEvent.APPLICATIONS_STORAGE_MOVIES;
case LIST_TYPE_PHOTOGRAPHY:
return MetricsEvent.APPLICATIONS_STORAGE_PHOTOS;
case LIST_TYPE_USAGE_ACCESS:
return MetricsEvent.USAGE_ACCESS;
case LIST_TYPE_HIGH_POWER:
@@ -604,6 +624,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
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;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed
// app. Maybe when they load the list of apps that contains managed profile apps.

View File

@@ -0,0 +1,90 @@
/*
* 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;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.InsetDrawable;
import android.os.UserHandle;
import android.support.annotation.WorkerThread;
import android.text.format.Formatter;
import android.util.Log;
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 = "PhotosViewHolderController";
private static final String IMAGE_MIME_TYPE = "image/*";
private static final int INSET_SIZE = 24; // dp
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(AppViewHolder holder) {
holder.appIcon.setImageDrawable(
new InsetDrawable(mContext.getDrawable(R.drawable.ic_photo_library), INSET_SIZE));
holder.appName.setText(mContext.getText(R.string.storage_detail_images));
holder.summary.setText(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);
Utils.launchIntent(fragment, intent);
}
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.deviceinfo.storage;
import static android.content.pm.ApplicationInfo.CATEGORY_AUDIO;
import static android.content.pm.ApplicationInfo.CATEGORY_GAME;
import static android.content.pm.ApplicationInfo.CATEGORY_IMAGE;
import static android.content.pm.ApplicationInfo.CATEGORY_VIDEO;
import android.content.Context;
@@ -134,6 +135,9 @@ public class StorageAsyncLoader
case CATEGORY_VIDEO:
result.videoAppsSize += blamedSize;
break;
case CATEGORY_IMAGE:
result.photosAppsSize += blamedSize;
break;
default:
// The deprecated game flag does not set the category.
if ((app.flags & ApplicationInfo.FLAG_IS_GAME) != 0) {
@@ -163,6 +167,7 @@ public class StorageAsyncLoader
public static class AppsStorageResult {
public long gamesSize;
public long musicAppsSize;
public long photosAppsSize;
public long videoAppsSize;
public long otherAppsSize;
public long cacheSize;

View File

@@ -59,7 +59,6 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
PreferenceControllerMixin {
private static final String TAG = "StorageItemPreference";
private static final String IMAGE_MIME_TYPE = "image/*";
private static final String SYSTEM_FRAGMENT_TAG = "SystemInfo";
@VisibleForTesting
@@ -93,9 +92,9 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
private StorageItemPreference mAppPreference;
private StorageItemPreference mFilePreference;
private StorageItemPreference mSystemPreference;
private boolean mIsWorkProfile;
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
private boolean mIsWorkProfile;
public StorageItemPreferenceController(
Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
@@ -259,7 +258,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
// TODO(b/35927909): Figure out how to split out apps which are only installed for work
// profiles in order to attribute those app's code bytes only to that profile.
mPhotoPreference.setStorageSize(
data.externalStats.imageBytes + data.externalStats.videoBytes, mTotalSize);
data.photosAppsSize + data.externalStats.imageBytes + data.externalStats.videoBytes,
mTotalSize);
mAudioPreference.setStorageSize(
data.musicAppsSize + data.externalStats.audioBytes, mTotalSize);
mGamePreference.setStorageSize(data.gamesSize, mTotalSize);
@@ -280,10 +280,12 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
long attributedSize = 0;
for (int i = 0; i < result.size(); i++) {
final StorageAsyncLoader.AppsStorageResult otherData = result.valueAt(i);
attributedSize += otherData.gamesSize
+ otherData.musicAppsSize
+ otherData.videoAppsSize
+ otherData.otherAppsSize;
attributedSize +=
otherData.gamesSize
+ otherData.musicAppsSize
+ otherData.videoAppsSize
+ otherData.photosAppsSize
+ otherData.otherAppsSize;
attributedSize += otherData.externalStats.totalBytes
- otherData.externalStats.appBytes;
}
@@ -317,12 +319,21 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
}
private Intent getPhotosIntent() {
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);
return intent;
Bundle args = new Bundle(2);
args.putString(
ManageApplications.EXTRA_CLASSNAME, Settings.PhotosStorageActivity.class.getName());
args.putInt(
ManageApplications.EXTRA_STORAGE_TYPE,
ManageApplications.STORAGE_TYPE_PHOTOS_VIDEOS);
return Utils.onBuildStartFragmentIntent(
mContext,
ManageApplications.class.getName(),
args,
null,
R.string.storage_photos_videos,
null,
false,
mMetricsFeatureProvider.getMetricsCategory(mFragment));
}
private Intent getAudioIntent() {

View File

@@ -0,0 +1,88 @@
package com.android.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.view.LayoutInflater;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
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.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class PhotosViewHolderControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
@Mock private StorageVolumeProvider mSvp;
@Mock private StorageStatsSource mSource;
private Context mContext;
private PhotosViewHolderController mController;
private VolumeInfo mVolume;
private AppViewHolder mHolder;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mVolume = new VolumeInfo("id", 0, null, "id");
mController =
new PhotosViewHolderController(
mContext, mSource, mVolume.fsUuid, new UserHandle(0));
LayoutInflater inflater = LayoutInflater.from(mContext);
mHolder = AppViewHolder.createOrRecycle(inflater, null);
}
@Test
public void storageShouldBeZeroBytesIfQueriedBeforeStorageQueryFinishes() {
mController.setupView(mHolder);
assertThat(mHolder.summary.getText().toString()).isEqualTo("0.00B");
}
@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.summary.getText().toString()).isEqualTo("11.00B");
}
@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

@@ -121,9 +121,12 @@ public class StorageItemPreferenceControllerTest {
nullable(UserHandle.class));
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();
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);
}
@Test