Home | History | Annotate | Download | only in documentsui
      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;
     18 
     19 import static com.android.documentsui.Shared.DEBUG;
     20 
     21 import android.annotation.IntDef;
     22 import android.content.Intent;
     23 import android.os.Parcel;
     24 import android.os.Parcelable;
     25 import android.util.Log;
     26 import android.util.SparseArray;
     27 
     28 import com.android.documentsui.dirlist.MultiSelectManager.Selection;
     29 import com.android.documentsui.model.DocumentInfo;
     30 import com.android.documentsui.model.DocumentStack;
     31 import com.android.documentsui.model.DurableUtils;
     32 import com.android.documentsui.model.RootInfo;
     33 import com.android.documentsui.services.FileOperationService;
     34 import com.android.documentsui.services.FileOperationService.OpType;
     35 
     36 import java.lang.annotation.Retention;
     37 import java.lang.annotation.RetentionPolicy;
     38 import java.util.ArrayList;
     39 import java.util.HashMap;
     40 import java.util.List;
     41 
     42 public class State implements android.os.Parcelable {
     43 
     44     private static final String TAG = "State";
     45 
     46     @IntDef(flag = true, value = {
     47             ACTION_BROWSE,
     48             ACTION_PICK_COPY_DESTINATION,
     49             ACTION_OPEN,
     50             ACTION_CREATE,
     51             ACTION_GET_CONTENT,
     52             ACTION_OPEN_TREE
     53     })
     54     @Retention(RetentionPolicy.SOURCE)
     55     public @interface ActionType {}
     56     // File manager and related private picking activity.
     57     public static final int ACTION_BROWSE = 1;
     58     public static final int ACTION_PICK_COPY_DESTINATION = 2;
     59     // All public picking activities
     60     public static final int ACTION_OPEN = 3;
     61     public static final int ACTION_CREATE = 4;
     62     public static final int ACTION_GET_CONTENT = 5;
     63     public static final int ACTION_OPEN_TREE = 6;
     64 
     65     @IntDef(flag = true, value = {
     66             MODE_UNKNOWN,
     67             MODE_LIST,
     68             MODE_GRID
     69     })
     70     @Retention(RetentionPolicy.SOURCE)
     71     public @interface ViewMode {}
     72     public static final int MODE_UNKNOWN = 0;
     73     public static final int MODE_LIST = 1;
     74     public static final int MODE_GRID = 2;
     75 
     76     public static final int SORT_ORDER_UNKNOWN = 0;
     77     public static final int SORT_ORDER_DISPLAY_NAME = 1;
     78     public static final int SORT_ORDER_LAST_MODIFIED = 2;
     79     public static final int SORT_ORDER_SIZE = 3;
     80 
     81     public @ActionType int action;
     82     public String[] acceptMimes;
     83 
     84     /** Derived from local preferences */
     85     public @ViewMode int derivedMode = MODE_GRID;
     86 
     87     /** Explicit user choice */
     88     public int userSortOrder = SORT_ORDER_UNKNOWN;
     89     /** Derived after loader */
     90     public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
     91 
     92     public boolean allowMultiple;
     93     public boolean forceSize;
     94     public boolean showSize;
     95     public boolean localOnly;
     96     public boolean showAdvancedOption;
     97     public boolean showAdvanced;
     98     public boolean restored;
     99     /*
    100      * Indicates handler was an external app, like photos.
    101      */
    102     public boolean external;
    103 
    104     // Indicates that a copy operation (or move) includes a directory.
    105     // Why? Directory creation isn't supported by some roots (like Downloads).
    106     // This allows us to restrict available roots to just those with support.
    107     public boolean directoryCopy;
    108     public boolean openableOnly;
    109 
    110     /**
    111      * This is basically a sub-type for the copy operation. It can be either COPY or MOVE.
    112      * The only legal values, if set, are: OPERATION_COPY, OPERATION_MOVE. Other pick
    113      * operations don't use this. In those cases OPERATION_UNKNOWN is also legal.
    114      */
    115     public @OpType int copyOperationSubType = FileOperationService.OPERATION_UNKNOWN;
    116 
    117     /** Current user navigation stack; empty implies recents. */
    118     public DocumentStack stack = new DocumentStack();
    119     private boolean mStackTouched;
    120     private boolean mInitialRootChanged;
    121     private boolean mInitialDocChanged;
    122 
    123     /** Instance state for every shown directory */
    124     public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
    125 
    126     /** Currently copying file */
    127     public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<>();
    128 
    129     /** Name of the package that started DocsUI */
    130     public List<String> excludedAuthorities = new ArrayList<>();
    131 
    132     public void initAcceptMimes(Intent intent) {
    133         if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
    134             acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
    135         } else {
    136             String glob = intent.getType();
    137             acceptMimes = new String[] { glob != null ? glob : "*/*" };
    138         }
    139     }
    140 
    141     public void onRootChanged(RootInfo root) {
    142         if (DEBUG) Log.d(TAG, "Root changed to: " + root);
    143         if (!mInitialRootChanged && stack.root != null && !root.equals(stack.root)) {
    144             mInitialRootChanged = true;
    145         }
    146         stack.root = root;
    147         stack.clear();
    148         mStackTouched = true;
    149     }
    150 
    151     public void pushDocument(DocumentInfo info) {
    152         if (DEBUG) Log.d(TAG, "Adding doc to stack: " + info);
    153         if (!mInitialDocChanged && stack.size() > 0 && !info.equals(stack.peek())) {
    154             mInitialDocChanged = true;
    155         }
    156         stack.push(info);
    157         mStackTouched = true;
    158     }
    159 
    160     public void popDocument() {
    161         if (DEBUG) Log.d(TAG, "Popping doc off stack.");
    162         stack.pop();
    163         mStackTouched = true;
    164     }
    165 
    166     public void setStack(DocumentStack stack) {
    167         if (DEBUG) Log.d(TAG, "Setting the whole darn stack to: " + stack);
    168         this.stack = stack;
    169         mStackTouched = true;
    170     }
    171 
    172     // This will return true even when the initial location is set.
    173     // To get a read on if the user has changed something, use #hasInitialLocationChanged.
    174     public boolean hasLocationChanged() {
    175         return mStackTouched;
    176     }
    177 
    178     public boolean hasInitialLocationChanged() {
    179         return mInitialRootChanged || mInitialDocChanged;
    180     }
    181 
    182     @Override
    183     public int describeContents() {
    184         return 0;
    185     }
    186 
    187     @Override
    188     public void writeToParcel(Parcel out, int flags) {
    189         out.writeInt(action);
    190         out.writeStringArray(acceptMimes);
    191         out.writeInt(userSortOrder);
    192         out.writeInt(allowMultiple ? 1 : 0);
    193         out.writeInt(forceSize ? 1 : 0);
    194         out.writeInt(showSize ? 1 : 0);
    195         out.writeInt(localOnly ? 1 : 0);
    196         out.writeInt(showAdvancedOption ? 1 : 0);
    197         out.writeInt(showAdvanced ? 1 : 0);
    198         out.writeInt(restored ? 1 : 0);
    199         out.writeInt(external ? 1 : 0);
    200         DurableUtils.writeToParcel(out, stack);
    201         out.writeMap(dirState);
    202         out.writeList(selectedDocumentsForCopy);
    203         out.writeList(excludedAuthorities);
    204         out.writeInt(openableOnly ? 1 : 0);
    205         out.writeInt(mStackTouched ? 1 : 0);
    206         out.writeInt(mInitialRootChanged ? 1 : 0);
    207         out.writeInt(mInitialDocChanged ? 1 : 0);
    208     }
    209 
    210     public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() {
    211         @Override
    212         public State createFromParcel(Parcel in) {
    213             return createFromParcel(in, null);
    214         }
    215 
    216         @Override
    217         public State createFromParcel(Parcel in, ClassLoader loader) {
    218             final State state = new State();
    219             state.action = in.readInt();
    220             state.acceptMimes = in.readStringArray();
    221             state.userSortOrder = in.readInt();
    222             state.allowMultiple = in.readInt() != 0;
    223             state.forceSize = in.readInt() != 0;
    224             state.showSize = in.readInt() != 0;
    225             state.localOnly = in.readInt() != 0;
    226             state.showAdvancedOption = in.readInt() != 0;
    227             state.showAdvanced = in.readInt() != 0;
    228             state.restored = in.readInt() != 0;
    229             state.external = in.readInt() != 0;
    230             DurableUtils.readFromParcel(in, state.stack);
    231             in.readMap(state.dirState, loader);
    232             in.readList(state.selectedDocumentsForCopy, loader);
    233             in.readList(state.excludedAuthorities, loader);
    234             state.openableOnly = in.readInt() != 0;
    235             state.mStackTouched = in.readInt() != 0;
    236             state.mInitialRootChanged = in.readInt() != 0;
    237             state.mInitialDocChanged = in.readInt() != 0;
    238             return state;
    239         }
    240 
    241         @Override
    242         public State[] newArray(int size) {
    243             return new State[size];
    244         }
    245     };
    246 }
    247