| /* |
| * Copyright (C) 2013 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.documentsui.base; |
| |
| import android.content.Intent; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.util.SparseArray; |
| |
| import androidx.annotation.IntDef; |
| |
| import com.android.documentsui.ConfigStore; |
| import com.android.documentsui.services.FileOperationService; |
| import com.android.documentsui.services.FileOperationService.OpType; |
| import com.android.documentsui.sorting.SortModel; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| public class State implements android.os.Parcelable { |
| |
| private static final String TAG = "State"; |
| |
| @IntDef(flag = true, value = { |
| ACTION_BROWSE, |
| ACTION_PICK_COPY_DESTINATION, |
| ACTION_OPEN, |
| ACTION_CREATE, |
| ACTION_GET_CONTENT, |
| ACTION_OPEN_TREE |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface ActionType { |
| } |
| |
| // File manager and related private picking activity. |
| public static final int ACTION_BROWSE = 1; |
| public static final int ACTION_PICK_COPY_DESTINATION = 2; |
| // All public picking activities |
| public static final int ACTION_OPEN = 3; |
| public static final int ACTION_CREATE = 4; |
| public static final int ACTION_GET_CONTENT = 5; |
| public static final int ACTION_OPEN_TREE = 6; |
| |
| @IntDef(flag = true, value = { |
| MODE_UNKNOWN, |
| MODE_LIST, |
| MODE_GRID |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface ViewMode { |
| } |
| |
| public static final int MODE_UNKNOWN = 0; |
| public static final int MODE_LIST = 1; |
| public static final int MODE_GRID = 2; |
| |
| public @ActionType int action; |
| public String[] acceptMimes; |
| |
| /** Derived from local preferences */ |
| public @ViewMode int derivedMode = MODE_GRID; |
| |
| public boolean debugMode = false; |
| |
| /** Current sort state */ |
| public SortModel sortModel; |
| |
| public boolean allowMultiple; |
| public boolean localOnly; |
| |
| public boolean openableOnly; |
| public boolean restrictScopeStorage; |
| public boolean showHiddenFiles; |
| public ConfigStore configStore; |
| |
| /** |
| * Represents whether the state supports cross-profile file picking. |
| */ |
| public boolean supportsCrossProfile = false; |
| |
| /** |
| * Represents whether the intent is a cross-profile intent |
| */ |
| public boolean canShareAcrossProfile = false; |
| |
| /** |
| * Returns true if we are allowed to interact with the user. |
| */ |
| public boolean canInteractWith(UserId userId) { |
| if (configStore.isPrivateSpaceInDocsUIEnabled()) { |
| return canForwardToProfileIdMap.getOrDefault(userId, false); |
| } |
| return canShareAcrossProfile || UserId.CURRENT_USER.equals(userId); |
| } |
| |
| /** |
| * Represents whether the intent can be forwarded to the {@link UserId} in the map |
| */ |
| public Map<UserId, Boolean> canForwardToProfileIdMap = new HashMap<>(); |
| |
| |
| /** |
| * This is basically a sub-type for the copy operation. It can be either COPY, |
| * COMPRESS, EXTRACT or MOVE. |
| * The only legal values, if set, are: OPERATION_COPY, OPERATION_COMPRESS, |
| * OPERATION_EXTRACT and OPERATION_MOVE. Other pick |
| * operations don't use this. In those cases OPERATION_UNKNOWN is also legal. |
| */ |
| public @OpType int copyOperationSubType = FileOperationService.OPERATION_UNKNOWN; |
| |
| /** Current user navigation stack; empty implies recents. */ |
| public final DocumentStack stack = new DocumentStack(); |
| |
| /** Instance configs for every shown directory */ |
| public HashMap<String, SparseArray<Parcelable>> dirConfigs = new HashMap<>(); |
| |
| /** Name of the package that started DocsUI */ |
| public List<String> excludedAuthorities = new ArrayList<>(); |
| |
| public void initAcceptMimes(Intent intent, String defaultAcceptMimeType) { |
| if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { |
| acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES); |
| } else { |
| acceptMimes = new String[]{defaultAcceptMimeType}; |
| } |
| } |
| |
| /** |
| * Check current action should have preview function or not. |
| * |
| * @return True, if the action should have preview. |
| */ |
| public boolean shouldShowPreview() { |
| return action == ACTION_GET_CONTENT |
| || action == ACTION_OPEN_TREE |
| || action == ACTION_OPEN; |
| } |
| |
| /** |
| * Check the action is file picking and acceptMimes are all images type or not. |
| * |
| * @return True, if acceptMimes are all image type and action is file picking. |
| */ |
| public boolean isPhotoPicking() { |
| if (action != ACTION_GET_CONTENT && action != ACTION_OPEN || acceptMimes == null) { |
| return false; |
| } |
| |
| for (String mimeType : acceptMimes) { |
| if (!MimeTypes.mimeMatches(MimeTypes.IMAGE_MIME, mimeType)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Returns true if DocsUI supports cross-profile for this {@link State}. |
| */ |
| public boolean supportsCrossProfile() { |
| return supportsCrossProfile; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel out, int flags) { |
| out.writeInt(action); |
| out.writeStringArray(acceptMimes); |
| out.writeInt(allowMultiple ? 1 : 0); |
| out.writeInt(localOnly ? 1 : 0); |
| DurableUtils.writeToParcel(out, stack); |
| out.writeMap(dirConfigs); |
| out.writeList(excludedAuthorities); |
| out.writeInt(openableOnly ? 1 : 0); |
| out.writeInt(restrictScopeStorage ? 1 : 0); |
| out.writeParcelable(sortModel, 0); |
| } |
| |
| @Override |
| public String toString() { |
| return "State{" |
| + "action=" + action |
| + ", acceptMimes=" + Arrays.toString(acceptMimes) |
| + ", allowMultiple=" + allowMultiple |
| + ", localOnly=" + localOnly |
| + ", stack=" + stack |
| + ", dirConfigs=" + dirConfigs |
| + ", excludedAuthorities=" + excludedAuthorities |
| + ", openableOnly=" + openableOnly |
| + ", restrictScopeStorage=" + restrictScopeStorage |
| + ", sortModel=" + sortModel |
| + "}"; |
| } |
| |
| public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() { |
| @Override |
| public State createFromParcel(Parcel in) { |
| return createFromParcel(in, null); |
| } |
| |
| @Override |
| public State createFromParcel(Parcel in, ClassLoader loader) { |
| final State state = new State(); |
| state.action = in.readInt(); |
| state.acceptMimes = in.createStringArray(); |
| state.allowMultiple = in.readInt() != 0; |
| state.localOnly = in.readInt() != 0; |
| DurableUtils.readFromParcel(in, state.stack); |
| in.readMap(state.dirConfigs, loader); |
| in.readList(state.excludedAuthorities, loader); |
| state.openableOnly = in.readInt() != 0; |
| state.restrictScopeStorage = in.readInt() != 0; |
| state.sortModel = in.readParcelable(loader); |
| return state; |
| } |
| |
| @Override |
| public State[] newArray(int size) { |
| return new State[size]; |
| } |
| }; |
| } |