PickActivity.java revision d080506e3aa8547605cd4783eb660775d7d2b8ee
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
19c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKayimport static com.android.documentsui.Shared.DEBUG;
20f8a5e08bfb793e0b1ec7e3ac455a6158ff968afcSteve McKayimport static com.android.documentsui.State.ACTION_CREATE;
21f8a5e08bfb793e0b1ec7e3ac455a6158ff968afcSteve McKayimport static com.android.documentsui.State.ACTION_GET_CONTENT;
22f8a5e08bfb793e0b1ec7e3ac455a6158ff968afcSteve McKayimport static com.android.documentsui.State.ACTION_OPEN;
23f8a5e08bfb793e0b1ec7e3ac455a6158ff968afcSteve McKayimport static com.android.documentsui.State.ACTION_OPEN_TREE;
24b8a5e08119c75b65ccecea8b6a59f2c87ea8ff32Ben Kwaimport static com.android.documentsui.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;
40c4693349d1a49dec8fd203f2c7adce18eee28b0aBen Kwaimport android.support.design.widget.Snackbar;
41e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkeyimport android.util.Log;
4209c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkeyimport android.view.Menu;
43e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
4416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.BaseActivity;
4516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.DocumentsApplication;
4616e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.DocumentsMenuManager;
4716e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.MenuManager;
4816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.MenuManager.DirectoryDetails;
49d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.DocumentInfo;
50d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.PairedTask;
51d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.RootInfo;
5216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.MimePredicate;
5316e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.R;
5416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.Shared;
5516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.Snackbars;
5616e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.State;
57f68210e9a1e36e65e56e0c95cfe990f0145ea63fSteve McKayimport com.android.documentsui.dirlist.DirectoryFragment;
587c35b036cb0de801a093df62da92c4a94399c26cBen Linimport com.android.documentsui.dirlist.FragmentTuner;
597c35b036cb0de801a093df62da92c4a94399c26cBen Linimport com.android.documentsui.dirlist.FragmentTuner.DocumentsTuner;
60d71bd61114e7bd71bac0100187faf75b2284092bTomasz Mikolajewskiimport com.android.documentsui.dirlist.Model;
61d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.picker.LastAccessedProvider.Columns;
62c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKayimport com.android.documentsui.services.FileOperationService;
63d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.sidebar.RootsFragment;
64f7adc939ea1191816a0a7572509d18d0659161ceJeff Sharkey
650e66b9b46fac44785b4059d45933aaba7324b691Ben Kwaimport java.util.Arrays;
660e66b9b46fac44785b4059d45933aaba7324b691Ben Kwaimport java.util.List;
670e66b9b46fac44785b4059d45933aaba7324b691Ben Kwa
6816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKaypublic class PickActivity extends BaseActivity {
694045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey    private static final int CODE_FORWARD = 42;
700574b18a7a95b29fab3cdb9ced6e5b46e24030feBen Kwa    private static final String TAG = "DocumentsActivity";
717c35b036cb0de801a093df62da92c4a94399c26cBen Lin    private DocumentsMenuManager mMenuManager;
727c35b036cb0de801a093df62da92c4a94399c26cBen Lin    private DirectoryDetails mDetails;
734045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey
7416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    public PickActivity() {
7518d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        super(R.layout.documents_activity, TAG);
76b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
7709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
78e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    @Override
79e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    public void onCreate(Bundle icicle) {
800fbfc653868966da7fd6109b247974e0d87a2297Steve McKay        super.onCreate(icicle);
817c35b036cb0de801a093df62da92c4a94399c26cBen Lin        mMenuManager = new DocumentsMenuManager(mSearchManager, getDisplayState());
827c35b036cb0de801a093df62da92c4a94399c26cBen Lin        mDetails = new DirectoryDetails(this);
83b243af7203b9f158bf95c1bf697856d1ee175a10Oren Blasberg
84b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_CREATE) {
8509c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            final String mimeType = getIntent().getType();
8609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
8709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            SaveFragment.show(getFragmentManager(), mimeType, title);
88caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        } else if (mState.action == ACTION_OPEN_TREE ||
89ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                   mState.action == ACTION_PICK_COPY_DESTINATION) {
906e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            PickFragment.show(getFragmentManager());
9109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        }
9246165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey
93b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
941d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            final Intent moreApps = new Intent(getIntent());
951d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            moreApps.setComponent(null);
961d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            moreApps.setPackage(null);
971d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            RootsFragment.show(getFragmentManager(), moreApps);
98caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        } else if (mState.action == ACTION_OPEN ||
99caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono                   mState.action == ACTION_CREATE ||
100caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono                   mState.action == ACTION_OPEN_TREE ||
101ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                   mState.action == ACTION_PICK_COPY_DESTINATION) {
102821727a0fd0fa608a3046db8dad6ea588e16828fBen Lin            RootsFragment.show(getFragmentManager(), (Intent) null);
1031d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey        }
104761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
105fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay        if (mState.restored) {
106a4cb878fa5a7b5253784ca712c824aaae3472585Aga Wronska            if (DEBUG) Log.d(TAG, "Stack already resolved");
107fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay        } else {
108fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // We set the activity title in AsyncTask.onPostExecute().
109fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // To prevent talkback from reading aloud the default title, we clear it here.
110fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            setTitle("");
111fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay
112fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // As a matter of policy we don't load the last used stack for the copy
113fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // destination picker (user is already in Files app).
114fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // Concensus was that the experice was too confusing.
115fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // In all other cases, where the user is visiting us from another app
116fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            // we restore the stack as last used from that app.
117fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            if (mState.action == ACTION_PICK_COPY_DESTINATION) {
118fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay                if (DEBUG) Log.d(TAG, "Launching directly into Home directory.");
11964ae1f4e0236cf9ff06e19887c491bf08ee8adceAga Wronska                loadRoot(getDefaultRoot());
120fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            } else {
121fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay                if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
1227232bf030839be0584824f0b38586360ba365051Ben Lin                new LoadLastAccessedStackTask(this).execute();
123fd8425ae34b73879ca14d244e63381c9400b48d7Steve McKay            }
1248b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey        }
125b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey    }
126f339f25982d562e1690358eb6dc663b327960945Jeff Sharkey
1270fbfc653868966da7fd6109b247974e0d87a2297Steve McKay    @Override
12816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void includeState(State state) {
129b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        final Intent intent = getIntent();
130b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        final String action = intent.getAction();
131b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
132b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_OPEN;
133b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
134b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_CREATE;
135b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
136b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_GET_CONTENT;
137f4943e16a80a7ae37ee19e9301017c15061df378Jeff Sharkey        } else if (Intent.ACTION_OPEN_DOCUMENT_TREE.equals(action)) {
138b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.action = ACTION_OPEN_TREE;
139ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        } else if (Shared.ACTION_PICK_COPY_DESTINATION.equals(action)) {
140ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa            state.action = ACTION_PICK_COPY_DESTINATION;
141b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        }
14246165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey
143b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        if (state.action == ACTION_OPEN || state.action == ACTION_GET_CONTENT) {
144b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.allowMultiple = intent.getBooleanExtra(
145b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey                    Intent.EXTRA_ALLOW_MULTIPLE, false);
146b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        }
14746165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey
14895d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski        if (state.action == ACTION_OPEN || state.action == ACTION_GET_CONTENT
14995d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski                || state.action == ACTION_CREATE) {
15095d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski            state.openableOnly = intent.hasCategory(Intent.CATEGORY_OPENABLE);
15195d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski        }
15295d9c2514fd469b47390fd585819c7478e227221Tomasz Mikolajewski
153ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        if (state.action == ACTION_PICK_COPY_DESTINATION) {
154f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            // Indicates that a copy operation (or move) includes a directory.
155f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            // Why? Directory creation isn't supported by some roots (like Downloads).
156f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            // This allows us to restrict available roots to just those with support.
157b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            state.directoryCopy = intent.getBooleanExtra(
158ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                    Shared.EXTRA_DIRECTORY_COPY, false);
159f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay            state.copyOperationSubType = intent.getIntExtra(
1604833477d7d42fa79ee42956bae4aebad77074e4bGarfield, Tan                    FileOperationService.EXTRA_OPERATION_TYPE,
161c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay                    FileOperationService.OPERATION_COPY);
162f2a822d1b63215dff38e042fe52469755544cf4cDaichi Hirono        }
1638b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey    }
1648b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey
165b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    public void onAppPicked(ResolveInfo info) {
166b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        final Intent intent = new Intent(getIntent());
167b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
168b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        intent.setComponent(new ComponentName(
169b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay                info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
170b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        startActivityForResult(intent, CODE_FORWARD);
171b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
1728b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey
173b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    @Override
174b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
175543a29231a88ac332d1b1c03ccf0cb605b6aebfeBen Kwa        if (DEBUG) Log.d(TAG, "onActivityResult() code=" + resultCode);
17638ec252f93f0798d81b11fce0a4064214928d969Jeff Sharkey
177b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        // Only relay back results when not canceled; otherwise stick around to
178b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        // let the user pick another app/backend.
179b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        if (requestCode == CODE_FORWARD && resultCode != RESULT_CANCELED) {
18038ec252f93f0798d81b11fce0a4064214928d969Jeff Sharkey
181b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            // Remember that we last picked via external app
182b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            final String packageName = getCallingPackageMaybeExtra();
183b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            final ContentValues values = new ContentValues();
1847232bf030839be0584824f0b38586360ba365051Ben Lin            values.put(Columns.EXTERNAL, 1);
1857232bf030839be0584824f0b38586360ba365051Ben Lin            getContentResolver().insert(LastAccessedProvider.buildLastAccessed(packageName), values);
1868b9970489d03ee0bda3d8d4773bf672c182922c6Jeff Sharkey
187b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            // Pass back result to original caller
188b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            setResult(resultCode, data);
189b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            finish();
190b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        } else {
191b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            super.onActivityResult(requestCode, resultCode, data);
1925b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey        }
193f339f25982d562e1690358eb6dc663b327960945Jeff Sharkey    }
1945b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey
19546165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey    @Override
19646165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey    protected void onPostCreate(Bundle savedInstanceState) {
19746165b507883ff67a790a04d74b8d62de60ba227Jeff Sharkey        super.onPostCreate(savedInstanceState);
19818d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        mDrawer.update();
19918d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        mNavigator.update();
200e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    }
201e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
202b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    @Override
20318d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay    public String getDrawerTitle() {
20418d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        String title = getIntent().getStringExtra(DocumentsContract.EXTRA_PROMPT);
20518d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        if (title == null) {
20618d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay            if (mState.action == ACTION_OPEN ||
20718d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                mState.action == ACTION_GET_CONTENT ||
20818d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                mState.action == ACTION_OPEN_TREE) {
20918d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                title = getResources().getString(R.string.title_open);
21018d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay            } else if (mState.action == ACTION_CREATE ||
21118d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                       mState.action == ACTION_PICK_COPY_DESTINATION) {
21218d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay                title = getResources().getString(R.string.title_save);
21377fd402217fc708895158c64ccfdd280dfc1a57fTomasz Mikolajewski            } else {
21417f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay                // If all else fails, just call it "Documents".
21517f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay                title = getResources().getString(R.string.app_label);
21609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            }
217e6fcceb3a65896401450ded1d3fbd13024730873Jeff Sharkey        }
218e6fcceb3a65896401450ded1d3fbd13024730873Jeff Sharkey
21918d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay        return title;
22009c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
221e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
22209c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    @Override
22309c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    public boolean onPrepareOptionsMenu(Menu menu) {
22409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        super.onPrepareOptionsMenu(menu);
2257c35b036cb0de801a093df62da92c4a94399c26cBen Lin        mMenuManager.updateOptionMenu(menu, mDetails);
22609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
227724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
2285b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey
229e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay        if (mState.action == ACTION_CREATE) {
230e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay            final FragmentManager fm = getFragmentManager();
2310fe95042025a9bcf73b0d7a6c3f027092bab825cSteve McKay            SaveFragment.get(fm).prepareForDirectory(cwd);
232e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay        }
233e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay
23409c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        return true;
235e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey    }
236e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey
23709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    @Override
23816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void refreshDirectory(int anim) {
2395b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey        final FragmentManager fm = getFragmentManager();
240a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey        final RootInfo root = getCurrentRoot();
241724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey        final DocumentInfo cwd = getCurrentDirectory();
242c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey
2432e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey        if (cwd == null) {
2442e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey            // No directory means recents
245caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            if (mState.action == ACTION_CREATE ||
246ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa                mState.action == ACTION_PICK_COPY_DESTINATION) {
2477232bf030839be0584824f0b38586360ba365051Ben Lin                loadRoot(getDefaultRoot());
2482e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey            } else {
249c8ae7a5cc51c220c9e0aa2b9c3d128f803f0df16Jeff Sharkey                DirectoryFragment.showRecentsOpen(fm, anim);
2507d58fc6e8875ccc3dbbb34bcd379a0f9c9ee481eJeff Sharkey
2517776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // In recents we pick layout mode based on the mimetype,
2527776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // picking GRID for visual types. We intentionally don't
2537776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // consult a user's saved preferences here since they are
2547776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                // set per root (not per root and per mimetype).
2557776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                boolean visualMimes = MimePredicate.mimeMatches(
25638ec252f93f0798d81b11fce0a4064214928d969Jeff Sharkey                        MimePredicate.VISUAL_MIMES, mState.acceptMimes);
2577776aa5f01b3aa9f7b401ba4f78735a4e028dda4Steve McKay                mState.derivedMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
2582e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey            }
2592e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey        } else {
2602e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey                // Normal boring directory
2618788dadd1b13193b577812df4f9f16a642ebfbb7Aga Wronska                DirectoryFragment.showDirectory(fm, root, cwd, anim);
26209c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        }
2632e694f88bd2088765403f01f8951d1fb4c7244c5Jeff Sharkey
264c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey        // Forget any replacement target
265b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_CREATE) {
266c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            final SaveFragment save = SaveFragment.get(fm);
267c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            if (save != null) {
268c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey                save.setReplaceTarget(null);
269c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            }
270c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey        }
271c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey
272caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        if (mState.action == ACTION_OPEN_TREE ||
273ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa            mState.action == ACTION_PICK_COPY_DESTINATION) {
2746e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            final PickFragment pick = PickFragment.get(fm);
2756e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            if (pick != null) {
276f171934ad7a9d901e81a33bbd0ec74aa34a48787Steve McKay                pick.setPickTarget(mState.action, mState.copyOperationSubType, cwd);
2776e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            }
2786e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey        }
27909c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
28009c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
281b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    void onSaveRequested(DocumentInfo replaceTarget) {
282c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        new ExistingFinishTask(this, replaceTarget.derivedUri)
283c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                .executeOnExecutor(getExecutorForCurrentDirectory());
2849dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
2859dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
2865e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay    @Override
28716e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    public void setPending(boolean pending) {
28816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        final SaveFragment save = SaveFragment.get(getFragmentManager());
28916e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        if (save != null) {
29016e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay            save.setPending(pending);
29116e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        }
29216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    }
29316e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay
29416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    @Override
29516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void onDirectoryCreated(DocumentInfo doc) {
2960af8afd3309538dec784ed0c9c35b252a8213123Steve McKay        assert(doc.isDirectory());
2975e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay        openContainerDocument(doc);
2985e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay    }
2995e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay
300b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    void onSaveRequested(String mimeType, String displayName) {
301c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        new CreateFinishTask(this, mimeType, displayName)
302c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                .executeOnExecutor(getExecutorForCurrentDirectory());
3034045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey    }
3044045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey
3054045780fb2336d23588546da473c462e9634e0a1Jeff Sharkey    @Override
306d71bd61114e7bd71bac0100187faf75b2284092bTomasz Mikolajewski    public void onDocumentPicked(DocumentInfo doc, Model model) {
30709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        final FragmentManager fm = getFragmentManager();
308734936aaddd080946a92e80bc65dc3d11a93f2d1Tomasz Mikolajewski        if (doc.isContainer()) {
309734936aaddd080946a92e80bc65dc3d11a93f2d1Tomasz Mikolajewski            openContainerDocument(doc);
310b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
31109c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey            // Explicit file picked, return
312c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            new ExistingFinishTask(this, doc.derivedUri)
313c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                    .executeOnExecutor(getExecutorForCurrentDirectory());
314b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        } else if (mState.action == ACTION_CREATE) {
315c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            // Replace selected file
316c6cbdf11d976ff5845d12c46fb2d601ca7fb0ab2Jeff Sharkey            SaveFragment.get(fm).setReplaceTarget(doc);
31709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        }
31809c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
31909c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
320d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay    @Override
321724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkey    public void onDocumentsPicked(List<DocumentInfo> docs) {
322b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
323873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            final int size = docs.size();
324873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            final Uri[] uris = new Uri[size];
325873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            for (int i = 0; i < size; i++) {
326a4d1f2200ddfb0d12145fba8457c47e8051c84f7Jeff Sharkey                uris[i] = docs.get(i).derivedUri;
327873daa3bd4d88e91fccf0dd6f05bacc5f2b1fef5Jeff Sharkey            }
328c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            new ExistingFinishTask(this, uris)
329c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                    .executeOnExecutor(getExecutorForCurrentDirectory());
330c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        }
331c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey    }
332c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey
3336e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey    public void onPickRequested(DocumentInfo pickTarget) {
334caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        Uri result;
335caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        if (mState.action == ACTION_OPEN_TREE) {
336caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            result = DocumentsContract.buildTreeDocumentUri(
337caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono                    pickTarget.authority, pickTarget.documentId);
338ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        } else if (mState.action == ACTION_PICK_COPY_DESTINATION) {
339caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            result = pickTarget.derivedUri;
340caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        } else {
341caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            // Should not be reached.
342caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono            throw new IllegalStateException("Invalid mState.action.");
343caadd41756cf53d71a735c8cf4ec16e7224de146Daichi Hirono        }
344c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        new PickFinishTask(this, result).executeOnExecutor(getExecutorForCurrentDirectory());
3456e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey    }
3466e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey
3477232bf030839be0584824f0b38586360ba365051Ben Lin    void updateLastAccessed() {
3487232bf030839be0584824f0b38586360ba365051Ben Lin        LastAccessedProvider.setLastAccessed(
3497232bf030839be0584824f0b38586360ba365051Ben Lin                getContentResolver(), getCallingPackageMaybeExtra(), mState.stack);
3509dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
3519dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
352b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    @Override
35316e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    protected void onTaskFinished(Uri... uris) {
354543a29231a88ac332d1b1c03ccf0cb605b6aebfeBen Kwa        if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
3555b53592dc3d9691ea96af39ed37246169bcc74c3Jeff Sharkey
35609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        final Intent intent = new Intent();
357c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        if (uris.length == 1) {
358c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            intent.setData(uris[0]);
359c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        } else if (uris.length > 1) {
360a5defe39d4eea635f9e2fac1822ff9c8d48a474aJeff Sharkey            final ClipData clipData = new ClipData(
361b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
362c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            for (int i = 1; i < uris.length; i++) {
363c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey                clipData.addItem(new ClipData.Item(uris[i]));
364c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            }
365c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey            intent.setClipData(clipData);
366c317af8d44d225b63e5e8879b218f1a7575604d7Jeff Sharkey        }
36709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
368b36204422c05de753a17ea9f53a422bf4e4acffcJeff Sharkey        if (mState.action == ACTION_GET_CONTENT) {
3691d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
3706c3164ded0ff721997f388783a6d2fd436e22366Jeff Sharkey        } else if (mState.action == ACTION_OPEN_TREE) {
3716e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
3726e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3736e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3746e565ffab8916af6c991c4f189a7ec438bce6978Jeff Sharkey                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
375ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa        } else if (mState.action == ACTION_PICK_COPY_DESTINATION) {
3766c3164ded0ff721997f388783a6d2fd436e22366Jeff Sharkey            // Picking a copy destination is only used internally by us, so we
3776c3164ded0ff721997f388783a6d2fd436e22366Jeff Sharkey            // don't need to extend permissions to the caller.
3784d0255f79cc92a5675d14b20f9cdf06ecb8d7109Steve McKay            intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
3794833477d7d42fa79ee42956bae4aebad77074e4bGarfield, Tan            intent.putExtra(FileOperationService.EXTRA_OPERATION_TYPE, mState.copyOperationSubType);
3801d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey        } else {
3811d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
3821d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
38313d369f702aeed957db63858e942b2f1c117bffdJeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
3841d890e0daf2f46dc83580280cfa22031dfebc216Jeff Sharkey        }
38509c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
38609c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        setResult(Activity.RESULT_OK, intent);
38709c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey        finish();
38809c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey    }
38909c10bf0b982cda69fadc182841c23d6792f0471Jeff Sharkey
390c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay
39116e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    public static PickActivity get(Fragment fragment) {
39216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        return (PickActivity) fragment.getActivity();
393b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
394b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
3957c35b036cb0de801a093df62da92c4a94399c26cBen Lin    @Override
3967c35b036cb0de801a093df62da92c4a94399c26cBen Lin    public FragmentTuner createFragmentTuner() {
3977c35b036cb0de801a093df62da92c4a94399c26cBen Lin        // Currently DocumentsTuner maintains a state specific to the fragment instance. Because of
3987c35b036cb0de801a093df62da92c4a94399c26cBen Lin        // that, we create a new instance everytime it is needed
3999de0da60f46dbdf6939f371a619d4d2018949d36Steve McKay        return new DocumentsTuner(this, getDisplayState(), mSortController);
4007c35b036cb0de801a093df62da92c4a94399c26cBen Lin    }
4017c35b036cb0de801a093df62da92c4a94399c26cBen Lin
4027c35b036cb0de801a093df62da92c4a94399c26cBen Lin    @Override
4037c35b036cb0de801a093df62da92c4a94399c26cBen Lin    public MenuManager getMenuManager() {
4047c35b036cb0de801a093df62da92c4a94399c26cBen Lin        return mMenuManager;
4057c35b036cb0de801a093df62da92c4a94399c26cBen Lin    }
4067c35b036cb0de801a093df62da92c4a94399c26cBen Lin
407ebf2a172b69cfa9105cb5807e7b76f58425be76cBen Lin    @Override
408ebf2a172b69cfa9105cb5807e7b76f58425be76cBen Lin    public DirectoryDetails getDirectoryDetails() {
409ebf2a172b69cfa9105cb5807e7b76f58425be76cBen Lin        return mDetails;
410ebf2a172b69cfa9105cb5807e7b76f58425be76cBen Lin    }
411ebf2a172b69cfa9105cb5807e7b76f58425be76cBen Lin
41216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    private static final class PickFinishTask extends PairedTask<PickActivity, Void, Void> {
413b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        private final Uri mUri;
414b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
41516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        public PickFinishTask(PickActivity activity, Uri uri) {
416c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            super(activity);
417b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            mUri = uri;
418b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
419b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
420b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
421c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected Void run(Void... params) {
4227232bf030839be0584824f0b38586360ba365051Ben Lin            mOwner.updateLastAccessed();
423b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            return null;
424b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
425b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
426b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
427c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void finish(Void result) {
428c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.onTaskFinished(mUri);
429b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
430b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
431b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
43216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    private static final class ExistingFinishTask extends PairedTask<PickActivity, Void, Void> {
433b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        private final Uri[] mUris;
434b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
43516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        public ExistingFinishTask(PickActivity activity, Uri... uris) {
436c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            super(activity);
437b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            mUris = uris;
438b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
439b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
440b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
441c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected Void run(Void... params) {
4427232bf030839be0584824f0b38586360ba365051Ben Lin            mOwner.updateLastAccessed();
443b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay            return null;
444b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
445b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
446b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        @Override
447c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void finish(Void result) {
448c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.onTaskFinished(mUris);
449b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay        }
450b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    }
451b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay
452b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay    /**
453b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay     * Task that creates a new document in the background.
454b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay     */
45516e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay    private static final class CreateFinishTask extends PairedTask<PickActivity, Void, Uri> {
4569dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        private final String mMimeType;
4579dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        private final String mDisplayName;
4589dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
45916e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay        public CreateFinishTask(PickActivity activity, String mimeType, String displayName) {
460c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            super(activity);
4619dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            mMimeType = mimeType;
4629dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            mDisplayName = displayName;
4639dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
4649dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
4659dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        @Override
466c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void prepare() {
467c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.setPending(true);
4684be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        }
4694be51f196d60ba23856b646de3091364230258b0Jeff Sharkey
4704be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        @Override
471c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected Uri run(Void... params) {
472c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            final ContentResolver resolver = mOwner.getContentResolver();
473c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            final DocumentInfo cwd = mOwner.getCurrentDirectory();
4743fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
4753fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            ContentProviderClient client = null;
4763fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            Uri childUri = null;
4773fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            try {
4783fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                client = DocumentsApplication.acquireUnstableProviderOrThrow(
4793fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                        resolver, cwd.derivedUri.getAuthority());
4803fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                childUri = DocumentsContract.createDocument(
4813fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                        client, cwd.derivedUri, mMimeType, mDisplayName);
4823fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            } catch (Exception e) {
4833fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                Log.w(TAG, "Failed to create document", e);
4843fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            } finally {
4853fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                ContentProviderClient.releaseQuietly(client);
4863fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            }
4873fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
4889dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            if (childUri != null) {
4897232bf030839be0584824f0b38586360ba365051Ben Lin                mOwner.updateLastAccessed();
4909dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            }
4913fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
4929dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            return childUri;
4939dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
4949dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
4959dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        @Override
496c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay        protected void finish(Uri result) {
4979dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            if (result != null) {
498c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                mOwner.onTaskFinished(result);
4999dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            } else {
500e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay                Snackbars.makeSnackbar(
501c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay                        mOwner, R.string.save_error, Snackbar.LENGTH_SHORT).show();
5029dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            }
5034be51f196d60ba23856b646de3091364230258b0Jeff Sharkey
504c7dc0cfe6f990a8589f37ef593378a691d379c94Steve McKay            mOwner.setPending(false);
5059dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
5069dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
507e22d02ecf489473c9983c554de308306e2741b7Jeff Sharkey}
508