DocumentsActivity.java revision 7aa7601c09ab5d87cc15a0ed9a8f511d494a4cbc
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;
27b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
28b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
294eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
3054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.app.ActionBar;
3154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.app.ActionBar.OnNavigationListener;
329e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.Activity;
339fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.app.Fragment;
349e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentManager;
354eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.ActivityNotFoundException;
36be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.content.ClipData;
3754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkeyimport android.content.ComponentName;
387aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.content.ContentProviderClient;
39be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.content.ContentResolver;
4020d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkeyimport android.content.ContentValues;
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;
46bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.graphics.drawable.ColorDrawable;
4788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.graphics.drawable.Drawable;
4888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.graphics.drawable.InsetDrawable;
499e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.net.Uri;
50a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport android.os.AsyncTask;
519e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.os.Bundle;
52b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport android.os.Parcel;
53e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport android.os.Parcelable;
54a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkeyimport android.provider.DocumentsContract;
553e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkeyimport android.provider.DocumentsContract.Root;
56bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.app.ActionBarDrawerToggle;
57bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.view.GravityCompat;
58bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.widget.DrawerLayout;
59bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.widget.DrawerLayout.DrawerListener;
609e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.util.Log;
61e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport android.util.SparseArray;
629e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.LayoutInflater;
6354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.Menu;
6454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuItem;
654ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.view.MenuItem.OnActionExpandListener;
6688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.view.MotionEvent;
679e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.View;
6888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.view.View.OnTouchListener;
699e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.ViewGroup;
7088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkeyimport android.view.WindowManager;
7154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.BaseAdapter;
7228c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkeyimport android.widget.ImageView;
73bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.widget.SearchView;
74bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.widget.SearchView.OnQueryTextListener;
7554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.TextView;
767e258b31e70464bb6d80b8b42f0cef8e4417bd6aJeff Sharkeyimport android.widget.Toast;
779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
78d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.RecentsProvider.RecentColumns;
79d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.RecentsProvider.ResumeColumns;
80ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
81b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport com.android.documentsui.model.DocumentStack;
82b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport com.android.documentsui.model.DurableUtils;
83ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.RootInfo;
84e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport com.google.common.collect.Maps;
8520d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey
86ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkeyimport libcore.io.IoUtils;
87ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
880c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkeyimport java.io.FileNotFoundException;
89b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport java.io.IOException;
90be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.Arrays;
91a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkeyimport java.util.Collection;
925545f56f7561810187545a1817b6001dd1f9931bJeff Sharkeyimport java.util.HashMap;
93be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.List;
94be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
959e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeypublic class DocumentsActivity extends Activity {
96ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static final String TAG = "Documents";
979e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
9888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private static final String EXTRA_STATE = "state";
9988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
1005545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    private static final int CODE_FORWARD = 42;
1015545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
10288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private boolean mShowAsDialog;
10388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
104bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private SearchView mSearchView;
105bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
106bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private DrawerLayout mDrawerLayout;
107bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private ActionBarDrawerToggle mDrawerToggle;
10888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private View mRootsContainer;
1091482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
110e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey    private DirectoryContainerView mDirectoryContainer;
111e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
112ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey    private boolean mIgnoreNextNavigation;
11388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private boolean mIgnoreNextClose;
1144ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey    private boolean mIgnoreNextCollapse;
115ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
1164eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey    private RootsCache mRoots;
117b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    private State mState;
11854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1199e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    @Override
1209e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    public void onCreate(Bundle icicle) {
1219e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        super.onCreate(icicle);
1229e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1234eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        mRoots = DocumentsApplication.getRootsCache(this);
1244eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
125b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        setResult(Activity.RESULT_CANCELED);
126b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        setContentView(R.layout.activity);
12754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
12888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        final Resources res = getResources();
12988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        mShowAsDialog = res.getBoolean(R.bool.show_as_dialog);
13088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
13188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mShowAsDialog) {
13288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            // backgroundDimAmount from theme isn't applied; do it manually
13388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final WindowManager.LayoutParams a = getWindow().getAttributes();
13488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            a.dimAmount = 0.6f;
13588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindow().setAttributes(a);
13688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
13788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
13888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindow().setFlags(~0, WindowManager.LayoutParams.FLAG_DIM_BEHIND);
13988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
14088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            // Inset ourselves to look like a dialog
14188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final Point size = new Point();
14288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindowManager().getDefaultDisplay().getSize(size);
14388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
14488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final int width = (int) res.getFraction(R.dimen.dialog_width, size.x, size.x);
14588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final int height = (int) res.getFraction(R.dimen.dialog_height, size.y, size.y);
14688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final int insetX = (size.x - width) / 2;
14788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final int insetY = (size.y - height) / 2;
14888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
14988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final Drawable before = getWindow().getDecorView().getBackground();
15088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            final Drawable after = new InsetDrawable(before, insetX, insetY, insetX, insetY);
15188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindow().getDecorView().setBackground(after);
15288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
15388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            // Dismiss when touch down in the dimmed inset area
15488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            getWindow().getDecorView().setOnTouchListener(new OnTouchListener() {
15588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                @Override
15688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                public boolean onTouch(View v, MotionEvent event) {
15788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
15888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                        final float x = event.getX();
15988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                        final float y = event.getY();
16088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                        if (x < insetX || x > v.getWidth() - insetX || y < insetY
16188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                                || y > v.getHeight() - insetY) {
16288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                            finish();
16388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                            return true;
16488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                        }
16588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    }
16688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    return false;
16788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                }
16888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            });
16988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
17088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        } else {
17188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            // Non-dialog means we have a drawer
17288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
1734eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
17488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
1751feeddf518d31a7ff5d28000a631857442cd7161Jeff Sharkey                    R.drawable.ic_drawer_glyph, R.string.drawer_open, R.string.drawer_close);
176be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
17788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerLayout.setDrawerListener(mDrawerListener);
17888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerLayout.setDrawerShadow(R.drawable.ic_drawer_shadow, GravityCompat.START);
179b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
18088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mRootsContainer = findViewById(R.id.container_roots);
18188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
182b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
183e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
184e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
185b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (icicle != null) {
186b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState = icicle.getParcelable(EXTRA_STATE);
187be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else {
188b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            buildDefaultState();
18954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
19054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
19188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        // Hide roots when we're managing a specific root
192b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_MANAGE) {
19388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            if (mShowAsDialog) {
19488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                findViewById(R.id.dialog_roots).setVisibility(View.GONE);
19588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            } else {
19688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
19788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
198b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
19954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
200b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_CREATE) {
20154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final String mimeType = getIntent().getType();
20254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
20354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            SaveFragment.show(getFragmentManager(), mimeType, title);
20454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
205bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
206b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
20754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            final Intent moreApps = new Intent(getIntent());
20854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            moreApps.setComponent(null);
20954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            moreApps.setPackage(null);
21054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            RootsFragment.show(getFragmentManager(), moreApps);
211b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE) {
21254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            RootsFragment.show(getFragmentManager(), null);
21354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
21466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
215a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        if (!mState.restored) {
216a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (mState.action == ACTION_MANAGE) {
217a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                final Uri rootUri = getIntent().getData();
218a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                new RestoreRootTask(rootUri).execute();
219a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            } else {
220a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                new RestoreStackTask().execute();
221a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            }
222a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        } else {
223a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            onCurrentDirectoryChanged(ANIM_NONE);
224a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
225b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    }
226a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
227b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    private void buildDefaultState() {
228b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        mState = new State();
22966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
230b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final Intent intent = getIntent();
231b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final String action = intent.getAction();
232b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
233b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_OPEN;
234b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
235b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_CREATE;
236b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
237b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_GET_CONTENT;
238a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey        } else if (DocumentsContract.ACTION_MANAGE_ROOT.equals(action)) {
239b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.action = ACTION_MANAGE;
240b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
241bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
242b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
243b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.allowMultiple = intent.getBooleanExtra(
244b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    Intent.EXTRA_ALLOW_MULTIPLE, false);
245b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
246bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
247b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_MANAGE) {
248b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.acceptMimes = new String[] { "*/*" };
249b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.allowMultiple = true;
250b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
251b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
252b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else {
253b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.acceptMimes = new String[] { intent.getType() };
254b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
255bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
256b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
257348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey        mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
258a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
259a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
260a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
261a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        private Uri mRootUri;
262a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
263a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        public RestoreRootTask(Uri rootUri) {
264a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            mRootUri = rootUri;
265a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
266a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
267a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
268a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected RootInfo doInBackground(Void... params) {
269a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            final String rootId = DocumentsContract.getRootId(mRootUri);
270a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
271a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
272a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
273a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
274a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected void onPostExecute(RootInfo root) {
275a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (isDestroyed()) return;
276a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            mState.restored = true;
277a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
278a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            if (root != null) {
279a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                onRootPicked(root, true);
280a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            } else {
281a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                Log.w(TAG, "Failed to find root: " + mRootUri);
282a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                finish();
283a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            }
284a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
285a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    }
286a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
287a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey    private class RestoreStackTask extends AsyncTask<Void, Void, Void> {
288a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        private volatile boolean mRestoredStack;
289deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        private volatile boolean mExternal;
290a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
291a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
292a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected Void doInBackground(Void... params) {
293a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            // Restore last stack for calling package
294a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            final String packageName = getCallingPackage();
295a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            final Cursor cursor = getContentResolver()
296a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                    .query(RecentsProvider.buildResume(packageName), null, null, null, null);
297a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            try {
298a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                if (cursor.moveToFirst()) {
2996a20e574116af1072782c1e87cb03eb33f05ec50Jeff Sharkey                    mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
300b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    final byte[] rawStack = cursor.getBlob(
301d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                            cursor.getColumnIndex(ResumeColumns.STACK));
302b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    DurableUtils.readFromArray(rawStack, mState.stack);
303a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                    mRestoredStack = true;
304a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                }
305b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            } catch (IOException e) {
3066a20e574116af1072782c1e87cb03eb33f05ec50Jeff Sharkey                Log.w(TAG, "Failed to resume: " + e);
307a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            } finally {
308ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                IoUtils.closeQuietly(cursor);
309ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
310ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
311deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (mRestoredStack) {
312deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                // Update the restored stack to ensure we have freshest data
313deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
314deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                try {
315deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mState.stack.updateRoot(matchingRoots);
316deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mState.stack.updateDocuments(getContentResolver());
317deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                } catch (FileNotFoundException e) {
318deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    Log.w(TAG, "Failed to restore stack: " + e);
319deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mState.stack.reset();
320deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                    mRestoredStack = false;
321deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                }
322dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            }
323a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
324a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            return null;
325a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        }
326a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
327a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        @Override
328a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        protected void onPostExecute(Void result) {
329a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            if (isDestroyed()) return;
330a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            mState.restored = true;
331a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
332deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Show drawer when no stack restored, but only when requesting
333deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // non-visual content. However, if we last used an external app,
334deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // drawer is always shown.
335deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
336deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            boolean showDrawer = false;
337deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (!mRestoredStack) {
338deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                showDrawer = true;
339deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            }
340deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
341deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                showDrawer = false;
342deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            }
343deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (mExternal && mState.action == ACTION_GET_CONTENT) {
344deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                showDrawer = true;
345deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            }
346deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
347deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            if (showDrawer) {
34888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                setRootsDrawerOpen(true);
349ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
350a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey
351a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            onCurrentDirectoryChanged(ANIM_NONE);
352dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
353a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey    }
354dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
355a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey    @Override
35688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    public void onResume() {
35788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        super.onResume();
358a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
359b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_MANAGE) {
360b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.showSize = true;
361a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey        } else {
362b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.showSize = SettingsActivity.getDisplayFileSize(this);
363deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            invalidateOptionsMenu();
364a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey        }
365bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    }
366bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
367bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private DrawerListener mDrawerListener = new DrawerListener() {
368bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
369bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerSlide(View drawerView, float slideOffset) {
370bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
371bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
372bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
373bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
374bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerOpened(View drawerView) {
375bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerOpened(drawerView);
376bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            updateActionBar();
3774ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            invalidateOptionsMenu();
378bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
379bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
380bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
381bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerClosed(View drawerView) {
382bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerClosed(drawerView);
383bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            updateActionBar();
3844ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            invalidateOptionsMenu();
385bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
386bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
387bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
388bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerStateChanged(int newState) {
389bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerStateChanged(newState);
390bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
391bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    };
392bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
393bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    @Override
394bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    protected void onPostCreate(Bundle savedInstanceState) {
395bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        super.onPostCreate(savedInstanceState);
39688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mDrawerToggle != null) {
39788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerToggle.syncState();
39888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
39988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    }
40088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
40188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    public void setRootsDrawerOpen(boolean open) {
40288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (!mShowAsDialog) {
40388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            if (open) {
40488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mDrawerLayout.openDrawer(mRootsContainer);
40588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            } else {
40688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mDrawerLayout.closeDrawer(mRootsContainer);
40788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
40888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
40988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    }
41088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
41188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey    private boolean isRootsDrawerOpen() {
41288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mShowAsDialog) {
41388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            return false;
41488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        } else {
41588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            return mDrawerLayout.isDrawerOpen(mRootsContainer);
41688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
4179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
4189e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
41954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public void updateActionBar() {
42054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final ActionBar actionBar = getActionBar();
4219e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
422bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        actionBar.setDisplayShowHomeEnabled(true);
4239e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
42488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        final boolean showIndicator = !mShowAsDialog && (mState.action != ACTION_MANAGE);
42588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        actionBar.setDisplayHomeAsUpEnabled(showIndicator);
42688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mDrawerToggle != null) {
42788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mDrawerToggle.setDrawerIndicatorEnabled(showIndicator);
428ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        }
429ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
43088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (isRootsDrawerOpen()) {
43154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
432bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            actionBar.setIcon(new ColorDrawable());
43354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
434b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
43554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                actionBar.setTitle(R.string.title_open);
436b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            } else if (mState.action == ACTION_CREATE) {
43754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                actionBar.setTitle(R.string.title_save);
43854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            }
439bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        } else {
440ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey            final RootInfo root = getCurrentRoot();
441aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey            actionBar.setIcon(root != null ? root.loadIcon(this) : null);
442ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
443ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (mState.stack.size() <= 1) {
444ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
445ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setTitle(root.title);
446ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            } else {
447ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                mIgnoreNextNavigation = true;
448ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
449ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setTitle(null);
450ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                actionBar.setListNavigationCallbacks(mStackAdapter, mStackListener);
451ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                actionBar.setSelectedNavigationItem(mStackAdapter.getCount() - 1);
452bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
4539e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
45454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
4559e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
45654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
45754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onCreateOptionsMenu(Menu menu) {
45854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        super.onCreateOptionsMenu(menu);
45954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        getMenuInflater().inflate(R.menu.activity, menu);
460bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
46188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        // Actions are always visible when showing as dialog
46288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mShowAsDialog) {
46388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            for (int i = 0; i < menu.size(); i++) {
46488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                menu.getItem(i).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
46588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
46688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        }
46788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
468bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        final MenuItem searchMenu = menu.findItem(R.id.menu_search);
469bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mSearchView = (SearchView) searchMenu.getActionView();
470bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
471bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            @Override
472bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            public boolean onQueryTextSubmit(String query) {
473b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                mState.currentSearch = query;
47488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mSearchView.clearFocus();
475e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                onCurrentDirectoryChanged(ANIM_NONE);
476bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                return true;
477bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
478bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
479bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            @Override
480bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            public boolean onQueryTextChange(String newText) {
481bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                return false;
482bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
483bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        });
484bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
4854ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
486b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            @Override
4874ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            public boolean onMenuItemActionExpand(MenuItem item) {
4884ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                return true;
4894ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            }
4904ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
4914ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            @Override
4924ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            public boolean onMenuItemActionCollapse(MenuItem item) {
4934ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                if (mIgnoreNextCollapse) {
4944ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                    mIgnoreNextCollapse = false;
4954ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                    return true;
4964ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                }
4974ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
498b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                mState.currentSearch = null;
499e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                onCurrentDirectoryChanged(ANIM_NONE);
5004ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                return true;
501b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
502b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        });
503b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
50488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
50588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            @Override
50688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            public boolean onClose() {
50788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                if (mIgnoreNextClose) {
50888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    mIgnoreNextClose = false;
50988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                    return false;
51088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                }
51188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
51288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mState.currentSearch = null;
513e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                onCurrentDirectoryChanged(ANIM_NONE);
51488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                return false;
51588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            }
51688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        });
51788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
51854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return true;
51954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
52054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
52154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
52254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onPrepareOptionsMenu(Menu menu) {
52354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        super.onPrepareOptionsMenu(menu);
52454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
5259fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final FragmentManager fm = getFragmentManager();
5263e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey
5273e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey        final RootInfo root = getCurrentRoot();
528ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
529dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
53054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
531bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        final MenuItem search = menu.findItem(R.id.menu_search);
532ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        final MenuItem sort = menu.findItem(R.id.menu_sort);
533ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
534ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        final MenuItem grid = menu.findItem(R.id.menu_grid);
5359fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final MenuItem list = menu.findItem(R.id.menu_list);
536a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey        final MenuItem settings = menu.findItem(R.id.menu_settings);
537dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
5384ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        // Open drawer means we hide most actions
53988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (isRootsDrawerOpen()) {
5404ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            createDir.setVisible(false);
5414ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            search.setVisible(false);
5424ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            sort.setVisible(false);
5434ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            grid.setVisible(false);
5444ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            list.setVisible(false);
5454ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            mIgnoreNextCollapse = true;
5464ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            search.collapseActionView();
5474ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            return true;
5484ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        }
5494ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
55088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        sort.setVisible(cwd != null);
55188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        grid.setVisible(mState.derivedMode != MODE_GRID);
55288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        list.setVisible(mState.derivedMode != MODE_LIST);
5539fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
5544ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        if (mState.currentSearch != null) {
5554ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            // Search uses backend ranking; no sorting
5564ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            sort.setVisible(false);
5574ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
5584ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            search.expandActionView();
55988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
56088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.setIconified(false);
56188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.clearFocus();
5624ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            mSearchView.setQuery(mState.currentSearch, false);
5634ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        } else {
56488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mIgnoreNextClose = true;
56588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.setIconified(true);
56688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            mSearchView.clearFocus();
56788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
5684ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            mIgnoreNextCollapse = true;
5694ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            search.collapseActionView();
5704ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        }
5714ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
572ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        // Only sort by size when visible
573ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        sortSize.setVisible(mState.showSize);
574ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
5759fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final boolean searchVisible;
576b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_CREATE) {
5779fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            createDir.setVisible(cwd != null && cwd.isCreateSupported());
5789fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            searchVisible = false;
5799fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
5809fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // No display options in recent directories
5819fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (cwd == null) {
5829fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                grid.setVisible(false);
5839fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                list.setVisible(false);
5849fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
5859fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
586dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
5879fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        } else {
5889fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            createDir.setVisible(false);
5893e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey
5903e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            searchVisible = root != null
5913e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                    && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0);
592dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
593bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
5949fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // TODO: close any search in-progress when hiding
5959fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        search.setVisible(searchVisible);
596b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
597b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        settings.setVisible(mState.action != ACTION_MANAGE);
598a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey
59954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return true;
6009e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
6019e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
60254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
60354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onOptionsItemSelected(MenuItem item) {
60488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) {
605bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
606bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
607bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
60854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final int id = item.getItemId();
60954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        if (id == android.R.id.home) {
610dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            onBackPressed();
611bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
61254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        } else if (id == R.id.menu_create_dir) {
61320d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey            CreateDirectoryFragment.show(getFragmentManager());
614bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
615bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        } else if (id == R.id.menu_search) {
616bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return false;
617ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        } else if (id == R.id.menu_sort_name) {
618d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserSortOrder(State.SORT_ORDER_DISPLAY_NAME);
619ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return true;
620ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        } else if (id == R.id.menu_sort_date) {
621d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserSortOrder(State.SORT_ORDER_LAST_MODIFIED);
622ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return true;
623ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        } else if (id == R.id.menu_sort_size) {
624d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserSortOrder(State.SORT_ORDER_SIZE);
625ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return true;
626b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else if (id == R.id.menu_grid) {
627d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserMode(State.MODE_GRID);
628b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return true;
629b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else if (id == R.id.menu_list) {
630d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            setUserMode(State.MODE_LIST);
631b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return true;
6329fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        } else if (id == R.id.menu_settings) {
6339fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            startActivity(new Intent(this, SettingsActivity.class));
6349fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            return true;
635b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
636b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return super.onOptionsItemSelected(item);
63754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
63854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
63954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
640d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    /**
641d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     * Update UI to reflect internal state changes not from user.
642d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     */
643d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    public void onStateChanged() {
644d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        invalidateOptionsMenu();
645d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    }
646d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
647d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    /**
648d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     * Set state sort order based on explicit user action.
649d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     */
650d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    private void setUserSortOrder(int sortOrder) {
651fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mState.userSortOrder = sortOrder;
652d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
653d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    }
654d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
655d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    /**
656d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     * Set state mode based on explicit user action.
657d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey     */
658d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    private void setUserMode(int mode) {
659fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mState.userMode = mode;
660d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
661d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    }
662d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
663dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    @Override
664dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    public void onBackPressed() {
665fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        if (!mState.stackTouched) {
666fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            super.onBackPressed();
667fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            return;
668fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        }
669fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
670b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final int size = mState.stack.size();
671dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        if (size > 1) {
672b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.stack.pop();
673e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_UP);
67488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey        } else if (size == 1 && !isRootsDrawerOpen()) {
675dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // TODO: open root drawer once we can capture back key
676dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            super.onBackPressed();
677dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        } else {
678dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            super.onBackPressed();
67954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
680dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
68154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
682b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    @Override
683b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    protected void onSaveInstanceState(Bundle state) {
684b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        super.onSaveInstanceState(state);
685b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        state.putParcelable(EXTRA_STATE, mState);
686b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    }
687b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
688b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    @Override
689b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    protected void onRestoreInstanceState(Bundle state) {
690b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        super.onRestoreInstanceState(state);
691b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        updateActionBar();
692b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    }
693b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
694ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey    private BaseAdapter mStackAdapter = new BaseAdapter() {
69554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
69654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public int getCount() {
697ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return mState.stack.size();
69854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
6999e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
70054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
701ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey        public DocumentInfo getItem(int position) {
702ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            return mState.stack.get(mState.stack.size() - position - 1);
70354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
7049e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
70554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
70654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public long getItemId(int position) {
707bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return position;
7089e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
7099e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
7109e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
71154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
71254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            if (convertView == null) {
71354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
714bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                        .inflate(R.layout.item_title, parent, false);
715bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
716bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
717bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
718ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            final DocumentInfo doc = getItem(position);
719bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
720ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (position == 0) {
721ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                final RootInfo root = getCurrentRoot();
722ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                title.setText(root.title);
723bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            } else {
724ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                title.setText(doc.displayName);
725bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
726bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
72728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            // No padding when shown in actionbar
72828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            convertView.setPadding(0, 0, 0, 0);
729bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return convertView;
730bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
731bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
732bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
733bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public View getDropDownView(int position, View convertView, ViewGroup parent) {
734bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            if (convertView == null) {
735bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
73628c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                        .inflate(R.layout.item_title, parent, false);
7379e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
7389e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
73928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
74028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
741ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            final DocumentInfo doc = getItem(position);
742ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
743ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (position == 0) {
744ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                final RootInfo root = getCurrentRoot();
74528c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                title.setText(root.title);
74628c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                subdir.setVisibility(View.GONE);
747ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            } else {
74828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                title.setText(doc.displayName);
74928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey                subdir.setVisibility(View.VISIBLE);
750ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
7519e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
75254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            return convertView;
7539e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
75454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
7559e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
756ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey    private OnNavigationListener mStackListener = new OnNavigationListener() {
7579e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
75854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public boolean onNavigationItemSelected(int itemPosition, long itemId) {
759ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            if (mIgnoreNextNavigation) {
760ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                mIgnoreNextNavigation = false;
761ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                return false;
762ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
763ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey
764ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            while (mState.stack.size() > itemPosition + 1) {
765fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                mState.stackTouched = true;
766ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey                mState.stack.pop();
767ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey            }
768e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_UP);
76954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            return true;
77054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
77154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
77254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
773ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public RootInfo getCurrentRoot() {
774d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        if (mState.stack.root != null) {
775d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            return mState.stack.root;
776b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
7774eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            return mRoots.getRecentsRoot();
778b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        }
779dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
780dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
781ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public DocumentInfo getCurrentDirectory() {
782b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        return mState.stack.peek();
783dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
784dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
785b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    public State getDisplayState() {
786b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        return mState;
7871482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    }
7881482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
789e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey    private void onCurrentDirectoryChanged(int anim) {
790dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final FragmentManager fm = getFragmentManager();
791d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        final RootInfo root = getCurrentRoot();
792ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
7939fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
794e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
795e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
796b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (cwd == null) {
797b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            // No directory means recents
798b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            if (mState.action == ACTION_CREATE) {
799b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                RecentsCreateFragment.show(fm);
800b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
801e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                DirectoryFragment.showRecentsOpen(fm, anim);
80288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey
803deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                // Start recents in grid when requesting visual things
804deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                final boolean visualMimes = MimePredicate.mimeMatches(
805deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                        MimePredicate.VISUAL_MIMES, mState.acceptMimes);
806deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey                mState.userMode = visualMimes ? MODE_GRID : MODE_LIST;
80788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey                mState.derivedMode = mState.userMode;
808b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
809b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
810b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            if (mState.currentSearch != null) {
811b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // Ongoing search
812e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
813b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
814b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // Normal boring directory
815e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                DirectoryFragment.showNormal(fm, root, cwd, anim);
816b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
81754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
818b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
8199fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // Forget any replacement target
820b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_CREATE) {
8219fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            final SaveFragment save = SaveFragment.get(fm);
8229fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (save != null) {
8239fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                save.setReplaceTarget(null);
8249fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
8259fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        }
8269fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
82728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        final RootsFragment roots = RootsFragment.get(fm);
82828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        if (roots != null) {
82928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey            roots.onCurrentRootChanged();
83028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey        }
83128c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey
832dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        updateActionBar();
83354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        invalidateOptionsMenu();
834dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        dumpStack();
83554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
83654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
837b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public void onStackPicked(DocumentStack stack) {
838deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        try {
839deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Update the restored stack to ensure we have freshest data
840deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            stack.updateDocuments(getContentResolver());
841deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
842deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            mState.stack = stack;
843deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            mState.stackTouched = true;
844deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            onCurrentDirectoryChanged(ANIM_SIDE);
845deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
846deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        } catch (FileNotFoundException e) {
847deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            Log.w(TAG, "Failed to restore stack: " + e);
848deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        }
849b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
850b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
851ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onRootPicked(RootInfo root, boolean closeDrawer) {
852ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        // Clear entire backstack and start in new root
853d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        mState.stack.root = root;
854b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        mState.stack.clear();
855fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mState.stackTouched = true;
856b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
857aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkey        if (!mRoots.isRecentsRoot(root)) {
8586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            new PickRootTask(root).execute();
859b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
860e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_SIDE);
861b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        }
86266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
86366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        if (closeDrawer) {
86488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey            setRootsDrawerOpen(false);
86566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
866ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    }
867ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
8686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class PickRootTask extends AsyncTask<Void, Void, DocumentInfo> {
8696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private RootInfo mRoot;
8706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
8716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public PickRootTask(RootInfo root) {
8726efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mRoot = root;
8736efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
8746efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
8756efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
8766efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected DocumentInfo doInBackground(Void... params) {
8776efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            try {
8786efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                final Uri uri = DocumentsContract.buildDocumentUri(
8796efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        mRoot.authority, mRoot.documentId);
8806efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return DocumentInfo.fromUri(getContentResolver(), uri);
8816efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } catch (FileNotFoundException e) {
8827aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                Log.w(TAG, "Failed to find root", e);
8836efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return null;
8846efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
8856efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
8866efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
8876efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
8886efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(DocumentInfo result) {
8896efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (result != null) {
8906efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                mState.stack.push(result);
8916efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                mState.stackTouched = true;
8926efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                onCurrentDirectoryChanged(ANIM_SIDE);
8936efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
8946efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
8956efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
8966efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
89754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    public void onAppPicked(ResolveInfo info) {
89854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        final Intent intent = new Intent(getIntent());
8995545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
90054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        intent.setComponent(new ComponentName(
90154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
9025545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        startActivityForResult(intent, CODE_FORWARD);
9035545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    }
9045545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
9055545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    @Override
9065545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
9075545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        Log.d(TAG, "onActivityResult() code=" + resultCode);
9085545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey
9095545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        // Only relay back results when not canceled; otherwise stick around to
9105545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        // let the user pick another app/backend.
9115545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        if (requestCode == CODE_FORWARD && resultCode != RESULT_CANCELED) {
912deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
913deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Remember that we last picked via external app
914deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            final String packageName = getCallingPackage();
915deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            final ContentValues values = new ContentValues();
916deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            values.put(ResumeColumns.EXTERNAL, 1);
917deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            getContentResolver().insert(RecentsProvider.buildResume(packageName), values);
918deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey
919deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey            // Pass back result to original caller
9205545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey            setResult(resultCode, data);
9215545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey            finish();
9225545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        } else {
9235545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey            super.onActivityResult(requestCode, resultCode, data);
9245545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey        }
92554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    }
92654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
927ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onDocumentPicked(DocumentInfo doc) {
92854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final FragmentManager fm = getFragmentManager();
929b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (doc.isDirectory()) {
930b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            mState.stack.push(doc);
931fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            mState.stackTouched = true;
932e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            onCurrentDirectoryChanged(ANIM_DOWN);
933b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
93454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            // Explicit file picked, return
9356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            new ExistingFinishTask(doc.derivedUri).execute();
936b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_CREATE) {
9379fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // Replace selected file
9389fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            SaveFragment.get(fm).setReplaceTarget(doc);
939b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        } else if (mState.action == ACTION_MANAGE) {
940a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey            // First try managing the document; we expect manager to filter
941a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey            // based on authority, so we don't grant.
942a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey            final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
943d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            manage.setData(doc.derivedUri);
944a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey
9454eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            try {
946a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                startActivity(manage);
9474eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            } catch (ActivityNotFoundException ex) {
948a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                // Fall back to viewing
949a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                final Intent view = new Intent(Intent.ACTION_VIEW);
950a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
951d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                view.setData(doc.derivedUri);
952a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey
953a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                try {
954a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                    startActivity(view);
955a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                } catch (ActivityNotFoundException ex2) {
956a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                    Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
957a61dc8e03e6e863005b3a4629ca8f3801d33d3c4Jeff Sharkey                }
9584eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            }
95954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
96054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
96154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
962ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onDocumentsPicked(List<DocumentInfo> docs) {
963b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
9644eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            final int size = docs.size();
9654eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            final Uri[] uris = new Uri[size];
9664eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            for (int i = 0; i < size; i++) {
967d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                uris[i] = docs.get(i).derivedUri;
9684eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey            }
9696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            new ExistingFinishTask(uris).execute();
970be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
971be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    }
972be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
973ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey    public void onSaveRequested(DocumentInfo replaceTarget) {
9746efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        new ExistingFinishTask(replaceTarget.derivedUri).execute();
9759fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
97692d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey
9779fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public void onSaveRequested(String mimeType, String displayName) {
9786efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        new CreateFinishTask(mimeType, displayName).execute();
97954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
98054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
9816efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private void saveStackBlocking() {
982dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final ContentResolver resolver = getContentResolver();
983dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final ContentValues values = new ContentValues();
984dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
985b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
986b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_CREATE) {
987dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // Remember stack for last create
988dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            values.clear();
9896efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            values.put(RecentColumns.KEY, mState.stack.buildKey());
990d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            values.put(RecentColumns.STACK, rawStack);
991d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            resolver.insert(RecentsProvider.buildRecent(), values);
992dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
993dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
994dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        // Remember location for next app launch
995dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final String packageName = getCallingPackage();
996dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        values.clear();
997d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        values.put(ResumeColumns.STACK, rawStack);
998deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey        values.put(ResumeColumns.EXTERNAL, 0);
999dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        resolver.insert(RecentsProvider.buildResume(packageName), values);
10006efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
10016efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10026efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private void onFinished(Uri... uris) {
10036efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        Log.d(TAG, "onFinished() " + Arrays.toString(uris));
1004dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
100554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final Intent intent = new Intent();
1006be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        if (uris.length == 1) {
1007be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            intent.setData(uris[0]);
1008be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else if (uris.length > 1) {
1009ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final ClipData clipData = new ClipData(
1010b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
1011be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            for (int i = 1; i < uris.length; i++) {
1012be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                clipData.addItem(new ClipData.Item(uris[i]));
1013be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            }
1014be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            intent.setClipData(clipData);
1015be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
101654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1017b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
101854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
101954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        } else {
102054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
102154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
1022e66c1778f80f4b18e29e018eca3a338f125f23b9Jeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
102354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
102454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
102554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        setResult(Activity.RESULT_OK, intent);
102654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        finish();
102754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
102854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
10296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class CreateFinishTask extends AsyncTask<Void, Void, Uri> {
10306efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final String mMimeType;
10316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final String mDisplayName;
10326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10336efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public CreateFinishTask(String mimeType, String displayName) {
10346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mMimeType = mimeType;
10356efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mDisplayName = displayName;
10366efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
10376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10386efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
10396efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected Uri doInBackground(Void... params) {
10407aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            final ContentResolver resolver = getContentResolver();
10416efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            final DocumentInfo cwd = getCurrentDirectory();
10427aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
10437aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            ContentProviderClient client = null;
10447aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            Uri childUri = null;
10457aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            try {
10467aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                client = DocumentsApplication.acquireUnstableProviderOrThrow(
10477aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                        resolver, cwd.derivedUri.getAuthority());
10487aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                childUri = DocumentsContract.createDocument(
10497aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                        client, cwd.derivedUri, mMimeType, mDisplayName);
10507aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            } catch (Exception e) {
10517aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                Log.w(TAG, "Failed to create document", e);
10527aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            } finally {
10537aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                ContentProviderClient.releaseQuietly(client);
10547aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            }
10557aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
10566efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (childUri != null) {
10576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                saveStackBlocking();
10586efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
10597aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
10606efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return childUri;
10616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
10626efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
10646efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(Uri result) {
10656efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (result != null) {
10666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                onFinished(result);
10676efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else {
10686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                Toast.makeText(DocumentsActivity.this, R.string.save_error, Toast.LENGTH_SHORT)
10696efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                        .show();
10706efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
10716efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
10726efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
10736efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10746efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class ExistingFinishTask extends AsyncTask<Void, Void, Void> {
10756efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final Uri[] mUris;
10766efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10776efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        public ExistingFinishTask(Uri... uris) {
10786efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mUris = uris;
10796efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
10806efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10816efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
10826efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected Void doInBackground(Void... params) {
10836efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            saveStackBlocking();
10846efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            return null;
10856efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
10866efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
10876efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
10886efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(Void result) {
10896efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            onFinished(mUris);
10906efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
10916efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
10926efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
1093b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey    public static class State implements android.os.Parcelable {
10944eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public int action;
1095ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public String[] acceptMimes;
1096fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
1097fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Explicit user choice */
1098fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int userMode = MODE_UNKNOWN;
1099fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Derived after loader */
1100fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int derivedMode = MODE_LIST;
1101fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
1102fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Explicit user choice */
1103fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int userSortOrder = SORT_ORDER_UNKNOWN;
1104fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        /** Derived after loader */
1105fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
1106fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey
1107ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public boolean allowMultiple = false;
1108b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        public boolean showSize = false;
110954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        public boolean localOnly = false;
1110348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey        public boolean showAdvanced = false;
1111fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        public boolean stackTouched = false;
1112a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey        public boolean restored = false;
11131482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1114b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        /** Current user navigation stack; empty implies recents. */
1115b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public DocumentStack stack = new DocumentStack();
1116b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        /** Currently active search, overriding any stack. */
1117b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public String currentSearch;
1118b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1119e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        /** Instance state for every shown directory */
1120e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey        public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
1121e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey
11224eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_OPEN = 1;
11234eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_CREATE = 2;
11244eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_GET_CONTENT = 3;
11254eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey        public static final int ACTION_MANAGE = 4;
11264eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey
1127d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int MODE_UNKNOWN = 0;
1128d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int MODE_LIST = 1;
1129d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int MODE_GRID = 2;
11301482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1131d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_UNKNOWN = 0;
1132d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_DISPLAY_NAME = 1;
1133d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_LAST_MODIFIED = 2;
1134d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        public static final int SORT_ORDER_SIZE = 3;
1135b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1136b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        @Override
1137b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public int describeContents() {
1138b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            return 0;
1139b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
1140b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1141b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        @Override
1142b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public void writeToParcel(Parcel out, int flags) {
1143b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(action);
1144fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            out.writeInt(userMode);
1145b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeStringArray(acceptMimes);
1146fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            out.writeInt(userSortOrder);
1147b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(allowMultiple ? 1 : 0);
1148b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(showSize ? 1 : 0);
1149b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeInt(localOnly ? 1 : 0);
1150348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey            out.writeInt(showAdvanced ? 1 : 0);
1151fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            out.writeInt(stackTouched ? 1 : 0);
1152a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey            out.writeInt(restored ? 1 : 0);
1153b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            DurableUtils.writeToParcel(out, stack);
1154b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            out.writeString(currentSearch);
1155e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey            out.writeMap(dirState);
1156b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        }
1157b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1158b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        public static final Creator<State> CREATOR = new Creator<State>() {
1159b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            @Override
1160b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            public State createFromParcel(Parcel in) {
1161b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                final State state = new State();
1162b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.action = in.readInt();
1163fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                state.userMode = in.readInt();
1164b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.acceptMimes = in.readStringArray();
1165fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                state.userSortOrder = in.readInt();
1166b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.allowMultiple = in.readInt() != 0;
1167b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.showSize = in.readInt() != 0;
1168b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.localOnly = in.readInt() != 0;
1169348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey                state.showAdvanced = in.readInt() != 0;
1170fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey                state.stackTouched = in.readInt() != 0;
1171a9ce049db87259e302e2368d2a4a1c11a94fd831Jeff Sharkey                state.restored = in.readInt() != 0;
1172b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                DurableUtils.readFromParcel(in, state.stack);
1173b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                state.currentSearch = in.readString();
1174e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey                in.readMap(state.dirState, null);
1175b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                return state;
1176b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            }
1177b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
1178b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            @Override
1179b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            public State[] newArray(int size) {
1180b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey                return new State[size];
1181b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            }
1182b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        };
11831482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    }
11841482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1185dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    private void dumpStack() {
1186d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        Log.d(TAG, "Current stack: ");
1187d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        Log.d(TAG, " * " + mState.stack.root);
1188b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey        for (DocumentInfo doc : mState.stack) {
1189d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            Log.d(TAG, " +-- " + doc);
1190dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
1191dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
11929fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
11939fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public static DocumentsActivity get(Fragment fragment) {
11949fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        return (DocumentsActivity) fragment.getActivity();
11959fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
11969e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey}
1197