Merge "Make photos/videos storage preference normal." into oc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3d1f6abd6f
@@ -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 */ }
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
@@ -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() {
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
Reference in New Issue
Block a user