Make photos/videos storage preference normal.

We had special behavior for it in the past, but this defines new
behavior that is much closer to what the other storage preferences do.
A photo app filter is used and a photos/video files preference exists on
it which intents over to the gallery app.

Fixes: 64147318
Test: Settings robotests

Change-Id: I47284515fe2dfcc924ae61a44bc47051e9f5fda6
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index a696172..ee041e8 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -21,7 +21,6 @@
 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 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 */ }
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index b932496..11eb0cc 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -59,6 +59,7 @@
 
 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 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 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 @@
         } 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 @@
                         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 @@
             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 @@
             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 @@
                 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 @@
             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.
diff --git a/src/com/android/settings/applications/PhotosViewHolderController.java b/src/com/android/settings/applications/PhotosViewHolderController.java
new file mode 100644
index 0000000..a652bb1
--- /dev/null
+++ b/src/com/android/settings/applications/PhotosViewHolderController.java
@@ -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);
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
index 630df85..f92a24e 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
@@ -18,6 +18,7 @@
 
 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 @@
                 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 static class AppsStorageResult {
         public long gamesSize;
         public long musicAppsSize;
+        public long photosAppsSize;
         public long videoAppsSize;
         public long otherAppsSize;
         public long cacheSize;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 99679d6..ca85f69 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -59,7 +59,6 @@
         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 @@
     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 @@
         // 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 @@
             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 @@
     }
 
     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() {