• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.providers.media.photopicker.data.model;
18 
19 import static android.provider.CloudMediaProviderContract.AlbumColumns;
20 import static android.provider.CloudMediaProviderContract.AlbumColumns.ALBUM_ID_CAMERA;
21 import static android.provider.CloudMediaProviderContract.AlbumColumns.ALBUM_ID_DOWNLOADS;
22 import static android.provider.CloudMediaProviderContract.AlbumColumns.ALBUM_ID_FAVORITES;
23 import static android.provider.CloudMediaProviderContract.AlbumColumns.ALBUM_ID_SCREENSHOTS;
24 import static android.provider.CloudMediaProviderContract.AlbumColumns.ALBUM_ID_VIDEOS;
25 
26 import static com.android.providers.media.photopicker.util.CursorUtils.getCursorInt;
27 import static com.android.providers.media.photopicker.util.CursorUtils.getCursorString;
28 
29 import android.content.Context;
30 import android.database.Cursor;
31 import android.net.Uri;
32 import android.os.Bundle;
33 import android.provider.MediaStore;
34 import android.text.TextUtils;
35 import android.util.Log;
36 
37 import androidx.annotation.NonNull;
38 import androidx.annotation.VisibleForTesting;
39 
40 import com.android.providers.media.R;
41 import com.android.providers.media.photopicker.data.ItemsProvider;
42 
43 import java.util.Locale;
44 
45 /**
46  * Defines each category (which is group of items) for the photo picker.
47  */
48 public class Category {
49     public static final String TAG = "PhotoPicker";
50     public static final Category DEFAULT = new Category();
51 
52     private final String mId;
53     private final String mAuthority;
54     private final String mDisplayName;
55     private final boolean mIsLocal;
56     private final Uri mCoverUri;
57     private final int mItemCount;
58 
Category()59     private Category() {
60         this(null, null, null, null, 0, false);
61     }
62 
63     @VisibleForTesting
Category(String id, String authority, String displayName, Uri coverUri, int itemCount, boolean isLocal)64     public Category(String id, String authority, String displayName, Uri coverUri, int itemCount,
65             boolean isLocal) {
66         mId = id;
67         mAuthority = authority;
68         mDisplayName = displayName;
69         mIsLocal = isLocal;
70         mCoverUri = coverUri;
71         mItemCount = itemCount;
72     }
73 
74     @Override
toString()75     public String toString() {
76         return String.format(Locale.ROOT, "Category: {mId: %s, mAuthority: %s, mDisplayName: %s, " +
77                 "mCoverUri: %s, mItemCount: %d, mIsLocal: %b",
78                 mId, mAuthority, mDisplayName, mCoverUri, mItemCount, mIsLocal);
79     }
80 
getId()81     public String getId() {
82         return mId;
83     }
84 
getAuthority()85     public String getAuthority() {
86         return mAuthority;
87     }
88 
getDisplayName(Context context)89     public String getDisplayName(Context context) {
90         if (mIsLocal) {
91             return getLocalizedDisplayName(context, mId);
92         }
93         return mDisplayName;
94     }
95 
isLocal()96     public boolean isLocal() {
97         return mIsLocal;
98     }
99 
getCoverUri()100     public Uri getCoverUri() {
101         return mCoverUri;
102     }
103 
getItemCount()104     public int getItemCount() {
105         return mItemCount;
106     }
107 
isDefault()108     public boolean isDefault() {
109         return TextUtils.isEmpty(mId);
110     }
111 
112     /**
113      * Write the {@link Category} to the given {@code bundle}.
114      */
toBundle(@onNull Bundle bundle)115     public void toBundle(@NonNull Bundle bundle) {
116         bundle.putString(AlbumColumns.ID, mId);
117         bundle.putString(AlbumColumns.AUTHORITY, mAuthority);
118         bundle.putString(AlbumColumns.DISPLAY_NAME, mDisplayName);
119         // Re-using the 'media_cover_id' to store the media_cover_uri for lack of
120         // a different constant
121         bundle.putParcelable(AlbumColumns.MEDIA_COVER_ID, mCoverUri);
122         bundle.putInt(AlbumColumns.MEDIA_COUNT, mItemCount);
123         bundle.putBoolean(AlbumColumns.IS_LOCAL, mIsLocal);
124     }
125 
126     /**
127      * Create a {@link Category} from the {@code bundle}.
128      */
fromBundle(@onNull Bundle bundle)129     public static Category fromBundle(@NonNull Bundle bundle) {
130         return new Category(bundle.getString(AlbumColumns.ID),
131                 bundle.getString(AlbumColumns.AUTHORITY),
132                 bundle.getString(AlbumColumns.DISPLAY_NAME),
133                 bundle.getParcelable(AlbumColumns.MEDIA_COVER_ID),
134                 bundle.getInt(AlbumColumns.MEDIA_COUNT),
135                 bundle.getBoolean(AlbumColumns.IS_LOCAL));
136     }
137 
138     /**
139      * Create a {@link Category} from the {@code cursor}.
140      */
fromCursor(@onNull Cursor cursor, @NonNull UserId userId)141     public static Category fromCursor(@NonNull Cursor cursor, @NonNull UserId userId) {
142         String authority = getCursorString(cursor, AlbumColumns.AUTHORITY);
143         if (authority == null) {
144             // Authority will be null for cloud albums in cursor.
145             String cloudProvider = cursor.getExtras().getString(MediaStore.EXTRA_CLOUD_PROVIDER);
146             if (cloudProvider == null) {
147                 // If cloud provider is null, cloud albums will not show up properly.
148                 Log.e(TAG, "Cloud provider is set by the user but not passed in album media cursor"
149                         + " extras.");
150             } else {
151                 authority = cloudProvider;
152             }
153         }
154         final boolean isLocal = authority != null
155                 && authority.equals(cursor.getExtras().getString(MediaStore.EXTRA_LOCAL_PROVIDER));
156         final Uri coverUri = ItemsProvider.getItemsUri(
157                 getCursorString(cursor, AlbumColumns.MEDIA_COVER_ID), authority, userId);
158 
159         return new Category(getCursorString(cursor, AlbumColumns.ID),
160                 authority,
161                 getCursorString(cursor, AlbumColumns.DISPLAY_NAME),
162                 coverUri,
163                 getCursorInt(cursor, AlbumColumns.MEDIA_COUNT),
164                 isLocal);
165     }
166 
getLocalizedDisplayName(Context context, String albumId)167     private static String getLocalizedDisplayName(Context context, String albumId) {
168         switch (albumId) {
169             case ALBUM_ID_VIDEOS:
170                 return context.getString(R.string.picker_category_videos);
171             case ALBUM_ID_CAMERA:
172                 return context.getString(R.string.picker_category_camera);
173             case ALBUM_ID_SCREENSHOTS:
174                 return context.getString(R.string.picker_category_screenshots);
175             case ALBUM_ID_DOWNLOADS:
176                 return context.getString(R.string.picker_category_downloads);
177             case ALBUM_ID_FAVORITES:
178                 return context.getString(R.string.picker_category_favorites);
179             default:
180                 return albumId;
181         }
182     }
183 }
184