PickActivity.java revision 78ade2b9111c69a3cb169024646577f38136bbf7
1e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey/*
2e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project
3e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey *
4e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * you may not use this file except in compliance with the License.
6e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * You may obtain a copy of the License at
7e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey *
8e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey *
10e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * See the License for the specific language governing permissions and
14e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey * limitations under the License.
15e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey */
16e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
1716e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKaypackage com.android.documentsui.picker;
18e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
19d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.Shared.DEBUG;
20d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.State.ACTION_CREATE;
21d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.State.ACTION_GET_CONTENT;
22d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.State.ACTION_OPEN;
23d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.State.ACTION_OPEN_TREE;
24d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION;
25311a7d8ef646fac19e5524da778108836df9a2dcJeff Sharkey
26e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.app.Activity;
27b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKayimport android.app.Fragment;
28e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.app.FragmentManager;
29c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkeyimport android.content.ClipData;
301d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkeyimport android.content.ComponentName;
313fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkeyimport android.content.ContentProviderClient;
32c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkeyimport android.content.ContentResolver;
33f7adc939ea1191816a0a7572509d18d0659161ceJeff Sharkeyimport android.content.ContentValues;
34e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.content.Intent;
351d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkeyimport android.content.pm.ResolveInfo;
36e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.net.Uri;
37e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.os.Bundle;
382023fcf5a16503524ca8ad1bfb8445a67d27d0a6Tomasz Mikolajewskiimport android.os.Parcelable;
39f339f25982d562e1690358eb6dc663b327960945Jeff Sharkeyimport android.provider.DocumentsContract;
40047182631669608af946480c2545a10acb2ef1bfSteve McKayimport android.support.annotation.CallSuper;
41c4693349d1a49dec8fd203f2c7adce18eee28b0aBen Kwaimport android.support.design.widget.Snackbar;
42e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.util.Log;
43047182631669608af946480c2545a10acb2ef1bfSteve McKayimport android.view.KeyEvent;
4409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkeyimport android.view.Menu;
45e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
46bd9f05aa36bf19d8b34d0d73a59e9bd65d3d26ebSteve McKayimport com.android.documentsui.ActionModeController;
4716e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.BaseActivity;
4816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.DocumentsApplication;
4975b7b9039cf0efcb188e916c6f510328bfe099a8Ben Linimport com.android.documentsui.FocusManager;
5092ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKayimport com.android.documentsui.Injector;
5116e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.MenuManager.DirectoryDetails;
52988d8a354b00dce7e24deee187c08a4591956ac9Steve McKayimport com.android.documentsui.ProviderExecutor;
53990f76ea83a249cd8fc3c797e40626b94cd7945cSteve McKayimport com.android.documentsui.R;
54047182631669608af946480c2545a10acb2ef1bfSteve McKayimport com.android.documentsui.SharedInputHandler;
55d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.DocumentInfo;
56d071895ec72bbb9414f6672ff808ec42b8e2d850Steve McKayimport com.android.documentsui.base.MimeTypes;
57d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.PairedTask;
58d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.RootInfo;
59d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport com.android.documentsui.base.Shared;
60d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport com.android.documentsui.base.State;
61f68210e9a1e36e65e56e0c95cfe990f0145ea63fSteve McKayimport com.android.documentsui.dirlist.DirectoryFragment;
62d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.picker.LastAccessedProvider.Columns;
63e8b547f1a7acdd10fd1e2f5816cebae49ecfd90bSteve McKayimport com.android.documentsui.prefs.ScopedPreferences;
644f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport com.android.documentsui.selection.SelectionManager;
65c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKayimport com.android.documentsui.services.FileOperationService;
66d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.sidebar.RootsFragment;
67c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKayimport com.android.documentsui.ui.DialogController;
6892ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKayimport com.android.documentsui.ui.MessageBuilder;
69c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKayimport com.android.documentsui.ui.Snackbars;
70f7adc939ea1191816a0a7572509d18d0659161ceJeff Sharkey
710e66b9b46fac44785b4059d45933aaba7324b691Ben Kwaimport java.util.Arrays;
720e66b9b46fac44785b4059d45933aaba7324b691Ben Kwaimport java.util.List;
730e66b9b46fac44785b4059d45933aaba7324b691Ben Kwa
7492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKaypublic class PickActivity extends BaseActivity implements ActionHandler.Addons {
7592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay
7692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay    static final String PREFERENCES_SCOPE = "picker";
77990f76ea83a249cd8fc3c797e40626b94cd7945cSteve McKay
78b6006b2ef723fdbb3fef3b4a350c8d363b127d0fSteve McKay    private static final String TAG = "PickActivity";
796525a19f46eca7fbec21a71f833436823de03da3Steve McKay    private static final int CODE_FORWARD = 42;
806525a19f46eca7fbec21a71f833436823de03da3Steve McKay
8192ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay    private Injector<ActionHandler<PickActivity>> mInjector;
82047182631669608af946480c2545a10acb2ef1bfSteve McKay    private SharedInputHandler mSharedInputHandler;
834045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey
8416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    public PickActivity() {
8518d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        super(R.layout.documents_activity, TAG);
86b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
8709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
88e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    @Override
89e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    public void onCreate(Bundle icicle) {
906525a19f46eca7fbec21a71f833436823de03da3Steve McKay
9192ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector = new Injector<>(
9292ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                new Config(),
9392ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                ScopedPreferences.create(this, PREFERENCES_SCOPE),
9492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                new MessageBuilder(this),
9592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                DialogController.STUB);
966525a19f46eca7fbec21a71f833436823de03da3Steve McKay
970fbfc653868966da7fd6109b247974e0d87a2297Steve McKay        super.onCreate(icicle);
98739f94ba0dc9be264d9596dac551fd63082d2fddSteve McKay
9992ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.selectionMgr = new SelectionManager(
1004f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                mState.allowMultiple
1014f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                        ? SelectionManager.MODE_MULTIPLE
1024f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                        : SelectionManager.MODE_SINGLE);
103047182631669608af946480c2545a10acb2ef1bfSteve McKay
10492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.focusManager = new FocusManager(
10592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                mInjector.selectionMgr,
106047182631669608af946480c2545a10acb2ef1bfSteve McKay                mDrawer,
10792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                this::focusSidebar,
108047182631669608af946480c2545a10acb2ef1bfSteve McKay                getColor(R.color.accent_dark));
109047182631669608af946480c2545a10acb2ef1bfSteve McKay
11092ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.menuManager = new MenuManager(mSearchManager, mState, new DirectoryDetails(this));
11130d8c7988e15336d995e4b5033ba533a8333446fJon Mann        mInjector.actionModeController = new ActionModeController(
11230d8c7988e15336d995e4b5033ba533a8333446fJon Mann                this,
11330d8c7988e15336d995e4b5033ba533a8333446fJon Mann                mInjector.selectionMgr,
11430d8c7988e15336d995e4b5033ba533a8333446fJon Mann                mInjector.menuManager,
11530d8c7988e15336d995e4b5033ba533a8333446fJon Mann                mInjector.messages);
11692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.actions = new ActionHandler<>(
117988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay                this,
118988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay                mState,
11963bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan                mRoots,
12063bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan                mDocs,
12163bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan                mSearchManager,
122988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay                ProviderExecutor::forAuthority,
12330d8c7988e15336d995e4b5033ba533a8333446fJon Mann                mInjector);
1245b0a2c187a9e446b683687817d22cbe443585223Steve McKay
125988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay        Intent intent = getIntent();
126988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay
12792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mSharedInputHandler = new SharedInputHandler(mInjector.focusManager, this::popDir);
128047182631669608af946480c2545a10acb2ef1bfSteve McKay
129988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay        setupLayout(intent);
13092ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.actions.initLocation(intent);
131988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay    }
132988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay
133988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay    private void setupLayout(Intent intent) {
134b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_CREATE) {
135988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay            final String mimeType = intent.getType();
136988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay            final String title = intent.getStringExtra(Intent.EXTRA_TITLE);
13709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            SaveFragment.show(getFragmentManager(), mimeType, title);
138caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        } else if (mState.action == ACTION_OPEN_TREE ||
139ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                   mState.action == ACTION_PICK_COPY_DESTINATION) {
1406e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            PickFragment.show(getFragmentManager());
14109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        }
14246165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey
143b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
144988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay            final Intent moreApps = new Intent(intent);
1451d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            moreApps.setComponent(null);
1461d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            moreApps.setPackage(null);
1471d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            RootsFragment.show(getFragmentManager(), moreApps);
148caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        } else if (mState.action == ACTION_OPEN ||
149caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono                   mState.action == ACTION_CREATE ||
150caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono                   mState.action == ACTION_OPEN_TREE ||
151ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                   mState.action == ACTION_PICK_COPY_DESTINATION) {
152821727a0fd0fa608a3046db8dad6ea588e16828fBen Lin            RootsFragment.show(getFragmentManager(), (Intent) null);
1531d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey        }
154b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey    }
155f339f25982d562e1690358eb6dc663b327960945Jeff Sharkey
1560fbfc653868966da7fd6109b247974e0d87a2297Steve McKay    @Override
15716e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void includeState(State state) {
158b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        final Intent intent = getIntent();
15978ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan
16078ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan        String defaultMimeType = (intent.getType() == null) ? "*/*" : intent.getType();
16178ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan        state.initAcceptMimes(intent, defaultMimeType);
16278ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan
163b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        final String action = intent.getAction();
164b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
165b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_OPEN;
166b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
167b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_CREATE;
168b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
169b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_GET_CONTENT;
170f4943e16a80a7ae37ee19e9301017c15061df378Jeff Sharkey        } else if (Intent.ACTION_OPEN_DOCUMENT_TREE.equals(action)) {
171b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_OPEN_TREE;
172ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        } else if (Shared.ACTION_PICK_COPY_DESTINATION.equals(action)) {
173ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa            state.action = ACTION_PICK_COPY_DESTINATION;
174b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        }
17546165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey
176b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        if (state.action == ACTION_OPEN || state.action == ACTION_GET_CONTENT) {
177b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.allowMultiple = intent.getBooleanExtra(
178b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey                    Intent.EXTRA_ALLOW_MULTIPLE, false);
179b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        }
18046165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey
18195d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski        if (state.action == ACTION_OPEN || state.action == ACTION_GET_CONTENT
18295d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski                || state.action == ACTION_CREATE) {
18395d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski            state.openableOnly = intent.hasCategory(Intent.CATEGORY_OPENABLE);
18495d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski        }
18595d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski
186ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        if (state.action == ACTION_PICK_COPY_DESTINATION) {
187f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            // Indicates that a copy operation (or move) includes a directory.
188f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            // Why? Directory creation isn't supported by some roots (like Downloads).
189f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            // This allows us to restrict available roots to just those with support.
190b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.directoryCopy = intent.getBooleanExtra(
191ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                    Shared.EXTRA_DIRECTORY_COPY, false);
192f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            state.copyOperationSubType = intent.getIntExtra(
1934833477d7d42fa79ee42956bae4aebad77074e4bGarfield, Tan                    FileOperationService.EXTRA_OPERATION_TYPE,
194c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay                    FileOperationService.OPERATION_COPY);
195f2a822d1b63215dff38e042fe52469755544cf4cDaichi Hirono        }
1968b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey    }
1978b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey
198c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay    @Override
199b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    public void onAppPicked(ResolveInfo info) {
200b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        final Intent intent = new Intent(getIntent());
201b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
202b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        intent.setComponent(new ComponentName(
203b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay                info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
204b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        startActivityForResult(intent, CODE_FORWARD);
205b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
2068b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey
207b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    @Override
208b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
209543a29231a88ac332d1b1c03ccf0cb605b6aebfeBen Kwa        if (DEBUG) Log.d(TAG, "onActivityResult() code=" + resultCode);
21038ec252f93f0798d81b11fce0a4064214928d969Jeff Sharkey
211b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        // Only relay back results when not canceled; otherwise stick around to
212b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        // let the user pick another app/backend.
213b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        if (requestCode == CODE_FORWARD && resultCode != RESULT_CANCELED) {
21438ec252f93f0798d81b11fce0a4064214928d969Jeff Sharkey
215b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            // Remember that we last picked via external app
216988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay            final String packageName = Shared.getCallingPackageName(this);
217b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            final ContentValues values = new ContentValues();
2187232bf030839be0584824f0b38586360ba365051Ben Lin            values.put(Columns.EXTERNAL, 1);
2197232bf030839be0584824f0b38586360ba365051Ben Lin            getContentResolver().insert(LastAccessedProvider.buildLastAccessed(packageName), values);
2208b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey
221b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            // Pass back result to original caller
222b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            setResult(resultCode, data);
223b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            finish();
224b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        } else {
225b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            super.onActivityResult(requestCode, resultCode, data);
2265b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey        }
227f339f25982d562e1690358eb6dc663b327960945Jeff Sharkey    }
2285b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey
22946165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey    @Override
23046165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey    protected void onPostCreate(Bundle savedInstanceState) {
23146165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey        super.onPostCreate(savedInstanceState);
23218d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        mDrawer.update();
23318d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        mNavigator.update();
234e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    }
235e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
236b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    @Override
23718d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay    public String getDrawerTitle() {
23818d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        String title = getIntent().getStringExtra(DocumentsContract.EXTRA_PROMPT);
23918d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        if (title == null) {
24018d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay            if (mState.action == ACTION_OPEN ||
24118d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                mState.action == ACTION_GET_CONTENT ||
24218d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                mState.action == ACTION_OPEN_TREE) {
24318d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                title = getResources().getString(R.string.title_open);
24418d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay            } else if (mState.action == ACTION_CREATE ||
24518d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                       mState.action == ACTION_PICK_COPY_DESTINATION) {
24618d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                title = getResources().getString(R.string.title_save);
24777fd402217fc708895158c64ccfdd280dfc1a57fTomasz Mikolajewski            } else {
24817f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay                // If all else fails, just call it "Documents".
24917f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay                title = getResources().getString(R.string.app_label);
25009c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            }
251e6fcceb3a65896401450ded1d3fbd13024730873Jeff Sharkey        }
252e6fcceb3a65896401450ded1d3fbd13024730873Jeff Sharkey
25318d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        return title;
25409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
255e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
25609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    @Override
25709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    public boolean onPrepareOptionsMenu(Menu menu) {
25809c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        super.onPrepareOptionsMenu(menu);
25992ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.menuManager.updateOptionMenu(menu);
26009c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
261724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
2625b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey
263e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay        if (mState.action == ACTION_CREATE) {
264e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay            final FragmentManager fm = getFragmentManager();
2650fe95042025a9bcf73b0d7a6c3f027092bab825cSteve McKay            SaveFragment.get(fm).prepareForDirectory(cwd);
266e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay        }
267e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay
26809c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        return true;
269e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    }
270e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
27109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    @Override
27216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void refreshDirectory(int anim) {
2735b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey        final FragmentManager fm = getFragmentManager();
274a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        final RootInfo root = getCurrentRoot();
275724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
276c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey
2772e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey        if (cwd == null) {
2782e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey            // No directory means recents
279caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            if (mState.action == ACTION_CREATE ||
280ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                mState.action == ACTION_PICK_COPY_DESTINATION) {
28192ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay                mInjector.actions.loadRoot(Shared.getDefaultRootUri(this));
2822e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey            } else {
283c8ae7a5cc51c220c9e0aa2b9c3d128f803f0df16Jeff Sharkey                DirectoryFragment.showRecentsOpen(fm, anim);
2847d58fc6e8875ccc3dbbb34bcd379a0f9c9ee481eJeff Sharkey
2857776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // In recents we pick layout mode based on the mimetype,
2867776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // picking GRID for visual types. We intentionally don't
2877776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // consult a user's saved preferences here since they are
2887776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // set per root (not per root and per mimetype).
289d071895ec72bbb9414f6672ff808ec42b8e2d850Steve McKay                boolean visualMimes = MimeTypes.mimeMatches(
290d071895ec72bbb9414f6672ff808ec42b8e2d850Steve McKay                        MimeTypes.VISUAL_MIMES, mState.acceptMimes);
2917776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                mState.derivedMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
2922e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey            }
2932e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey        } else {
2942e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey                // Normal boring directory
2958788dadd1b13193b577812df4f9f16a642ebfbb7Aga Wronska                DirectoryFragment.showDirectory(fm, root, cwd, anim);
29609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        }
2972e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey
298c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey        // Forget any replacement target
299b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_CREATE) {
300c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            final SaveFragment save = SaveFragment.get(fm);
301c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            if (save != null) {
302c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey                save.setReplaceTarget(null);
303c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            }
304c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey        }
305c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey
306caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        if (mState.action == ACTION_OPEN_TREE ||
307ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa            mState.action == ACTION_PICK_COPY_DESTINATION) {
3086e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            final PickFragment pick = PickFragment.get(fm);
3096e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            if (pick != null) {
310f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay                pick.setPickTarget(mState.action, mState.copyOperationSubType, cwd);
3116e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            }
3126e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey        }
31309c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
31409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
315b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    void onSaveRequested(DocumentInfo replaceTarget) {
316c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        new ExistingFinishTask(this, replaceTarget.derivedUri)
317c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                .executeOnExecutor(getExecutorForCurrentDirectory());
3189dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
3199dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
3205e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay    @Override
32116e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    public void setPending(boolean pending) {
32216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        final SaveFragment save = SaveFragment.get(getFragmentManager());
32316e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        if (save != null) {
32416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay            save.setPending(pending);
32516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        }
32616e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    }
32716e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay
32816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    @Override
32916e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void onDirectoryCreated(DocumentInfo doc) {
3300af8afd3309538dec784ed0c9c35b252a8213123Steve McKay        assert(doc.isDirectory());
33192ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        mInjector.actions.openContainerDocument(doc);
3325e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay    }
3335e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay
334b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    void onSaveRequested(String mimeType, String displayName) {
335c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        new CreateFinishTask(this, mimeType, displayName)
336c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                .executeOnExecutor(getExecutorForCurrentDirectory());
3374045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey    }
3384045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey
3394045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey    @Override
340eed2f4ec78227b5e173ff667a5517637a91b9a30Steve McKay    public void onDocumentPicked(DocumentInfo doc) {
34109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        final FragmentManager fm = getFragmentManager();
34252fe423907ac089fff5c56d84261ebd0c0506519Tomasz Mikolajewski        // Do not inline-open archives, as otherwise it would be impossible to pick
34352fe423907ac089fff5c56d84261ebd0c0506519Tomasz Mikolajewski        // archive files. Note, that picking files inside archives is not supported.
34452fe423907ac089fff5c56d84261ebd0c0506519Tomasz Mikolajewski        if (doc.isDirectory()) {
34592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay            mInjector.actions.openContainerDocument(doc);
346b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
34709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            // Explicit file picked, return
348c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            new ExistingFinishTask(this, doc.derivedUri)
349c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                    .executeOnExecutor(getExecutorForCurrentDirectory());
350b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (mState.action == ACTION_CREATE) {
351c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            // Replace selected file
352c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            SaveFragment.get(fm).setReplaceTarget(doc);
35309c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        }
35409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
35509c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
356d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay    @Override
357724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public void onDocumentsPicked(List<DocumentInfo> docs) {
358b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
359873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            final int size = docs.size();
360873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            final Uri[] uris = new Uri[size];
361873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            for (int i = 0; i < size; i++) {
362a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                uris[i] = docs.get(i).derivedUri;
363873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            }
364c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            new ExistingFinishTask(this, uris)
365c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                    .executeOnExecutor(getExecutorForCurrentDirectory());
366c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        }
367c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey    }
368c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey
3696e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey    public void onPickRequested(DocumentInfo pickTarget) {
370caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        Uri result;
371caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        if (mState.action == ACTION_OPEN_TREE) {
372caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            result = DocumentsContract.buildTreeDocumentUri(
373caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono                    pickTarget.authority, pickTarget.documentId);
374ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        } else if (mState.action == ACTION_PICK_COPY_DESTINATION) {
375caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            result = pickTarget.derivedUri;
376caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        } else {
377caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            // Should not be reached.
378caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            throw new IllegalStateException("Invalid mState.action.");
379caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        }
380c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        new PickFinishTask(this, result).executeOnExecutor(getExecutorForCurrentDirectory());
3816e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey    }
3826e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey
3837232bf030839be0584824f0b38586360ba365051Ben Lin    void updateLastAccessed() {
3847232bf030839be0584824f0b38586360ba365051Ben Lin        LastAccessedProvider.setLastAccessed(
385988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay                getContentResolver(), Shared.getCallingPackageName(this), mState.stack);
3869dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
3879dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
38878ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan    private void onTaskFinished(Uri... uris) {
389543a29231a88ac332d1b1c03ccf0cb605b6aebfeBen Kwa        if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
3905b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey
39109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        final Intent intent = new Intent();
392c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        if (uris.length == 1) {
393c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            intent.setData(uris[0]);
394c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        } else if (uris.length > 1) {
395a5defe39d4eea635f9e2fac1822ff9c8d48a474aJeff Sharkey            final ClipData clipData = new ClipData(
396b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
397c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            for (int i = 1; i < uris.length; i++) {
398c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey                clipData.addItem(new ClipData.Item(uris[i]));
399c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            }
400c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            intent.setClipData(clipData);
401c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        }
40209c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
403b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
4041d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
4056c3164ded0ff721997f388783a6d2fd436e22366Jeff Sharkey        } else if (mState.action == ACTION_OPEN_TREE) {
4066e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
4076e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
4086e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4096e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
410ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        } else if (mState.action == ACTION_PICK_COPY_DESTINATION) {
4116c3164ded0ff721997f388783a6d2fd436e22366Jeff Sharkey            // Picking a copy destination is only used internally by us, so we
4126c3164ded0ff721997f388783a6d2fd436e22366Jeff Sharkey            // don't need to extend permissions to the caller.
4134d0255f79cc92a5675d14b20f9cdf06ecb8d7109Steve McKay            intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
4144833477d7d42fa79ee42956bae4aebad77074e4bGarfield, Tan            intent.putExtra(FileOperationService.EXTRA_OPERATION_TYPE, mState.copyOperationSubType);
4151d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey        } else {
4161d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
4171d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
41813d369f702aeed957db63858e942b2f1c117bffdJeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
4191d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey        }
42009c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
42109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        setResult(Activity.RESULT_OK, intent);
42209c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        finish();
42309c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
42409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
425047182631669608af946480c2545a10acb2ef1bfSteve McKay    @CallSuper
426047182631669608af946480c2545a10acb2ef1bfSteve McKay    @Override
427047182631669608af946480c2545a10acb2ef1bfSteve McKay    public boolean onKeyDown(int keyCode, KeyEvent event) {
428047182631669608af946480c2545a10acb2ef1bfSteve McKay        return mSharedInputHandler.onKeyDown(keyCode, event)
429047182631669608af946480c2545a10acb2ef1bfSteve McKay                || super.onKeyDown(keyCode, event);
430047182631669608af946480c2545a10acb2ef1bfSteve McKay    }
431c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay
43216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    public static PickActivity get(Fragment fragment) {
43316e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        return (PickActivity) fragment.getActivity();
434b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
435b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
43616e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    private static final class PickFinishTask extends PairedTask<PickActivity, Void, Void> {
437b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        private final Uri mUri;
438b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
43916e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        public PickFinishTask(PickActivity activity, Uri uri) {
440c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            super(activity);
441b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            mUri = uri;
442b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
443b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
444b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
445c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected Void run(Void... params) {
4467232bf030839be0584824f0b38586360ba365051Ben Lin            mOwner.updateLastAccessed();
447b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            return null;
448b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
449b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
450b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
451c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void finish(Void result) {
452c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.onTaskFinished(mUri);
453b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
454b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
455b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
45616e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    private static final class ExistingFinishTask extends PairedTask<PickActivity, Void, Void> {
457b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        private final Uri[] mUris;
458b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
45916e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        public ExistingFinishTask(PickActivity activity, Uri... uris) {
460c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            super(activity);
461b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            mUris = uris;
462b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
463b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
464b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
465c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected Void run(Void... params) {
4667232bf030839be0584824f0b38586360ba365051Ben Lin            mOwner.updateLastAccessed();
467b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            return null;
468b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
469b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
470b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
471c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void finish(Void result) {
472c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.onTaskFinished(mUris);
473b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
474b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
475b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
476b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    /**
477b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay     * Task that creates a new document in the background.
478b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay     */
47916e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    private static final class CreateFinishTask extends PairedTask<PickActivity, Void, Uri> {
4809dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        private final String mMimeType;
4819dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        private final String mDisplayName;
4829dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
48316e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        public CreateFinishTask(PickActivity activity, String mimeType, String displayName) {
484c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            super(activity);
4859dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            mMimeType = mimeType;
4869dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            mDisplayName = displayName;
4879dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
4889dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
4899dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        @Override
490c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void prepare() {
491c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.setPending(true);
4924be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        }
4934be51f196d60ba23856b646de3091364230258b0Jeff Sharkey
4944be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        @Override
495c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected Uri run(Void... params) {
496c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            final ContentResolver resolver = mOwner.getContentResolver();
497c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            final DocumentInfo cwd = mOwner.getCurrentDirectory();
4983fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
4993fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            ContentProviderClient client = null;
5003fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            Uri childUri = null;
5013fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            try {
5023fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                client = DocumentsApplication.acquireUnstableProviderOrThrow(
5033fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                        resolver, cwd.derivedUri.getAuthority());
5043fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                childUri = DocumentsContract.createDocument(
5053fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                        client, cwd.derivedUri, mMimeType, mDisplayName);
5063fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            } catch (Exception e) {
5073fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                Log.w(TAG, "Failed to create document", e);
5083fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            } finally {
5093fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                ContentProviderClient.releaseQuietly(client);
5103fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            }
5113fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
5129dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            if (childUri != null) {
5137232bf030839be0584824f0b38586360ba365051Ben Lin                mOwner.updateLastAccessed();
5149dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            }
5153fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
5169dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            return childUri;
5179dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
5189dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
5199dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        @Override
520c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void finish(Uri result) {
5219dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            if (result != null) {
522c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                mOwner.onTaskFinished(result);
5239dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            } else {
524e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay                Snackbars.makeSnackbar(
525c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                        mOwner, R.string.save_error, Snackbar.LENGTH_SHORT).show();
5269dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            }
5274be51f196d60ba23856b646de3091364230258b0Jeff Sharkey
528c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.setPending(false);
5299dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
5309dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
53192ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay
53292ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay    @Override
53392ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay    public Injector<ActionHandler<PickActivity>> getInjector() {
53492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay        return mInjector;
53592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay    }
536e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey}
537