1 /*
2  * Copyright (C) 2013 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.documentsui.base;
18 
19 import android.content.Intent;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.util.SparseArray;
23 
24 import androidx.annotation.IntDef;
25 
26 import com.android.documentsui.services.FileOperationService;
27 import com.android.documentsui.services.FileOperationService.OpType;
28 import com.android.documentsui.sorting.SortModel;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.List;
36 
37 public class State implements android.os.Parcelable {
38 
39     private static final String TAG = "State";
40 
41     @IntDef(flag = true, value = {
42             ACTION_BROWSE,
43             ACTION_PICK_COPY_DESTINATION,
44             ACTION_OPEN,
45             ACTION_CREATE,
46             ACTION_GET_CONTENT,
47             ACTION_OPEN_TREE
48     })
49     @Retention(RetentionPolicy.SOURCE)
50     public @interface ActionType {}
51     // File manager and related private picking activity.
52     public static final int ACTION_BROWSE = 1;
53     public static final int ACTION_PICK_COPY_DESTINATION = 2;
54     // All public picking activities
55     public static final int ACTION_OPEN = 3;
56     public static final int ACTION_CREATE = 4;
57     public static final int ACTION_GET_CONTENT = 5;
58     public static final int ACTION_OPEN_TREE = 6;
59 
60     @IntDef(flag = true, value = {
61             MODE_UNKNOWN,
62             MODE_LIST,
63             MODE_GRID
64     })
65     @Retention(RetentionPolicy.SOURCE)
66     public @interface ViewMode {}
67     public static final int MODE_UNKNOWN = 0;
68     public static final int MODE_LIST = 1;
69     public static final int MODE_GRID = 2;
70 
71     public @ActionType int action;
72     public String[] acceptMimes;
73 
74     /** Derived from local preferences */
75     public @ViewMode int derivedMode = MODE_GRID;
76 
77     public boolean debugMode = false;
78 
79     /** Current sort state */
80     public SortModel sortModel;
81 
82     public boolean allowMultiple;
83     public boolean localOnly;
84     public boolean showDeviceStorageOption;
85     public boolean showAdvanced;
86 
87     // Indicates that a copy operation (or move) includes a directory.
88     // Why? Directory creation isn't supported by some roots (like Downloads).
89     // This allows us to restrict available roots to just those with support.
90     public boolean directoryCopy;
91     public boolean openableOnly;
92 
93     /**
94      * This is basically a sub-type for the copy operation. It can be either COPY,
95      * COMPRESS, EXTRACT or MOVE.
96      * The only legal values, if set, are: OPERATION_COPY, OPERATION_COMPRESS,
97      * OPERATION_EXTRACT and OPERATION_MOVE. Other pick
98      * operations don't use this. In those cases OPERATION_UNKNOWN is also legal.
99      */
100     public @OpType int copyOperationSubType = FileOperationService.OPERATION_UNKNOWN;
101 
102     /** Current user navigation stack; empty implies recents. */
103     public final DocumentStack stack = new DocumentStack();
104 
105     /** Instance configs for every shown directory */
106     public HashMap<String, SparseArray<Parcelable>> dirConfigs = new HashMap<>();
107 
108     /** Name of the package that started DocsUI */
109     public List<String> excludedAuthorities = new ArrayList<>();
110 
initAcceptMimes(Intent intent, String defaultAcceptMimeType)111     public void initAcceptMimes(Intent intent, String defaultAcceptMimeType) {
112         if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
113             acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
114         } else {
115             acceptMimes = new String[] { defaultAcceptMimeType };
116         }
117     }
118 
119     /**
120      * Check current action should have preview function or not.
121      * @return True, if the action should have preview.
122      */
shouldShowPreview()123     public boolean shouldShowPreview() {
124         return action == ACTION_GET_CONTENT
125                 || action == ACTION_OPEN_TREE
126                 || action == ACTION_OPEN;
127     }
128 
129     /**
130      * Check the action is file picking and acceptMimes are all images type or not.
131      * @return True, if acceptMimes are all image type and action is file picking.
132      */
isPhotoPicking()133     public boolean isPhotoPicking() {
134         if (action != ACTION_GET_CONTENT && action != ACTION_OPEN || acceptMimes == null) {
135             return false;
136         }
137 
138         for (String mimeType : acceptMimes) {
139             if (!MimeTypes.mimeMatches(MimeTypes.IMAGE_MIME, mimeType)) {
140                 return false;
141             }
142         }
143         return true;
144     }
145 
146     @Override
describeContents()147     public int describeContents() {
148         return 0;
149     }
150 
151     @Override
writeToParcel(Parcel out, int flags)152     public void writeToParcel(Parcel out, int flags) {
153         out.writeInt(action);
154         out.writeStringArray(acceptMimes);
155         out.writeInt(allowMultiple ? 1 : 0);
156         out.writeInt(localOnly ? 1 : 0);
157         out.writeInt(showDeviceStorageOption ? 1 : 0);
158         out.writeInt(showAdvanced ? 1 : 0);
159         DurableUtils.writeToParcel(out, stack);
160         out.writeMap(dirConfigs);
161         out.writeList(excludedAuthorities);
162         out.writeInt(openableOnly ? 1 : 0);
163         out.writeParcelable(sortModel, 0);
164     }
165 
166     @Override
toString()167     public String toString() {
168         return "State{"
169                 + "action=" + action
170                 + ", acceptMimes=" + Arrays.toString(acceptMimes)
171                 + ", allowMultiple=" + allowMultiple
172                 + ", localOnly=" + localOnly
173                 + ", showDeviceStorageOption=" + showDeviceStorageOption
174                 + ", showAdvanced=" + showAdvanced
175                 + ", stack=" + stack
176                 + ", dirConfigs=" + dirConfigs
177                 + ", excludedAuthorities=" + excludedAuthorities
178                 + ", openableOnly=" + openableOnly
179                 + ", sortModel=" + sortModel
180                 + "}";
181     }
182 
183     public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() {
184         @Override
185         public State createFromParcel(Parcel in) {
186             return createFromParcel(in, null);
187         }
188 
189         @Override
190         public State createFromParcel(Parcel in, ClassLoader loader) {
191             final State state = new State();
192             state.action = in.readInt();
193             state.acceptMimes = in.createStringArray();
194             state.allowMultiple = in.readInt() != 0;
195             state.localOnly = in.readInt() != 0;
196             state.showDeviceStorageOption = in.readInt() != 0;
197             state.showAdvanced = in.readInt() != 0;
198             DurableUtils.readFromParcel(in, state.stack);
199             in.readMap(state.dirConfigs, loader);
200             in.readList(state.excludedAuthorities, loader);
201             state.openableOnly = in.readInt() != 0;
202             state.sortModel = in.readParcelable(loader);
203             return state;
204         }
205 
206         @Override
207         public State[] newArray(int size) {
208             return new State[size];
209         }
210     };
211 }
212