19e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey/*
29e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project
39e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *
49e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
59e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * you may not use this file except in compliance with the License.
69e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * You may obtain a copy of the License at
79e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *
89e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
99e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *
109e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
119e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
129e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * See the License for the specific language governing permissions and
149e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * limitations under the License.
159e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey */
169e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeypackage com.android.documentsui;
189e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
19e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
20e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport static com.android.documentsui.DirectoryFragment.ANIM_NONE;
21e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
22e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport static com.android.documentsui.DirectoryFragment.ANIM_UP;
23b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.ACTION_CREATE;
24b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
25b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
26b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.ACTION_OPEN;
27b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.ACTION_OPEN_TREE;
28b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
29b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
304eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
319e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.Activity;
329fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.app.Fragment;
339e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentManager;
344eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.ActivityNotFoundException;
35be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.content.ClipData;
3654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.ComponentName;
377aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.content.ContentProviderClient;
38be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.content.ContentResolver;
3920d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkeyimport android.content.ContentValues;
40f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkeyimport android.content.Context;
419e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.Intent;
4254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.pm.ResolveInfo;
4388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.content.res.Resources;
4454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.database.Cursor;
4588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.graphics.Point;
469e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.net.Uri;
47a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.os.AsyncTask;
489e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.os.Bundle;
49b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport android.os.Parcel;
50e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport android.os.Parcelable;
51a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkeyimport android.provider.DocumentsContract;
523e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkeyimport android.provider.DocumentsContract.Root;
53bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.app.ActionBarDrawerToggle;
54bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.widget.DrawerLayout;
55bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.widget.DrawerLayout.DrawerListener;
569e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.util.Log;
57e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport android.util.SparseArray;
589e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.LayoutInflater;
5954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.Menu;
6054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuItem;
614ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.view.MenuItem.OnActionExpandListener;
629e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.View;
639e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.ViewGroup;
6488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.view.WindowManager;
65f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkeyimport android.widget.AdapterView;
66f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkeyimport android.widget.AdapterView.OnItemSelectedListener;
6754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.BaseAdapter;
6828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkeyimport android.widget.ImageView;
69bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.widget.SearchView;
70bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.widget.SearchView.OnQueryTextListener;
71f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkeyimport android.widget.Spinner;
7254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.TextView;
737e258b31e70464bb6d80b8b42f0cef8e4417bd6aJeff Sharkeyimport android.widget.Toast;
74f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkeyimport android.widget.Toolbar;
759e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
76d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.RecentsProvider.RecentColumns;
77d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.RecentsProvider.ResumeColumns;
78ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
79b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport com.android.documentsui.model.DocumentStack;
80b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport com.android.documentsui.model.DurableUtils;
81ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.RootInfo;
82e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport com.google.common.collect.Maps;
8320d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey
84ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkeyimport libcore.io.IoUtils;
85ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
860c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkeyimport java.io.FileNotFoundException;
87b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport java.io.IOException;
88be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.Arrays;
89a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport java.util.Collection;
905545f56f7561810187545a1817b6001dd1f9931bJeff Sharkeyimport java.util.HashMap;
91be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.List;
92d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport java.util.concurrent.Executor;
93be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
949e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeypublic class DocumentsActivity extends Activity {
95ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static final String TAG = "Documents";
969e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
9788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private static final String EXTRA_STATE = "state";
9888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
995545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    private static final int CODE_FORWARD = 42;
1005545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
10188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private boolean mShowAsDialog;
10288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
103bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private SearchView mSearchView;
104bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
105f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey    private Toolbar mToolbar;
106f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey    private Spinner mToolbarStack;
107f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
108f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey    private Toolbar mRootsToolbar;
109f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
110bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private DrawerLayout mDrawerLayout;
111bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private ActionBarDrawerToggle mDrawerToggle;
112f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey    private View mRootsDrawer;
1131482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
114e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey    private DirectoryContainerView mDirectoryContainer;
115e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
116ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey    private boolean mIgnoreNextNavigation;
11788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private boolean mIgnoreNextClose;
1184ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey    private boolean mIgnoreNextCollapse;
119ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
120f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey    private boolean mSearchExpanded;
121f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
1224eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    private RootsCache mRoots;
123b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    private State mState;
12454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1259e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    @Override
1269e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    public void onCreate(Bundle icicle) {
1279e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        super.onCreate(icicle);
1289e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1294eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        mRoots = DocumentsApplication.getRootsCache(this);
1304eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
131b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        setResult(Activity.RESULT_CANCELED);
132b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        setContentView(R.layout.activity);
13354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
134f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        final Context context = this;
13588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        final Resources res = getResources();
13688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        mShowAsDialog = res.getBoolean(R.bool.show_as_dialog);
13788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
13888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mShowAsDialog) {
139f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            // Strongly define our horizontal dimension; we leave vertical as
140f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            // WRAP_CONTENT so that system resizes us when IME is showing.
14188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final WindowManager.LayoutParams a = getWindow().getAttributes();
14288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
14388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final Point size = new Point();
14488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindowManager().getDefaultDisplay().getSize(size);
145f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            a.width = (int) res.getFraction(R.dimen.dialog_width, size.x, size.x);
14688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
147f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            getWindow().setAttributes(a);
14888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
14988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        } else {
15088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            // Non-dialog means we have a drawer
15188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
1524eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
15388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
154f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                    R.drawable.ic_hamburger, R.string.drawer_open, R.string.drawer_close);
155be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
15688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerLayout.setDrawerListener(mDrawerListener);
157b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
158f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mRootsDrawer = findViewById(R.id.drawer_roots);
15988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
160b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
161e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
162e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
163b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (icicle != null) {
164b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState = icicle.getParcelable(EXTRA_STATE);
165be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else {
166b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            buildDefaultState();
16754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
16854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
169f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        mToolbar = (Toolbar) findViewById(R.id.toolbar);
170f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        mToolbar.setTitleTextAppearance(context,
171f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
172f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
173f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        mToolbarStack = (Spinner) findViewById(R.id.stack);
174f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        mToolbarStack.setOnItemSelectedListener(mStackListener);
175f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
176f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        mRootsToolbar = (Toolbar) findViewById(R.id.roots_toolbar);
177f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        if (mRootsToolbar != null) {
178f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mRootsToolbar.setTitleTextAppearance(context,
179f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                    android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
180f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        }
181f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
1828a850b4c0e0d4ceff4553dbb2490fe13f0e05f9dJeff Sharkey        setActionBar(mToolbar);
1838a850b4c0e0d4ceff4553dbb2490fe13f0e05f9dJeff Sharkey
18488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        // Hide roots when we're managing a specific root
185b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_MANAGE) {
18688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            if (mShowAsDialog) {
187f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                findViewById(R.id.container_roots).setVisibility(View.GONE);
18888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            } else {
18988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
19088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
191b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
19254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
193b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_CREATE) {
19454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final String mimeType = getIntent().getType();
19554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
19654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            SaveFragment.show(getFragmentManager(), mimeType, title);
197b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        } else if (mState.action == ACTION_OPEN_TREE) {
19821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            PickFragment.show(getFragmentManager());
19954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
200bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
201b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
20254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final Intent moreApps = new Intent(getIntent());
20354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            moreApps.setComponent(null);
20454ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            moreApps.setPackage(null);
20554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            RootsFragment.show(getFragmentManager(), moreApps);
20621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE
207b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey                || mState.action == ACTION_OPEN_TREE) {
20854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            RootsFragment.show(getFragmentManager(), null);
20954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
21066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
211a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        if (!mState.restored) {
212a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (mState.action == ACTION_MANAGE) {
213a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                final Uri rootUri = getIntent().getData();
214d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey                new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
215a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            } else {
216a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                new RestoreStackTask().execute();
217a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
218a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        } else {
219a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            onCurrentDirectoryChanged(ANIM_NONE);
220a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
221b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    }
222a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
223b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    private void buildDefaultState() {
224b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        mState = new State();
22566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
226b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final Intent intent = getIntent();
227b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final String action = intent.getAction();
228b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
229b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_OPEN;
230b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
231b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_CREATE;
232b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
233b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_GET_CONTENT;
234b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        } else if (Intent.ACTION_OPEN_DOCUMENT_TREE.equals(action)) {
235b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey            mState.action = ACTION_OPEN_TREE;
236a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey        } else if (DocumentsContract.ACTION_MANAGE_ROOT.equals(action)) {
237b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_MANAGE;
238b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
239bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
240b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
241b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.allowMultiple = intent.getBooleanExtra(
242b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    Intent.EXTRA_ALLOW_MULTIPLE, false);
243b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
244bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
245b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_MANAGE) {
246b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.acceptMimes = new String[] { "*/*" };
247b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.allowMultiple = true;
248b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
249b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
250b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else {
251b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.acceptMimes = new String[] { intent.getType() };
252b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
253bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
254b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
25596c620595bd0585f934b0971b4552c57845e9a78Jeff Sharkey        mState.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
25696c620595bd0585f934b0971b4552c57845e9a78Jeff Sharkey        mState.showAdvanced = mState.forceAdvanced
257669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                | LocalPreferences.getDisplayAdvancedDevices(this);
258669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey
259669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        if (mState.action == ACTION_MANAGE) {
260669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey            mState.showSize = true;
261669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        } else {
262669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey            mState.showSize = LocalPreferences.getDisplayFileSize(this);
263669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        }
264a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
265a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
266a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
267a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        private Uri mRootUri;
268a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
269a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        public RestoreRootTask(Uri rootUri) {
270a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            mRootUri = rootUri;
271a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
272a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
273a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
274a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected RootInfo doInBackground(Void... params) {
275a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            final String rootId = DocumentsContract.getRootId(mRootUri);
276a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
277a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
278a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
279a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
280a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected void onPostExecute(RootInfo root) {
281a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (isDestroyed()) return;
282a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            mState.restored = true;
283a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
284a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            if (root != null) {
285a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                onRootPicked(root, true);
286a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            } else {
287a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                Log.w(TAG, "Failed to find root: " + mRootUri);
288a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                finish();
289a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            }
290a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
291a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
292a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
293a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private class RestoreStackTask extends AsyncTask<Void, Void, Void> {
294a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        private volatile boolean mRestoredStack;
295deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        private volatile boolean mExternal;
296a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
297a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
298a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected Void doInBackground(Void... params) {
299a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            // Restore last stack for calling package
30015be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey            final String packageName = getCallingPackageMaybeExtra();
301a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            final Cursor cursor = getContentResolver()
302a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                    .query(RecentsProvider.buildResume(packageName), null, null, null, null);
303a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            try {
304a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                if (cursor.moveToFirst()) {
3056a20e574116af1072782c1e87cb03eb33f05ec50Jeff Sharkey                    mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
306b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    final byte[] rawStack = cursor.getBlob(
307d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                            cursor.getColumnIndex(ResumeColumns.STACK));
308b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    DurableUtils.readFromArray(rawStack, mState.stack);
309a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                    mRestoredStack = true;
310a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                }
311b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            } catch (IOException e) {
3126a20e574116af1072782c1e87cb03eb33f05ec50Jeff Sharkey                Log.w(TAG, "Failed to resume: " + e);
313a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            } finally {
314ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                IoUtils.closeQuietly(cursor);
315ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
316ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
317deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (mRestoredStack) {
318deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                // Update the restored stack to ensure we have freshest data
319deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
320deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                try {
321deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mState.stack.updateRoot(matchingRoots);
322deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mState.stack.updateDocuments(getContentResolver());
323deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                } catch (FileNotFoundException e) {
324deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    Log.w(TAG, "Failed to restore stack: " + e);
325deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mState.stack.reset();
326deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mRestoredStack = false;
327deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                }
328dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            }
329a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
330a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            return null;
331a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
332a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
333a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
334a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected void onPostExecute(Void result) {
335a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (isDestroyed()) return;
336a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            mState.restored = true;
337a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
338deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Show drawer when no stack restored, but only when requesting
339deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // non-visual content. However, if we last used an external app,
340deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // drawer is always shown.
341deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
342deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            boolean showDrawer = false;
343deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (!mRestoredStack) {
344deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                showDrawer = true;
345deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            }
346deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
347deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                showDrawer = false;
348deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            }
349deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (mExternal && mState.action == ACTION_GET_CONTENT) {
350deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                showDrawer = true;
351deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            }
352deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
353deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (showDrawer) {
35488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                setRootsDrawerOpen(true);
355ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
356a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
357a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            onCurrentDirectoryChanged(ANIM_NONE);
358dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
359a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey    }
360dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
361bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private DrawerListener mDrawerListener = new DrawerListener() {
362bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
363bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerSlide(View drawerView, float slideOffset) {
364bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
365bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
366bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
367bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
368bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerOpened(View drawerView) {
369bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerOpened(drawerView);
370bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
371bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
372bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
373bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerClosed(View drawerView) {
374bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerClosed(drawerView);
375bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
376bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
377bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
378bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerStateChanged(int newState) {
379bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerStateChanged(newState);
380bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
381bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    };
382bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
383bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    @Override
384bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    protected void onPostCreate(Bundle savedInstanceState) {
385bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        super.onPostCreate(savedInstanceState);
38688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mDrawerToggle != null) {
38788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerToggle.syncState();
38888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
38943aef1643b82e0fe1a524b20c2a533fd620ecfc3Jeff Sharkey        updateActionBar();
39088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    }
39188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
39288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    public void setRootsDrawerOpen(boolean open) {
39388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (!mShowAsDialog) {
39488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            if (open) {
395f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mDrawerLayout.openDrawer(mRootsDrawer);
39688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            } else {
397f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mDrawerLayout.closeDrawer(mRootsDrawer);
39888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
39988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
40088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    }
40188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
40288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private boolean isRootsDrawerOpen() {
40388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mShowAsDialog) {
40488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            return false;
40588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        } else {
406f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            return mDrawerLayout.isDrawerOpen(mRootsDrawer);
40788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
4089e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
4099e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
41054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public void updateActionBar() {
411f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        if (mRootsToolbar != null) {
41221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT
413b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey                    || mState.action == ACTION_OPEN_TREE) {
414f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mRootsToolbar.setTitle(R.string.title_open);
415b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            } else if (mState.action == ACTION_CREATE) {
416f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mRootsToolbar.setTitle(R.string.title_save);
41754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            }
418f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        }
419f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
420f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        final RootInfo root = getCurrentRoot();
421f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        final boolean showRootIcon = mShowAsDialog || (mState.action == ACTION_MANAGE);
422f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        if (showRootIcon) {
423c29dd61cbfc9f073239bdce3f4fe397deae2c623Jeff Sharkey            mToolbar.setNavigationIcon(
424c29dd61cbfc9f073239bdce3f4fe397deae2c623Jeff Sharkey                    root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
425b7b30f691c5b87468ef6ad769487a9f4b315075dJeff Sharkey            mToolbar.setNavigationContentDescription(R.string.drawer_open);
426f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mToolbar.setNavigationOnClickListener(null);
427bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        } else {
428f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
429b7b30f691c5b87468ef6ad769487a9f4b315075dJeff Sharkey            mToolbar.setNavigationContentDescription(R.string.drawer_open);
430f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
431f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                @Override
432f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                public void onClick(View v) {
433f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                    setRootsDrawerOpen(true);
434f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                }
435f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            });
436f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        }
437ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
438f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        if (mSearchExpanded) {
439f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mToolbar.setTitle(null);
440f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mToolbarStack.setVisibility(View.GONE);
441f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            mToolbarStack.setAdapter(null);
442f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        } else {
443ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (mState.stack.size() <= 1) {
444f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbar.setTitle(root.title);
445f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbarStack.setVisibility(View.GONE);
446f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbarStack.setAdapter(null);
447ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            } else {
448f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbar.setTitle(null);
449f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbarStack.setVisibility(View.VISIBLE);
450f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbarStack.setAdapter(mStackAdapter);
451f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
452ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                mIgnoreNextNavigation = true;
453f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
454bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
4559e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
45654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
4579e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
45854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
45954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onCreateOptionsMenu(Menu menu) {
46054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        super.onCreateOptionsMenu(menu);
46154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        getMenuInflater().inflate(R.menu.activity, menu);
462bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
463669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        // Most actions are visible when showing as dialog
46488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mShowAsDialog) {
46588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            for (int i = 0; i < menu.size(); i++) {
466669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                final MenuItem item = menu.getItem(i);
467669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                switch (item.getItemId()) {
468669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                    case R.id.menu_advanced:
469669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                    case R.id.menu_file_size:
470669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                        break;
471669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                    default:
472669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
473669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                }
47488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
47588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
47688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
477bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        final MenuItem searchMenu = menu.findItem(R.id.menu_search);
478bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mSearchView = (SearchView) searchMenu.getActionView();
479bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
480bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            @Override
481bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            public boolean onQueryTextSubmit(String query) {
482f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mSearchExpanded = true;
483b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                mState.currentSearch = query;
48488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mSearchView.clearFocus();
485e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                onCurrentDirectoryChanged(ANIM_NONE);
486bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                return true;
487bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
488bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
489bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            @Override
490bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            public boolean onQueryTextChange(String newText) {
491bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                return false;
492bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
493bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        });
494bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
4954ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
496b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            @Override
4974ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            public boolean onMenuItemActionExpand(MenuItem item) {
498f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mSearchExpanded = true;
499f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                updateActionBar();
5004ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                return true;
5014ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            }
5024ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
5034ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            @Override
5044ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            public boolean onMenuItemActionCollapse(MenuItem item) {
505f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mSearchExpanded = false;
5064ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                if (mIgnoreNextCollapse) {
5074ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                    mIgnoreNextCollapse = false;
5084ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                    return true;
5094ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                }
5104ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
511b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                mState.currentSearch = null;
512e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                onCurrentDirectoryChanged(ANIM_NONE);
5134ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                return true;
514b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
515b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        });
516b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
51788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
51888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            @Override
51988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            public boolean onClose() {
520f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                mSearchExpanded = false;
52188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                if (mIgnoreNextClose) {
52288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    mIgnoreNextClose = false;
52388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    return false;
52488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                }
52588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
52688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mState.currentSearch = null;
527e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                onCurrentDirectoryChanged(ANIM_NONE);
52888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                return false;
52988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
53088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        });
53188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
53254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return true;
53354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
53454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
53554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
53654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onPrepareOptionsMenu(Menu menu) {
53754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        super.onPrepareOptionsMenu(menu);
53854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
5399fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final FragmentManager fm = getFragmentManager();
5403e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey
5413e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey        final RootInfo root = getCurrentRoot();
542ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
543dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
54454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
545bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        final MenuItem search = menu.findItem(R.id.menu_search);
546ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        final MenuItem sort = menu.findItem(R.id.menu_sort);
547ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
548ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        final MenuItem grid = menu.findItem(R.id.menu_grid);
5499fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final MenuItem list = menu.findItem(R.id.menu_list);
550669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        final MenuItem advanced = menu.findItem(R.id.menu_advanced);
551669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
552dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
55388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        sort.setVisible(cwd != null);
55488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        grid.setVisible(mState.derivedMode != MODE_GRID);
55588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        list.setVisible(mState.derivedMode != MODE_LIST);
5569fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
5574ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        if (mState.currentSearch != null) {
5584ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            // Search uses backend ranking; no sorting
5594ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            sort.setVisible(false);
5604ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
5614ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            search.expandActionView();
56288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
56388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.setIconified(false);
56488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.clearFocus();
5654ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            mSearchView.setQuery(mState.currentSearch, false);
5664ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        } else {
56788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mIgnoreNextClose = true;
56888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.setIconified(true);
56988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.clearFocus();
57088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
5714ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            mIgnoreNextCollapse = true;
5724ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            search.collapseActionView();
5734ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        }
5744ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
575ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        // Only sort by size when visible
576ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        sortSize.setVisible(mState.showSize);
577ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
5780166ddf5bbb5d855cb2f5bca4c6a9f0281c14814Jeff Sharkey        boolean searchVisible;
5790166ddf5bbb5d855cb2f5bca4c6a9f0281c14814Jeff Sharkey        boolean fileSizeVisible = mState.action != ACTION_MANAGE;
580b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        if (mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE) {
5819fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            createDir.setVisible(cwd != null && cwd.isCreateSupported());
5829fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            searchVisible = false;
5839fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
5849fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // No display options in recent directories
5859fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (cwd == null) {
5869fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                grid.setVisible(false);
5879fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                list.setVisible(false);
5880166ddf5bbb5d855cb2f5bca4c6a9f0281c14814Jeff Sharkey                fileSizeVisible = false;
5899fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
5909fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
59121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            if (mState.action == ACTION_CREATE) {
59221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
59321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            }
5949fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        } else {
5959fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            createDir.setVisible(false);
5963e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey
5973e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            searchVisible = root != null
5983e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                    && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0);
599dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
600bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
6019fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // TODO: close any search in-progress when hiding
6029fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        search.setVisible(searchVisible);
603b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
604669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
605669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
606669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
607669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey                ? R.string.menu_file_size_hide : R.string.menu_file_size_show);
608669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey
609669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        advanced.setVisible(mState.action != ACTION_MANAGE);
6100166ddf5bbb5d855cb2f5bca4c6a9f0281c14814Jeff Sharkey        fileSize.setVisible(fileSizeVisible);
611a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
61254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return true;
6139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
6149e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
61554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
61654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onOptionsItemSelected(MenuItem item) {
61788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) {
618bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
619bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
620bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
62154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final int id = item.getItemId();
62254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        if (id == android.R.id.home) {
623dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            onBackPressed();
624bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
62554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        } else if (id == R.id.menu_create_dir) {
62620d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey            CreateDirectoryFragment.show(getFragmentManager());
627bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
628bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        } else if (id == R.id.menu_search) {
629bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return false;
630ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        } else if (id == R.id.menu_sort_name) {
631d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserSortOrder(State.SORT_ORDER_DISPLAY_NAME);
632ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return true;
633ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        } else if (id == R.id.menu_sort_date) {
634d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserSortOrder(State.SORT_ORDER_LAST_MODIFIED);
635ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return true;
636ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        } else if (id == R.id.menu_sort_size) {
637d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserSortOrder(State.SORT_ORDER_SIZE);
638ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return true;
639b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else if (id == R.id.menu_grid) {
640d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserMode(State.MODE_GRID);
641b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return true;
642b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else if (id == R.id.menu_list) {
643d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserMode(State.MODE_LIST);
644b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return true;
645669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        } else if (id == R.id.menu_advanced) {
646669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey            setDisplayAdvancedDevices(!LocalPreferences.getDisplayAdvancedDevices(this));
647669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey            return true;
648669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        } else if (id == R.id.menu_file_size) {
649669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey            setDisplayFileSize(!LocalPreferences.getDisplayFileSize(this));
6509fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            return true;
651b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
652b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return super.onOptionsItemSelected(item);
65354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
65454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
65554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
656669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    private void setDisplayAdvancedDevices(boolean display) {
657669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        LocalPreferences.setDisplayAdvancedDevices(this, display);
658669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        mState.showAdvanced = mState.forceAdvanced | display;
659669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
660669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        invalidateOptionsMenu();
661669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    }
662669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey
663669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    private void setDisplayFileSize(boolean display) {
664669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        LocalPreferences.setDisplayFileSize(this, display);
665669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        mState.showSize = display;
666669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        DirectoryFragment.get(getFragmentManager()).onDisplayStateChanged();
667669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey        invalidateOptionsMenu();
668669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey    }
669669f8e7c70c595964a1c9ca154ac123da84d99a1Jeff Sharkey
670d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    /**
671d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     * Update UI to reflect internal state changes not from user.
672d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     */
673d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    public void onStateChanged() {
674d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        invalidateOptionsMenu();
675d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    }
676d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
677d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    /**
678d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     * Set state sort order based on explicit user action.
679d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     */
680d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    private void setUserSortOrder(int sortOrder) {
681fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mState.userSortOrder = sortOrder;
682d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
683d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    }
684d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
685d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    /**
686d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     * Set state mode based on explicit user action.
687d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     */
688d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    private void setUserMode(int mode) {
689fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mState.userMode = mode;
690d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
691d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    }
692d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
69304d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey    public void setPending(boolean pending) {
69404d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        final SaveFragment save = SaveFragment.get(getFragmentManager());
69504d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        if (save != null) {
69604d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey            save.setPending(pending);
69704d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        }
69804d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey    }
69904d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey
700dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    @Override
701dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    public void onBackPressed() {
702fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        if (!mState.stackTouched) {
703fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            super.onBackPressed();
704fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            return;
705fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        }
706fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
707b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final int size = mState.stack.size();
708dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        if (size > 1) {
709b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.stack.pop();
710e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_UP);
71188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        } else if (size == 1 && !isRootsDrawerOpen()) {
712dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // TODO: open root drawer once we can capture back key
713dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            super.onBackPressed();
714dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        } else {
715dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            super.onBackPressed();
71654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
717dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
71854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
719b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    @Override
720b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    protected void onSaveInstanceState(Bundle state) {
721b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        super.onSaveInstanceState(state);
722b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        state.putParcelable(EXTRA_STATE, mState);
723b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    }
724b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
725b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    @Override
726b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    protected void onRestoreInstanceState(Bundle state) {
727b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        super.onRestoreInstanceState(state);
728b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    }
729b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
730ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey    private BaseAdapter mStackAdapter = new BaseAdapter() {
73154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
73254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public int getCount() {
733ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return mState.stack.size();
73454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
7359e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
73654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
737ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        public DocumentInfo getItem(int position) {
738ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return mState.stack.get(mState.stack.size() - position - 1);
73954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
7409e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
74154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
74254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public long getItemId(int position) {
743bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return position;
7449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
7459e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
7469e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
74754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
74854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            if (convertView == null) {
74954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
750f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                        .inflate(R.layout.item_subdir_title, parent, false);
751bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
752bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
753bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
754ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            final DocumentInfo doc = getItem(position);
755bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
756ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (position == 0) {
757ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                final RootInfo root = getCurrentRoot();
758ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                title.setText(root.title);
759bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            } else {
760ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                title.setText(doc.displayName);
761bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
762bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
763bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return convertView;
764bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
765bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
766bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
767bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public View getDropDownView(int position, View convertView, ViewGroup parent) {
768bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            if (convertView == null) {
769bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
770f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                        .inflate(R.layout.item_subdir, parent, false);
7719e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
7729e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
77328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
77428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
775ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            final DocumentInfo doc = getItem(position);
776ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
777ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (position == 0) {
778ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                final RootInfo root = getCurrentRoot();
77928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                title.setText(root.title);
78028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                subdir.setVisibility(View.GONE);
781ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            } else {
78228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                title.setText(doc.displayName);
78328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                subdir.setVisibility(View.VISIBLE);
784ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
7859e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
78654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            return convertView;
7879e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
78854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
7899e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
790f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey    private OnItemSelectedListener mStackListener = new OnItemSelectedListener() {
7919e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
792f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
793ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (mIgnoreNextNavigation) {
794ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                mIgnoreNextNavigation = false;
795f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey                return;
796ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
797ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
798f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            while (mState.stack.size() > position + 1) {
799fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                mState.stackTouched = true;
800ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                mState.stack.pop();
801ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
802e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_UP);
803f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        }
804f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey
805f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        @Override
806f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey        public void onNothingSelected(AdapterView<?> parent) {
807f52773fd62fc2fec40c2e17230b644dfbee6cf2dJeff Sharkey            // Ignored
80854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
80954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
81054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
811ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public RootInfo getCurrentRoot() {
812d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        if (mState.stack.root != null) {
813d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            return mState.stack.root;
814b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
8154eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            return mRoots.getRecentsRoot();
816b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        }
817dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
818dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
819ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public DocumentInfo getCurrentDirectory() {
820b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        return mState.stack.peek();
821dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
822dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
82315be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey    private String getCallingPackageMaybeExtra() {
82415be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey        final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME);
82515be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey        return (extra != null) ? extra : getCallingPackage();
82615be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey    }
82715be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey
828d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey    public Executor getCurrentExecutor() {
829d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
830d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        if (cwd != null && cwd.authority != null) {
831d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            return ProviderExecutor.forAuthority(cwd.authority);
832d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        } else {
833d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            return AsyncTask.THREAD_POOL_EXECUTOR;
834d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        }
835d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey    }
836d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey
837b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    public State getDisplayState() {
838b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        return mState;
8391482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    }
8401482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
841e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey    private void onCurrentDirectoryChanged(int anim) {
842dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final FragmentManager fm = getFragmentManager();
843d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        final RootInfo root = getCurrentRoot();
844ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
8459fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
846e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
847e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
848b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (cwd == null) {
849b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            // No directory means recents
850b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey            if (mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE) {
851b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                RecentsCreateFragment.show(fm);
852b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
853e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                DirectoryFragment.showRecentsOpen(fm, anim);
85488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
855deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                // Start recents in grid when requesting visual things
856deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                final boolean visualMimes = MimePredicate.mimeMatches(
857deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                        MimePredicate.VISUAL_MIMES, mState.acceptMimes);
858deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                mState.userMode = visualMimes ? MODE_GRID : MODE_LIST;
85988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mState.derivedMode = mState.userMode;
860b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
861b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
862b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            if (mState.currentSearch != null) {
863b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // Ongoing search
864e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
865b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
866b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // Normal boring directory
867e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                DirectoryFragment.showNormal(fm, root, cwd, anim);
868b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
86954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
870b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
8719fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // Forget any replacement target
872b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_CREATE) {
8739fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            final SaveFragment save = SaveFragment.get(fm);
8749fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (save != null) {
8759fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                save.setReplaceTarget(null);
8769fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
8779fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        }
8789fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
879b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        if (mState.action == ACTION_OPEN_TREE) {
88021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            final PickFragment pick = PickFragment.get(fm);
88121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            if (pick != null) {
88221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                final CharSequence displayName = (mState.stack.size() <= 1) ? root.title
88321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                        : cwd.displayName;
88421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                pick.setPickTarget(cwd, displayName);
88521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            }
88621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        }
88721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey
88828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        final RootsFragment roots = RootsFragment.get(fm);
88928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        if (roots != null) {
89028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            roots.onCurrentRootChanged();
89128c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        }
89228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
893dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        updateActionBar();
89454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        invalidateOptionsMenu();
895dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        dumpStack();
89654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
89754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
898b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public void onStackPicked(DocumentStack stack) {
899deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        try {
900deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Update the restored stack to ensure we have freshest data
901deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            stack.updateDocuments(getContentResolver());
902deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
903deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            mState.stack = stack;
904deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            mState.stackTouched = true;
905deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            onCurrentDirectoryChanged(ANIM_SIDE);
906deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
907deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        } catch (FileNotFoundException e) {
908deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            Log.w(TAG, "Failed to restore stack: " + e);
909deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        }
910b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
911b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
912ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onRootPicked(RootInfo root, boolean closeDrawer) {
913ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        // Clear entire backstack and start in new root
914d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        mState.stack.root = root;
915b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        mState.stack.clear();
916fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mState.stackTouched = true;
917b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
918aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (!mRoots.isRecentsRoot(root)) {
919d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            new PickRootTask(root).executeOnExecutor(getCurrentExecutor());
920b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
921e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_SIDE);
922b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        }
92366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
92466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        if (closeDrawer) {
92588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            setRootsDrawerOpen(false);
92666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
927ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    }
928ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
9296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class PickRootTask extends AsyncTask<Void, Void, DocumentInfo> {
9306efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private RootInfo mRoot;
9316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
9326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public PickRootTask(RootInfo root) {
9336efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mRoot = root;
9346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
9356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
9366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
9376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected DocumentInfo doInBackground(Void... params) {
9386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            try {
9396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                final Uri uri = DocumentsContract.buildDocumentUri(
9406efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        mRoot.authority, mRoot.documentId);
9416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return DocumentInfo.fromUri(getContentResolver(), uri);
9426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } catch (FileNotFoundException e) {
9437aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                Log.w(TAG, "Failed to find root", e);
9446efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return null;
9456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
9466efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
9476efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
9486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
9496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(DocumentInfo result) {
9506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (result != null) {
9516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                mState.stack.push(result);
9526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                mState.stackTouched = true;
9536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                onCurrentDirectoryChanged(ANIM_SIDE);
9546efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
9556efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
9566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
9576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
95854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    public void onAppPicked(ResolveInfo info) {
95954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        final Intent intent = new Intent(getIntent());
9605545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
96154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        intent.setComponent(new ComponentName(
96254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
9635545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        startActivityForResult(intent, CODE_FORWARD);
9645545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    }
9655545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
9665545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    @Override
9675545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
9685545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        Log.d(TAG, "onActivityResult() code=" + resultCode);
9695545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
9705545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        // Only relay back results when not canceled; otherwise stick around to
9715545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        // let the user pick another app/backend.
9725545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        if (requestCode == CODE_FORWARD && resultCode != RESULT_CANCELED) {
973deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
974deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Remember that we last picked via external app
97515be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey            final String packageName = getCallingPackageMaybeExtra();
976deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            final ContentValues values = new ContentValues();
977deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            values.put(ResumeColumns.EXTERNAL, 1);
978deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            getContentResolver().insert(RecentsProvider.buildResume(packageName), values);
979deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
980deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Pass back result to original caller
9815545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey            setResult(resultCode, data);
9825545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey            finish();
9835545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        } else {
9845545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey            super.onActivityResult(requestCode, resultCode, data);
9855545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        }
98654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    }
98754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
988ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onDocumentPicked(DocumentInfo doc) {
98954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final FragmentManager fm = getFragmentManager();
990b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (doc.isDirectory()) {
991b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.stack.push(doc);
992fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            mState.stackTouched = true;
993e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_DOWN);
994b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
99554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            // Explicit file picked, return
996d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor());
997b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_CREATE) {
9989fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // Replace selected file
9999fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            SaveFragment.get(fm).setReplaceTarget(doc);
1000b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_MANAGE) {
1001a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey            // First try managing the document; we expect manager to filter
1002a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey            // based on authority, so we don't grant.
1003a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey            final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
1004d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            manage.setData(doc.derivedUri);
1005a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey
10064eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            try {
1007a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                startActivity(manage);
10084eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            } catch (ActivityNotFoundException ex) {
1009a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                // Fall back to viewing
1010a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                final Intent view = new Intent(Intent.ACTION_VIEW);
1011a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
1012d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                view.setData(doc.derivedUri);
1013a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey
1014a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                try {
1015a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                    startActivity(view);
1016a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                } catch (ActivityNotFoundException ex2) {
1017a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                    Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
1018a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                }
10194eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            }
102054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
102154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
102254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1023ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onDocumentsPicked(List<DocumentInfo> docs) {
1024b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
10254eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            final int size = docs.size();
10264eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            final Uri[] uris = new Uri[size];
10274eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            for (int i = 0; i < size; i++) {
1028d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                uris[i] = docs.get(i).derivedUri;
10294eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            }
1030d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            new ExistingFinishTask(uris).executeOnExecutor(getCurrentExecutor());
1031be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
1032be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    }
1033be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
1034ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onSaveRequested(DocumentInfo replaceTarget) {
1035d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getCurrentExecutor());
10369fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
103792d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey
10389fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public void onSaveRequested(String mimeType, String displayName) {
1039d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
104054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
104154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
104221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey    public void onPickRequested(DocumentInfo pickTarget) {
1043b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        final Uri viaUri = DocumentsContract.buildTreeDocumentUri(pickTarget.authority,
104421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                pickTarget.documentId);
104521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        new PickFinishTask(viaUri).executeOnExecutor(getCurrentExecutor());
104621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey    }
104721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey
10486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private void saveStackBlocking() {
1049dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final ContentResolver resolver = getContentResolver();
1050dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final ContentValues values = new ContentValues();
1051dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
1052b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
1053b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        if (mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE) {
1054dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // Remember stack for last create
1055dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            values.clear();
10566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            values.put(RecentColumns.KEY, mState.stack.buildKey());
1057d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            values.put(RecentColumns.STACK, rawStack);
1058d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            resolver.insert(RecentsProvider.buildRecent(), values);
1059dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
1060dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
1061dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        // Remember location for next app launch
106215be83612c34b65404f15d0feafdb4a329467769Jeff Sharkey        final String packageName = getCallingPackageMaybeExtra();
1063dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        values.clear();
1064d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        values.put(ResumeColumns.STACK, rawStack);
1065deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        values.put(ResumeColumns.EXTERNAL, 0);
1066dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        resolver.insert(RecentsProvider.buildResume(packageName), values);
10676efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
10686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private void onFinished(Uri... uris) {
10706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        Log.d(TAG, "onFinished() " + Arrays.toString(uris));
1071dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
107254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final Intent intent = new Intent();
1073be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        if (uris.length == 1) {
1074be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            intent.setData(uris[0]);
1075be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else if (uris.length > 1) {
1076ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final ClipData clipData = new ClipData(
1077b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
1078be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            for (int i = 1; i < uris.length; i++) {
1079be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                clipData.addItem(new ClipData.Item(uris[i]));
1080be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            }
1081be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            intent.setClipData(clipData);
1082be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
108354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1084b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
108554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
1086b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        } else if (mState.action == ACTION_OPEN_TREE) {
108721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
108821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
108921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
109021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
109154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        } else {
109254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
109354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
1094e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
109554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
109654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
109754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        setResult(Activity.RESULT_OK, intent);
109854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        finish();
109954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
110054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
11016efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class CreateFinishTask extends AsyncTask<Void, Void, Uri> {
11026efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final String mMimeType;
11036efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final String mDisplayName;
11046efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11056efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public CreateFinishTask(String mimeType, String displayName) {
11066efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mMimeType = mimeType;
11076efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mDisplayName = displayName;
11086efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
11096efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11106efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
111104d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        protected void onPreExecute() {
111204d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey            setPending(true);
111304d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        }
111404d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey
111504d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        @Override
11166efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected Uri doInBackground(Void... params) {
11177aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            final ContentResolver resolver = getContentResolver();
11186efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final DocumentInfo cwd = getCurrentDirectory();
11197aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
11207aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            ContentProviderClient client = null;
11217aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            Uri childUri = null;
11227aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            try {
11237aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                client = DocumentsApplication.acquireUnstableProviderOrThrow(
11247aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                        resolver, cwd.derivedUri.getAuthority());
11257aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                childUri = DocumentsContract.createDocument(
11267aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                        client, cwd.derivedUri, mMimeType, mDisplayName);
11277aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            } catch (Exception e) {
11287aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                Log.w(TAG, "Failed to create document", e);
11297aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            } finally {
11307aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                ContentProviderClient.releaseQuietly(client);
11317aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            }
11327aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
11336efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (childUri != null) {
11346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                saveStackBlocking();
11356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
11367aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
11376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return childUri;
11386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
11396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11406efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
11416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(Uri result) {
11426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (result != null) {
11436efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                onFinished(result);
11446efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else {
11456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                Toast.makeText(DocumentsActivity.this, R.string.save_error, Toast.LENGTH_SHORT)
11466efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        .show();
11476efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
114804d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey
114904d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey            setPending(false);
11506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
11516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
11526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class ExistingFinishTask extends AsyncTask<Void, Void, Void> {
11546efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final Uri[] mUris;
11556efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public ExistingFinishTask(Uri... uris) {
11576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mUris = uris;
11586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
11596efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11606efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
11616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected Void doInBackground(Void... params) {
11626efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            saveStackBlocking();
11636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return null;
11646efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
11656efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
11666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
11676efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(Void result) {
11686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            onFinished(mUris);
11696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
11706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
11716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
117221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey    private class PickFinishTask extends AsyncTask<Void, Void, Void> {
117321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        private final Uri mUri;
117421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey
117521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        public PickFinishTask(Uri uri) {
117621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            mUri = uri;
117721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        }
117821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey
117921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        @Override
118021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        protected Void doInBackground(Void... params) {
118121de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            saveStackBlocking();
118221de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            return null;
118321de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        }
118421de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey
118521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        @Override
118621de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        protected void onPostExecute(Void result) {
118721de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey            onFinished(mUri);
118821de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        }
118921de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey    }
119021de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey
1191b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    public static class State implements android.os.Parcelable {
11924eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public int action;
1193ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public String[] acceptMimes;
1194fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
1195fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Explicit user choice */
1196fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int userMode = MODE_UNKNOWN;
1197fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Derived after loader */
1198fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int derivedMode = MODE_LIST;
1199fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
1200fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Explicit user choice */
1201fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int userSortOrder = SORT_ORDER_UNKNOWN;
1202fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Derived after loader */
1203fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
1204fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
1205ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public boolean allowMultiple = false;
1206b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        public boolean showSize = false;
120754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        public boolean localOnly = false;
120896c620595bd0585f934b0971b4552c57845e9a78Jeff Sharkey        public boolean forceAdvanced = false;
1209348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey        public boolean showAdvanced = false;
1210fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public boolean stackTouched = false;
1211a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        public boolean restored = false;
12121482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1213b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        /** Current user navigation stack; empty implies recents. */
1214b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public DocumentStack stack = new DocumentStack();
1215b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        /** Currently active search, overriding any stack. */
1216b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public String currentSearch;
1217b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1218e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        /** Instance state for every shown directory */
1219e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
1220e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
12214eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_OPEN = 1;
12224eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_CREATE = 2;
12234eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_GET_CONTENT = 3;
1224b9fbb7290b02de1ce621deaa2d28a5e42f2e0937Jeff Sharkey        public static final int ACTION_OPEN_TREE = 4;
122521de56a94668e0fda1b8bb4ee4f99a09b40d28fdJeff Sharkey        public static final int ACTION_MANAGE = 5;
12264eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
1227d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int MODE_UNKNOWN = 0;
1228d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int MODE_LIST = 1;
1229d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int MODE_GRID = 2;
12301482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1231d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_UNKNOWN = 0;
1232d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_DISPLAY_NAME = 1;
1233d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_LAST_MODIFIED = 2;
1234d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_SIZE = 3;
1235b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1236b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        @Override
1237b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public int describeContents() {
1238b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            return 0;
1239b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
1240b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1241b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        @Override
1242b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public void writeToParcel(Parcel out, int flags) {
1243b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(action);
1244fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            out.writeInt(userMode);
1245b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeStringArray(acceptMimes);
1246fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            out.writeInt(userSortOrder);
1247b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(allowMultiple ? 1 : 0);
1248b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(showSize ? 1 : 0);
1249b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(localOnly ? 1 : 0);
125096c620595bd0585f934b0971b4552c57845e9a78Jeff Sharkey            out.writeInt(forceAdvanced ? 1 : 0);
1251348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey            out.writeInt(showAdvanced ? 1 : 0);
1252fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            out.writeInt(stackTouched ? 1 : 0);
1253a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            out.writeInt(restored ? 1 : 0);
1254b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            DurableUtils.writeToParcel(out, stack);
1255b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeString(currentSearch);
1256e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            out.writeMap(dirState);
1257b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
1258b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1259b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public static final Creator<State> CREATOR = new Creator<State>() {
1260b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            @Override
1261b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            public State createFromParcel(Parcel in) {
1262b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                final State state = new State();
1263b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.action = in.readInt();
1264fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                state.userMode = in.readInt();
1265b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.acceptMimes = in.readStringArray();
1266fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                state.userSortOrder = in.readInt();
1267b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.allowMultiple = in.readInt() != 0;
1268b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.showSize = in.readInt() != 0;
1269b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.localOnly = in.readInt() != 0;
127096c620595bd0585f934b0971b4552c57845e9a78Jeff Sharkey                state.forceAdvanced = in.readInt() != 0;
1271348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey                state.showAdvanced = in.readInt() != 0;
1272fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                state.stackTouched = in.readInt() != 0;
1273a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                state.restored = in.readInt() != 0;
1274b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                DurableUtils.readFromParcel(in, state.stack);
1275b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.currentSearch = in.readString();
1276e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                in.readMap(state.dirState, null);
1277b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                return state;
1278b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            }
1279b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1280b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            @Override
1281b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            public State[] newArray(int size) {
1282b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                return new State[size];
1283b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            }
1284b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        };
12851482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    }
12861482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1287dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    private void dumpStack() {
1288d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        Log.d(TAG, "Current stack: ");
1289d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        Log.d(TAG, " * " + mState.stack.root);
1290b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        for (DocumentInfo doc : mState.stack) {
1291d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            Log.d(TAG, " +-- " + doc);
1292dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
1293dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
12949fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
12959fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public static DocumentsActivity get(Fragment fragment) {
12969fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        return (DocumentsActivity) fragment.getActivity();
12979fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
12989e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey}
1299