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 85 public boolean openableOnly; 86 public boolean restrictScopeStorage; 87 public boolean showHiddenFiles; 88 89 /** 90 * Represents whether the state supports cross-profile file picking. 91 */ 92 public boolean supportsCrossProfile = false; 93 94 /** 95 * Represents whether the intent is a cross-profile intent 96 */ 97 public boolean canShareAcrossProfile = false; 98 99 /** 100 * Returns true if we are allowed to interact with the user. 101 */ canInteractWith(UserId userId)102 public boolean canInteractWith(UserId userId) { 103 return canShareAcrossProfile || UserId.CURRENT_USER.equals(userId); 104 } 105 106 /** 107 * This is basically a sub-type for the copy operation. It can be either COPY, 108 * COMPRESS, EXTRACT or MOVE. 109 * The only legal values, if set, are: OPERATION_COPY, OPERATION_COMPRESS, 110 * OPERATION_EXTRACT and OPERATION_MOVE. Other pick 111 * operations don't use this. In those cases OPERATION_UNKNOWN is also legal. 112 */ 113 public @OpType int copyOperationSubType = FileOperationService.OPERATION_UNKNOWN; 114 115 /** Current user navigation stack; empty implies recents. */ 116 public final DocumentStack stack = new DocumentStack(); 117 118 /** Instance configs for every shown directory */ 119 public HashMap<String, SparseArray<Parcelable>> dirConfigs = new HashMap<>(); 120 121 /** Name of the package that started DocsUI */ 122 public List<String> excludedAuthorities = new ArrayList<>(); 123 initAcceptMimes(Intent intent, String defaultAcceptMimeType)124 public void initAcceptMimes(Intent intent, String defaultAcceptMimeType) { 125 if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { 126 acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES); 127 } else { 128 acceptMimes = new String[] { defaultAcceptMimeType }; 129 } 130 } 131 132 /** 133 * Check current action should have preview function or not. 134 * @return True, if the action should have preview. 135 */ shouldShowPreview()136 public boolean shouldShowPreview() { 137 return action == ACTION_GET_CONTENT 138 || action == ACTION_OPEN_TREE 139 || action == ACTION_OPEN; 140 } 141 142 /** 143 * Check the action is file picking and acceptMimes are all images type or not. 144 * @return True, if acceptMimes are all image type and action is file picking. 145 */ isPhotoPicking()146 public boolean isPhotoPicking() { 147 if (action != ACTION_GET_CONTENT && action != ACTION_OPEN || acceptMimes == null) { 148 return false; 149 } 150 151 for (String mimeType : acceptMimes) { 152 if (!MimeTypes.mimeMatches(MimeTypes.IMAGE_MIME, mimeType)) { 153 return false; 154 } 155 } 156 return true; 157 } 158 159 /** 160 * Returns true if DocsUI supports cross-profile for this {@link State}. 161 */ supportsCrossProfile()162 public boolean supportsCrossProfile() { 163 return supportsCrossProfile; 164 } 165 166 @Override describeContents()167 public int describeContents() { 168 return 0; 169 } 170 171 @Override writeToParcel(Parcel out, int flags)172 public void writeToParcel(Parcel out, int flags) { 173 out.writeInt(action); 174 out.writeStringArray(acceptMimes); 175 out.writeInt(allowMultiple ? 1 : 0); 176 out.writeInt(localOnly ? 1 : 0); 177 DurableUtils.writeToParcel(out, stack); 178 out.writeMap(dirConfigs); 179 out.writeList(excludedAuthorities); 180 out.writeInt(openableOnly ? 1 : 0); 181 out.writeInt(restrictScopeStorage ? 1 : 0); 182 out.writeParcelable(sortModel, 0); 183 } 184 185 @Override toString()186 public String toString() { 187 return "State{" 188 + "action=" + action 189 + ", acceptMimes=" + Arrays.toString(acceptMimes) 190 + ", allowMultiple=" + allowMultiple 191 + ", localOnly=" + localOnly 192 + ", stack=" + stack 193 + ", dirConfigs=" + dirConfigs 194 + ", excludedAuthorities=" + excludedAuthorities 195 + ", openableOnly=" + openableOnly 196 + ", restrictScopeStorage=" + restrictScopeStorage 197 + ", sortModel=" + sortModel 198 + "}"; 199 } 200 201 public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() { 202 @Override 203 public State createFromParcel(Parcel in) { 204 return createFromParcel(in, null); 205 } 206 207 @Override 208 public State createFromParcel(Parcel in, ClassLoader loader) { 209 final State state = new State(); 210 state.action = in.readInt(); 211 state.acceptMimes = in.createStringArray(); 212 state.allowMultiple = in.readInt() != 0; 213 state.localOnly = in.readInt() != 0; 214 DurableUtils.readFromParcel(in, state.stack); 215 in.readMap(state.dirConfigs, loader); 216 in.readList(state.excludedAuthorities, loader); 217 state.openableOnly = in.readInt() != 0; 218 state.restrictScopeStorage = in.readInt() != 0; 219 state.sortModel = in.readParcelable(loader); 220 return state; 221 } 222 223 @Override 224 public State[] newArray(int size) { 225 return new State[size]; 226 } 227 }; 228 } 229