/* * 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()) { if (canForwardToProfileIdMap.isEmpty() && UserId.CURRENT_USER.equals(userId)) { return true; } 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 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> dirConfigs = new HashMap<>(); /** Name of the package that started DocsUI */ public List 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 CREATOR = new ClassLoaderCreator() { @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]; } }; }