blob: dd8ccf9d4df414d57b010b009141818ec509d4dd [file] [log] [blame]
Steve McKayd0a2a2c2015-03-25 14:35:33 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.documentsui;
18
Steve McKay459bc2b2015-09-16 15:07:31 -070019import static com.android.documentsui.Shared.DEBUG;
Steve McKayf68210e2015-11-03 15:23:16 -080020import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
Steve McKay459bc2b2015-09-16 15:07:31 -070021import static com.android.internal.util.Preconditions.checkArgument;
Steve McKayf2c8b0d2015-09-23 15:44:24 -070022import static com.android.internal.util.Preconditions.checkState;
Steve McKay7ef09a22015-05-06 12:16:40 -070023
Steve McKayd0a2a2c2015-03-25 14:35:33 -070024import android.app.Activity;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070025import android.app.FragmentManager;
26import android.content.ActivityNotFoundException;
27import android.content.ClipData;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070028import android.content.ContentResolver;
29import android.content.ContentValues;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070030import android.content.Intent;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070031import android.net.Uri;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070032import android.os.Bundle;
Steve McKay4d0255f2015-09-25 16:02:56 -070033import android.os.Parcelable;
34import android.provider.DocumentsContract;
Steve McKayfefcd702015-08-20 16:19:38 +000035import android.support.annotation.Nullable;
Ben Kwac4693342015-09-30 10:00:10 -070036import android.support.design.widget.Snackbar;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070037import android.util.Log;
Steve McKay0599a442015-05-05 14:50:00 -070038import android.view.KeyEvent;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070039import android.view.Menu;
40import android.view.MenuItem;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070041import android.view.View;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070042import android.widget.BaseAdapter;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070043import android.widget.Spinner;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070044import android.widget.Toolbar;
45
46import com.android.documentsui.RecentsProvider.ResumeColumns;
Steve McKayf68210e2015-11-03 15:23:16 -080047import com.android.documentsui.dirlist.DirectoryFragment;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070048import com.android.documentsui.model.DocumentInfo;
49import com.android.documentsui.model.DocumentStack;
50import com.android.documentsui.model.DurableUtils;
51import com.android.documentsui.model.RootInfo;
52
Tomasz Mikolajewski332d8192015-04-13 19:38:43 +090053import java.util.ArrayList;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070054import java.util.Arrays;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070055import java.util.List;
Steve McKayd0a2a2c2015-03-25 14:35:33 -070056
Steve McKayb68dd222015-04-20 17:18:15 -070057/**
Steve McKay64ac2512015-05-12 12:49:58 -070058 * Standalone file management activity.
Steve McKayb68dd222015-04-20 17:18:15 -070059 */
Steve McKay0fbfc652015-08-20 16:48:49 -070060public class FilesActivity extends BaseActivity {
Steve McKayedc65bb2015-07-31 14:35:22 -070061
Ben Kwa0574b182015-09-08 07:31:19 -070062 public static final String TAG = "FilesActivity";
Steve McKayd0a2a2c2015-03-25 14:35:33 -070063
Steve McKayd0a2a2c2015-03-25 14:35:33 -070064 private Toolbar mToolbar;
65 private Spinner mToolbarStack;
Steve McKayb68dd222015-04-20 17:18:15 -070066 private ItemSelectedListener mStackListener;
67 private BaseAdapter mStackAdapter;
Steve McKay1f199482015-05-20 15:58:42 -070068 private DocumentClipper mClipper;
Steve McKayb68dd222015-04-20 17:18:15 -070069
Steve McKay0fbfc652015-08-20 16:48:49 -070070 public FilesActivity() {
71 super(R.layout.files_activity, TAG);
Steve McKayb68dd222015-04-20 17:18:15 -070072 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -070073
74 @Override
75 public void onCreate(Bundle icicle) {
Steve McKayd0a2a2c2015-03-25 14:35:33 -070076 super.onCreate(icicle);
77
Steve McKayd0a2a2c2015-03-25 14:35:33 -070078 mToolbar = (Toolbar) findViewById(R.id.toolbar);
Steve McKayd0a2a2c2015-03-25 14:35:33 -070079
Steve McKayb68dd222015-04-20 17:18:15 -070080 mStackAdapter = new StackAdapter();
81 mStackListener = new ItemSelectedListener();
Steve McKayd0a2a2c2015-03-25 14:35:33 -070082 mToolbarStack = (Spinner) findViewById(R.id.stack);
83 mToolbarStack.setOnItemSelectedListener(mStackListener);
84
Steve McKayd0a2a2c2015-03-25 14:35:33 -070085 setActionBar(mToolbar);
86
Steve McKay0fbfc652015-08-20 16:48:49 -070087 mClipper = new DocumentClipper(this);
88 mDrawer = DrawerController.create(this);
Steve McKay1f199482015-05-20 15:58:42 -070089
Steve McKayd0a2a2c2015-03-25 14:35:33 -070090 RootsFragment.show(getFragmentManager(), null);
Steve McKay459bc2b2015-09-16 15:07:31 -070091
Steve McKay4d0255f2015-09-25 16:02:56 -070092 if (mState.restored) {
Steve McKay6c8bfb72015-10-05 12:32:46 -070093 if (DEBUG) Log.d(TAG, "Restored instance for uri: " + getIntent().getData());
Steve McKay4d0255f2015-09-25 16:02:56 -070094 onCurrentDirectoryChanged(ANIM_NONE);
95 } else {
96 Intent intent = getIntent();
97 Uri uri = intent.getData();
98
Steve McKay6c8bfb72015-10-05 12:32:46 -070099 if (DEBUG) Log.d(TAG, "Creating new instance for uri: " + uri);
Steve McKay4d0255f2015-09-25 16:02:56 -0700100 // If a non-empty stack is present in our state it was read (presumably)
101 // from EXTRA_STACK intent extra. In this case, we'll skip other means of
102 // loading or restoring the stack.
103 if (!mState.stack.isEmpty()) {
Steve McKaya8fa58d2015-12-08 17:02:03 -0800104 if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
Steve McKay4d0255f2015-09-25 16:02:56 -0700105 // When restoring from a stack, if a URI is present, it should only ever
106 // be a launch URI. Launch URIs support sensible activity management, but
Steve McKaya8fa58d2015-12-08 17:02:03 -0800107 // don't specify a real content target.
108 checkState(uri == null || LauncherActivity.isLaunchUri(uri));
Steve McKay4d0255f2015-09-25 16:02:56 -0700109 onCurrentDirectoryChanged(ANIM_NONE);
110 } else if (DocumentsContract.isRootUri(this, uri)) {
Steve McKaya8fa58d2015-12-08 17:02:03 -0800111 if (DEBUG) Log.d(TAG, "Launching with root URI.");
Steve McKay4d0255f2015-09-25 16:02:56 -0700112 // If we've got a specific root to display, restore that root using a dedicated
113 // authority. That way a misbehaving provider won't result in an ANR.
114 new RestoreRootTask(uri).executeOnExecutor(
115 ProviderExecutor.forAuthority(uri.getAuthority()));
Steve McKay459bc2b2015-09-16 15:07:31 -0700116 } else {
Steve McKaya8fa58d2015-12-08 17:02:03 -0800117 if (DEBUG) Log.d(TAG, "Launching into Home directory.");
118 // If all else fails, try to load "Home" directory.
119 uri = DocumentsContract.buildHomeUri();
120 new RestoreRootTask(uri).executeOnExecutor(
121 ProviderExecutor.forAuthority(uri.getAuthority()));
Steve McKay459bc2b2015-09-16 15:07:31 -0700122 }
Tomasz Mikolajewski9452c442015-04-14 16:32:41 +0900123
Steve McKay4d0255f2015-09-25 16:02:56 -0700124 // TODO: Ensure we're handling CopyService errors correctly across all activities.
Tomasz Mikolajewski9452c442015-04-14 16:32:41 +0900125 // Show a failure dialog if there was a failed operation.
Tomasz Mikolajewski332d8192015-04-13 19:38:43 +0900126 final int failure = intent.getIntExtra(CopyService.EXTRA_FAILURE, 0);
Ben Kwacb4461f2015-05-05 11:50:11 -0700127 final int transferMode = intent.getIntExtra(CopyService.EXTRA_TRANSFER_MODE,
Tomasz Mikolajewski85578962015-11-04 15:33:20 +0900128 CopyService.TRANSFER_MODE_COPY);
Tomasz Mikolajewski332d8192015-04-13 19:38:43 +0900129 if (failure != 0) {
Tomasz Mikolajewski9452c442015-04-14 16:32:41 +0900130 final ArrayList<DocumentInfo> failedSrcList =
131 intent.getParcelableArrayListExtra(CopyService.EXTRA_SRC_LIST);
Steve McKay4d0255f2015-09-25 16:02:56 -0700132 FailureDialogFragment.show(
133 getFragmentManager(),
134 failure,
135 failedSrcList,
136 mState.stack,
Ben Kwacb4461f2015-05-05 11:50:11 -0700137 transferMode);
Tomasz Mikolajewski332d8192015-04-13 19:38:43 +0900138 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700139 }
140 }
141
Steve McKay0fbfc652015-08-20 16:48:49 -0700142 @Override
Ben Kwa0574b182015-09-08 07:31:19 -0700143 State buildState() {
144 State state = buildDefaultState();
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700145
146 final Intent intent = getIntent();
Ben Kwa0574b182015-09-08 07:31:19 -0700147
Steve McKay459bc2b2015-09-16 15:07:31 -0700148 state.action = State.ACTION_BROWSE;
Ben Kwa0574b182015-09-08 07:31:19 -0700149 state.allowMultiple = true;
Steve McKay64ac2512015-05-12 12:49:58 -0700150
Steve McKay459bc2b2015-09-16 15:07:31 -0700151 // Options specific to the DocumentsActivity.
152 checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
Steve McKay64ac2512015-05-12 12:49:58 -0700153
Steve McKay4d0255f2015-09-25 16:02:56 -0700154 final DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);
Steve McKay459bc2b2015-09-16 15:07:31 -0700155 if (stack != null) {
Steve McKayb68dd222015-04-20 17:18:15 -0700156 state.stack = stack;
Steve McKay459bc2b2015-09-16 15:07:31 -0700157 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700158
Steve McKayb68dd222015-04-20 17:18:15 -0700159 return state;
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700160 }
161
162 @Override
163 protected void onPostCreate(Bundle savedInstanceState) {
164 super.onPostCreate(savedInstanceState);
Steve McKaya8fa58d2015-12-08 17:02:03 -0800165 // This check avoids a flicker from "Recents" to "Home".
166 // Only update action bar at this point if there is an active
167 // serach. Why? Because this avoid an early (undesired) load of
168 // the recents root...which is the default root in other activities.
169 // In Files app "Home" is the default, but it is loaded async.
170 // updateActionBar will be called once Home root is loaded.
171 // Except while searching we need this call to ensure the
172 // search bits get layed out correctly.
173 if (mSearchManager.isSearching()) {
174 updateActionBar();
175 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700176 }
177
178 @Override
Steve McKay459bc2b2015-09-16 15:07:31 -0700179 public void onResume() {
180 super.onResume();
181
182 final RootInfo root = getCurrentRoot();
183
184 // If we're browsing a specific root, and that root went away, then we
185 // have no reason to hang around.
186 // TODO: Rather than just disappearing, maybe we should inform
187 // the user what has happened, let them close us. Less surprising.
188 if (mRoots.getRootBlocking(root.authority, root.rootId) == null) {
189 finish();
190 }
191 }
192
193 @Override
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700194 public void updateActionBar() {
195 final RootInfo root = getCurrentRoot();
Steve McKay6bbed4d2015-08-17 13:18:05 -0700196
Steve McKay0fbfc652015-08-20 16:48:49 -0700197 if (mDrawer.isPresent()) {
Steve McKay6bbed4d2015-08-17 13:18:05 -0700198 mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
199 mToolbar.setNavigationContentDescription(R.string.drawer_open);
200 mToolbar.setNavigationOnClickListener(
201 new View.OnClickListener() {
202 @Override
203 public void onClick(View v) {
204 mDrawer.setOpen(true);
205 }
206 });
207 } else {
208 mToolbar.setNavigationIcon(
209 root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
210 mToolbar.setNavigationContentDescription(R.string.drawer_open);
211 mToolbar.setNavigationOnClickListener(null);
212 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700213
Steve McKayb68dd222015-04-20 17:18:15 -0700214 if (mSearchManager.isExpanded()) {
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700215 mToolbar.setTitle(null);
216 mToolbarStack.setVisibility(View.GONE);
217 mToolbarStack.setAdapter(null);
218 } else {
219 if (mState.stack.size() <= 1) {
220 mToolbar.setTitle(root.title);
221 mToolbarStack.setVisibility(View.GONE);
222 mToolbarStack.setAdapter(null);
223 } else {
224 mToolbar.setTitle(null);
225 mToolbarStack.setVisibility(View.VISIBLE);
226 mToolbarStack.setAdapter(mStackAdapter);
227
Steve McKayb68dd222015-04-20 17:18:15 -0700228 mStackListener.mIgnoreNextNavigation = true;
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700229 mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
230 }
231 }
232 }
233
234 @Override
235 public boolean onCreateOptionsMenu(Menu menu) {
Steve McKayb68dd222015-04-20 17:18:15 -0700236 boolean showMenu = super.onCreateOptionsMenu(menu);
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700237
Steve McKayb68dd222015-04-20 17:18:15 -0700238 expandMenus(menu);
Steve McKayb68dd222015-04-20 17:18:15 -0700239 return showMenu;
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700240 }
241
242 @Override
243 public boolean onPrepareOptionsMenu(Menu menu) {
Steve McKaye9809272015-10-01 11:39:24 -0700244 super.onPrepareOptionsMenu(menu);
Steve McKayf2c8b0d2015-09-23 15:44:24 -0700245
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700246 final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
Steve McKayf2c8b0d2015-09-23 15:44:24 -0700247 final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
248 final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700249
Steve McKay8e258c62015-05-06 14:27:57 -0700250 createDir.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
Steve McKaye9809272015-10-01 11:39:24 -0700251 createDir.setVisible(true);
252 createDir.setEnabled(canCreateDirectory());
253
254 pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
Steve McKayceeb3f72015-05-19 16:10:25 -0700255
Steve McKayf2c8b0d2015-09-23 15:44:24 -0700256 newWindow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
257 newWindow.setVisible(mProductivityDevice);
Steve McKayf2c8b0d2015-09-23 15:44:24 -0700258
Steve McKaye9809272015-10-01 11:39:24 -0700259 Menus.disableHiddenItems(menu, pasteFromCb);
260 return true;
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700261 }
262
263 @Override
Steve McKay1f199482015-05-20 15:58:42 -0700264 public boolean onOptionsItemSelected(MenuItem item) {
Steve McKayf2c8b0d2015-09-23 15:44:24 -0700265 switch (item.getItemId()) {
266 case R.id.menu_create_dir:
267 checkState(canCreateDirectory());
268 showCreateDirectoryDialog();
269 return true;
270 case R.id.menu_new_window:
Steve McKay4d0255f2015-09-25 16:02:56 -0700271 createNewWindow();
Steve McKayf2c8b0d2015-09-23 15:44:24 -0700272 return true;
273 case R.id.menu_paste_from_clipboard:
274 DirectoryFragment dir = DirectoryFragment.get(getFragmentManager());
275 dir = DirectoryFragment.get(getFragmentManager());
276 dir.pasteFromClipboard();
277 return true;
Steve McKay1f199482015-05-20 15:58:42 -0700278 }
279
280 return super.onOptionsItemSelected(item);
281 }
282
Steve McKay4d0255f2015-09-25 16:02:56 -0700283 private void createNewWindow() {
284 Intent intent = LauncherActivity.createLaunchIntent(this);
285 intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
286 startActivity(intent);
287 }
288
Steve McKay1f199482015-05-20 15:58:42 -0700289 @Override
Steve McKayb68dd222015-04-20 17:18:15 -0700290 void onDirectoryChanged(int anim) {
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700291 final FragmentManager fm = getFragmentManager();
292 final RootInfo root = getCurrentRoot();
293 final DocumentInfo cwd = getCurrentDirectory();
294
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700295 if (cwd == null) {
296 DirectoryFragment.showRecentsOpen(fm, anim);
297
298 // Start recents in grid when requesting visual things
299 final boolean visualMimes = MimePredicate.mimeMatches(
300 MimePredicate.VISUAL_MIMES, mState.acceptMimes);
301 mState.userMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
302 mState.derivedMode = mState.userMode;
303 } else {
304 if (mState.currentSearch != null) {
305 // Ongoing search
306 DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
307 } else {
308 // Normal boring directory
309 DirectoryFragment.showNormal(fm, root, cwd, anim);
310 }
311 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700312 }
313
314 @Override
Steve McKay6bbed4d2015-08-17 13:18:05 -0700315 void onRootPicked(RootInfo root) {
316 super.onRootPicked(root);
317 mDrawer.setOpen(false);
318 }
319
320 @Override
Steve McKay351a7492015-08-04 10:11:01 -0700321 public void onDocumentsPicked(List<DocumentInfo> docs) {
322 throw new UnsupportedOperationException();
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700323 }
324
Steve McKay351a7492015-08-04 10:11:01 -0700325 @Override
Ben Kwab8a5e082015-12-07 13:25:27 -0800326 public void onDocumentPicked(DocumentInfo doc, @Nullable SiblingProvider siblings) {
Tomasz Mikolajewski734936a2015-11-25 13:01:18 +0900327 if (doc.isContainer()) {
328 openContainerDocument(doc);
Steve McKay351a7492015-08-04 10:11:01 -0700329 } else {
330 openDocument(doc, siblings);
331 }
Steve McKayedc65bb2015-07-31 14:35:22 -0700332 }
333
334 /**
335 * Launches an intent to view the specified document.
336 */
Ben Kwab8a5e082015-12-07 13:25:27 -0800337 private void openDocument(DocumentInfo doc, @Nullable SiblingProvider siblings) {
Steve McKay351a7492015-08-04 10:11:01 -0700338 Intent intent = null;
339 if (siblings != null) {
Steve McKay3bd316c2015-10-15 15:27:30 -0700340 QuickViewIntentBuilder builder = new QuickViewIntentBuilder(
341 getPackageManager(), getResources(), doc, siblings);
Steve McKay351a7492015-08-04 10:11:01 -0700342 intent = builder.build();
343 }
344
Steve McKay3bd316c2015-10-15 15:27:30 -0700345 if (intent != null) {
346 // TODO: un-work around issue b/24963914. Should be fixed soon.
347 try {
348 startActivity(intent);
349 return;
350 } catch (SecurityException e) {
Steve McKayb4a6b362015-10-23 09:04:09 -0700351 // Carry on to regular view mode.
Steve McKay3bd316c2015-10-15 15:27:30 -0700352 Log.e(TAG, "Caught security error: " + e.getLocalizedMessage());
353 }
Steve McKayedc65bb2015-07-31 14:35:22 -0700354 }
355
Steve McKayb4a6b362015-10-23 09:04:09 -0700356 // Fallback to traditional VIEW action...
Steve McKay3bd316c2015-10-15 15:27:30 -0700357 intent = new Intent(Intent.ACTION_VIEW);
358 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
359 intent.setData(doc.derivedUri);
360
Steve McKay351a7492015-08-04 10:11:01 -0700361 if (DEBUG && intent.getClipData() != null) {
362 Log.d(TAG, "Starting intent w/ clip data: " + intent.getClipData());
363 }
364
Steve McKayedc65bb2015-07-31 14:35:22 -0700365 try {
366 startActivity(intent);
Steve McKay3bd316c2015-10-15 15:27:30 -0700367 } catch (ActivityNotFoundException e) {
368 Snackbars.makeSnackbar(
369 this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
Steve McKayedc65bb2015-07-31 14:35:22 -0700370 }
371 }
372
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700373 @Override
Steve McKay0599a442015-05-05 14:50:00 -0700374 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
375 DirectoryFragment dir;
376 switch (keyCode) {
377 case KeyEvent.KEYCODE_A:
378 dir = DirectoryFragment.get(getFragmentManager());
379 dir.selectAllFiles();
380 return true;
Steve McKay1f199482015-05-20 15:58:42 -0700381 case KeyEvent.KEYCODE_C:
382 // TODO: Should be statically bound using alphabeticShortcut. See b/21330356.
Steve McKay0599a442015-05-05 14:50:00 -0700383 dir = DirectoryFragment.get(getFragmentManager());
Steve McKay1f199482015-05-20 15:58:42 -0700384 dir.copySelectedToClipboard();
Steve McKay6035b3c2015-12-04 11:19:09 -0800385 return true;
386 case KeyEvent.KEYCODE_V:
387 // TODO: Should be statically bound using alphabeticShortcut. See b/21330356.
388 dir = DirectoryFragment.get(getFragmentManager());
389 dir.pasteFromClipboard();
390 return true;
391 default:
392 return super.onKeyShortcut(keyCode, event);
Steve McKay0599a442015-05-05 14:50:00 -0700393 }
394 }
395
396 @Override
Steve McKayb68dd222015-04-20 17:18:15 -0700397 void saveStackBlocking() {
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700398 final ContentResolver resolver = getContentResolver();
399 final ContentValues values = new ContentValues();
400
Steve McKayb68dd222015-04-20 17:18:15 -0700401 final byte[] rawStack = DurableUtils.writeToArrayOrNull(
402 getDisplayState().stack);
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700403
404 // Remember location for next app launch
405 final String packageName = getCallingPackageMaybeExtra();
406 values.clear();
407 values.put(ResumeColumns.STACK, rawStack);
408 values.put(ResumeColumns.EXTERNAL, 0);
409 resolver.insert(RecentsProvider.buildResume(packageName), values);
410 }
411
Steve McKayb68dd222015-04-20 17:18:15 -0700412 @Override
413 void onTaskFinished(Uri... uris) {
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700414 Log.d(TAG, "onFinished() " + Arrays.toString(uris));
415
416 final Intent intent = new Intent();
417 if (uris.length == 1) {
418 intent.setData(uris[0]);
419 } else if (uris.length > 1) {
420 final ClipData clipData = new ClipData(
421 null, mState.acceptMimes, new ClipData.Item(uris[0]));
422 for (int i = 1; i < uris.length; i++) {
423 clipData.addItem(new ClipData.Item(uris[i]));
424 }
425 intent.setClipData(clipData);
426 }
427
428 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
429 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
430 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
431
432 setResult(Activity.RESULT_OK, intent);
433 finish();
434 }
Steve McKayd0a2a2c2015-03-25 14:35:33 -0700435}