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