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