summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java151
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java151
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java27
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java47
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/PairedTask.java77
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java52
6 files changed, 309 insertions, 196 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index e72343e9a9ba..2eaf76f5ebec 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -45,22 +45,16 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Spinner;
-import android.widget.Toolbar;
-import com.android.documentsui.RecentsProvider.ResumeColumns;
import com.android.documentsui.SearchManager.SearchManagerListener;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
-import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
import com.android.internal.util.Preconditions;
-import libcore.io.IoUtils;
-
import java.io.FileNotFoundException;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -87,8 +81,8 @@ public abstract class BaseActivity extends Activity
abstract void onTaskFinished(Uri... uris);
abstract void refreshDirectory(int anim);
- abstract void saveStackBlocking();
- abstract State buildState();
+ /** Allows sub-classes to include information in a newly created State instance. */
+ abstract void includeState(State initialState);
public BaseActivity(@LayoutRes int layoutId, String tag) {
mLayoutId = layoutId;
@@ -103,9 +97,7 @@ public abstract class BaseActivity extends Activity
setContentView(mLayoutId);
mDrawer = DrawerController.create(this);
- mState = (icicle != null)
- ? icicle.<State>getParcelable(EXTRA_STATE)
- : buildState();
+ mState = getState(icicle);
Metrics.logActivityLaunch(this, mState, getIntent());
mRoots = DocumentsApplication.getRootsCache(this);
@@ -114,7 +106,8 @@ public abstract class BaseActivity extends Activity
new RootsCache.OnCacheUpdateListener() {
@Override
public void onCacheUpdate() {
- new HandleRootsChangedTask().execute(getCurrentRoot());
+ new HandleRootsChangedTask(BaseActivity.this)
+ .execute(getCurrentRoot());
}
});
@@ -184,7 +177,20 @@ public abstract class BaseActivity extends Activity
super.onDestroy();
}
- State buildDefaultState() {
+ private State getState(@Nullable Bundle icicle) {
+ if (icicle != null) {
+ State state = icicle.<State>getParcelable(EXTRA_STATE);
+ if (DEBUG) Log.d(mTag, "Recovered existing state object: " + state);
+ return state;
+ }
+
+ State state = createSharedState();
+ includeState(state);
+ if (DEBUG) Log.d(mTag, "Created new state object: " + state);
+ return state;
+ }
+
+ private State createSharedState() {
State state = new State();
final Intent intent = getIntent();
@@ -224,7 +230,7 @@ public abstract class BaseActivity extends Activity
if (mRoots.isRecentsRoot(root)) {
refreshCurrentRootAndDirectory(ANIM_NONE);
} else {
- new PickRootTask(root).executeOnExecutor(getExecutorForCurrentDirectory());
+ new PickRootTask(this, root).executeOnExecutor(getExecutorForCurrentDirectory());
}
}
@@ -574,115 +580,40 @@ public abstract class BaseActivity extends Activity
}
}
- final class PickRootTask extends AsyncTask<Void, Void, DocumentInfo> {
+ private static final class PickRootTask extends PairedTask<BaseActivity, Void, DocumentInfo> {
private RootInfo mRoot;
- public PickRootTask(RootInfo root) {
+ public PickRootTask(BaseActivity activity, RootInfo root) {
+ super(activity);
mRoot = root;
}
@Override
- protected DocumentInfo doInBackground(Void... params) {
- return getRootDocumentBlocking(mRoot);
- }
-
- @Override
- protected void onPostExecute(DocumentInfo result) {
- if (result != null && !isDestroyed()) {
- openContainerDocument(result);
- }
+ protected DocumentInfo run(Void... params) {
+ return mOwner.getRootDocumentBlocking(mRoot);
}
- }
-
- final class RestoreStackTask extends AsyncTask<Void, Void, Void> {
- private volatile boolean mRestoredStack;
- private volatile boolean mExternal;
@Override
- protected Void doInBackground(Void... params) {
- if (DEBUG && !mState.stack.isEmpty()) {
- Log.w(mTag, "Overwriting existing stack.");
- }
- RootsCache roots = DocumentsApplication.getRootsCache(BaseActivity.this);
-
- // Restore last stack for calling package
- final String packageName = getCallingPackageMaybeExtra();
- final Cursor cursor = getContentResolver()
- .query(RecentsProvider.buildResume(packageName), null, null, null, null);
- try {
- if (cursor.moveToFirst()) {
- mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
- final byte[] rawStack = cursor.getBlob(
- cursor.getColumnIndex(ResumeColumns.STACK));
- DurableUtils.readFromArray(rawStack, mState.stack);
- mRestoredStack = true;
- }
- } catch (IOException e) {
- Log.w(mTag, "Failed to resume: " + e);
- } finally {
- IoUtils.closeQuietly(cursor);
- }
-
- if (mRestoredStack) {
- // Update the restored stack to ensure we have freshest data
- final Collection<RootInfo> matchingRoots = roots.getMatchingRootsBlocking(mState);
- try {
- mState.stack.updateRoot(matchingRoots);
- mState.stack.updateDocuments(getContentResolver());
- } catch (FileNotFoundException e) {
- Log.w(mTag, "Failed to restore stack: " + e);
- mState.stack.reset();
- mRestoredStack = false;
- }
+ protected void finish(DocumentInfo result) {
+ if (result != null) {
+ mOwner.openContainerDocument(result);
}
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- if (isDestroyed()) return;
- mState.restored = true;
- refreshCurrentRootAndDirectory(ANIM_NONE);
- onStackRestored(mRestoredStack, mExternal);
}
}
- final class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
- private Uri mRootUri;
-
- public RestoreRootTask(Uri rootUri) {
- mRootUri = rootUri;
- }
-
- @Override
- protected RootInfo doInBackground(Void... params) {
- final String rootId = DocumentsContract.getRootId(mRootUri);
- return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
- }
+ private static final class HandleRootsChangedTask
+ extends PairedTask<BaseActivity, RootInfo, RootInfo> {
+ DocumentInfo mHome;
- @Override
- protected void onPostExecute(RootInfo root) {
- if (isDestroyed()) return;
- mState.restored = true;
-
- if (root != null) {
- onRootPicked(root);
- } else {
- Log.w(mTag, "Failed to find root: " + mRootUri);
- finish();
- }
+ public HandleRootsChangedTask(BaseActivity activity) {
+ super(activity);
}
- }
-
- final class HandleRootsChangedTask extends AsyncTask<RootInfo, Void, RootInfo> {
- DocumentInfo mHome;
@Override
- protected RootInfo doInBackground(RootInfo... roots) {
+ protected RootInfo run(RootInfo... roots) {
checkArgument(roots.length == 1);
final RootInfo currentRoot = roots[0];
- final Collection<RootInfo> cachedRoots = mRoots.getRootsBlocking();
+ final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
RootInfo homeRoot = null;
for (final RootInfo root : cachedRoots) {
if (root.isHome()) {
@@ -694,17 +625,17 @@ public abstract class BaseActivity extends Activity
}
}
Preconditions.checkNotNull(homeRoot);
- mHome = getRootDocumentBlocking(homeRoot);
+ mHome = mOwner.getRootDocumentBlocking(homeRoot);
return homeRoot;
}
@Override
- protected void onPostExecute(RootInfo homeRoot) {
- if (homeRoot != null && mHome != null && !isDestroyed()) {
+ protected void finish(RootInfo homeRoot) {
+ if (homeRoot != null && mHome != null) {
// Clear entire backstack and start in new root
- mState.onRootChanged(homeRoot);
- mSearchManager.update(homeRoot);
- openContainerDocument(mHome);
+ mOwner.mState.onRootChanged(homeRoot);
+ mOwner.mSearchManager.update(homeRoot);
+ mOwner.openContainerDocument(mHome);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 815ff3db9517..b33b6007ba7e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,6 +16,7 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.State.ACTION_CREATE;
import static com.android.documentsui.State.ACTION_GET_CONTENT;
import static com.android.documentsui.State.ACTION_OPEN;
@@ -31,11 +32,12 @@ import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
@@ -52,7 +54,12 @@ import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
+import libcore.io.IoUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
public class DocumentsActivity extends BaseActivity {
@@ -94,16 +101,14 @@ public class DocumentsActivity extends BaseActivity {
// In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
// talkback from reading aloud the default title, we clear it here.
setTitle("");
- new RestoreStackTask().execute();
+ new RestoreStackTask(this).execute();
} else {
refreshCurrentRootAndDirectory(ANIM_NONE);
}
}
@Override
- State buildState() {
- State state = buildDefaultState();
-
+ void includeState(State state) {
final Intent intent = getIntent();
final String action = intent.getAction();
if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
@@ -134,8 +139,6 @@ public class DocumentsActivity extends BaseActivity {
state.transferMode = intent.getIntExtra(FileOperationService.EXTRA_OPERATION,
FileOperationService.OPERATION_COPY);
}
-
- return state;
}
@Override
@@ -319,11 +322,13 @@ public class DocumentsActivity extends BaseActivity {
}
void onSaveRequested(DocumentInfo replaceTarget) {
- new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
+ new ExistingFinishTask(this, replaceTarget.derivedUri)
+ .executeOnExecutor(getExecutorForCurrentDirectory());
}
void onSaveRequested(String mimeType, String displayName) {
- new CreateFinishTask(mimeType, displayName).executeOnExecutor(getExecutorForCurrentDirectory());
+ new CreateFinishTask(this, mimeType, displayName)
+ .executeOnExecutor(getExecutorForCurrentDirectory());
}
@Override
@@ -343,7 +348,8 @@ public class DocumentsActivity extends BaseActivity {
openContainerDocument(doc);
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
// Explicit file picked, return
- new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
+ new ExistingFinishTask(this, doc.derivedUri)
+ .executeOnExecutor(getExecutorForCurrentDirectory());
} else if (mState.action == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
@@ -358,7 +364,8 @@ public class DocumentsActivity extends BaseActivity {
for (int i = 0; i < size; i++) {
uris[i] = docs.get(i).derivedUri;
}
- new ExistingFinishTask(uris).executeOnExecutor(getExecutorForCurrentDirectory());
+ new ExistingFinishTask(this, uris)
+ .executeOnExecutor(getExecutorForCurrentDirectory());
}
}
@@ -373,11 +380,10 @@ public class DocumentsActivity extends BaseActivity {
// Should not be reached.
throw new IllegalStateException("Invalid mState.action.");
}
- new PickFinishTask(result).executeOnExecutor(getExecutorForCurrentDirectory());
+ new PickFinishTask(this, result).executeOnExecutor(getExecutorForCurrentDirectory());
}
- @Override
- void saveStackBlocking() {
+ void writeStackToRecentsBlocking() {
final ContentResolver resolver = getContentResolver();
final ContentValues values = new ContentValues();
@@ -438,69 +444,138 @@ public class DocumentsActivity extends BaseActivity {
finish();
}
+
public static DocumentsActivity get(Fragment fragment) {
return (DocumentsActivity) fragment.getActivity();
}
- private final class PickFinishTask extends AsyncTask<Void, Void, Void> {
+ /**
+ * Restores the stack from Recents for the specified package.
+ */
+ private static final class RestoreStackTask
+ extends PairedTask<DocumentsActivity, Void, Void> {
+
+ private volatile boolean mRestoredStack;
+ private volatile boolean mExternal;
+ private Context mContext;
+ private State mState;
+
+ public RestoreStackTask(DocumentsActivity activity) {
+ super(activity);
+ mState = activity.mState;
+ }
+
+ @Override
+ protected Void run(Void... params) {
+ if (DEBUG && !mState.stack.isEmpty()) {
+ Log.w(TAG, "Overwriting existing stack.");
+ }
+ RootsCache roots = DocumentsApplication.getRootsCache(mContext);
+
+ String packageName = mOwner.getCallingPackageMaybeExtra();
+ Uri resumeUri = RecentsProvider.buildResume(packageName);
+ Cursor cursor = mOwner.getContentResolver().query(resumeUri, null, null, null, null);
+ try {
+ if (cursor.moveToFirst()) {
+ mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
+ final byte[] rawStack = cursor.getBlob(
+ cursor.getColumnIndex(ResumeColumns.STACK));
+ DurableUtils.readFromArray(rawStack, mState.stack);
+ mRestoredStack = true;
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to resume: " + e);
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ }
+
+ if (mRestoredStack) {
+ // Update the restored stack to ensure we have freshest data
+ final Collection<RootInfo> matchingRoots = roots.getMatchingRootsBlocking(mState);
+ try {
+ mState.stack.updateRoot(matchingRoots);
+ mState.stack.updateDocuments(mOwner.getContentResolver());
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Failed to restore stack for package: " + packageName
+ + " because of error: "+ e);
+ mState.stack.reset();
+ mRestoredStack = false;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void finish(Void result) {
+ mState.restored = true;
+ mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
+ mOwner.onStackRestored(mRestoredStack, mExternal);
+ }
+ }
+
+ private static final class PickFinishTask extends PairedTask<DocumentsActivity, Void, Void> {
private final Uri mUri;
- public PickFinishTask(Uri uri) {
+ public PickFinishTask(DocumentsActivity activity, Uri uri) {
+ super(activity);
mUri = uri;
}
@Override
- protected Void doInBackground(Void... params) {
- saveStackBlocking();
+ protected Void run(Void... params) {
+ mOwner.writeStackToRecentsBlocking();
return null;
}
@Override
- protected void onPostExecute(Void result) {
- onTaskFinished(mUri);
+ protected void finish(Void result) {
+ mOwner.onTaskFinished(mUri);
}
}
- final class ExistingFinishTask extends AsyncTask<Void, Void, Void> {
+ private static final class ExistingFinishTask extends PairedTask<DocumentsActivity, Void, Void> {
private final Uri[] mUris;
- public ExistingFinishTask(Uri... uris) {
+ public ExistingFinishTask(DocumentsActivity activity, Uri... uris) {
+ super(activity);
mUris = uris;
}
@Override
- protected Void doInBackground(Void... params) {
- saveStackBlocking();
+ protected Void run(Void... params) {
+ mOwner.writeStackToRecentsBlocking();
return null;
}
@Override
- protected void onPostExecute(Void result) {
- onTaskFinished(mUris);
+ protected void finish(Void result) {
+ mOwner.onTaskFinished(mUris);
}
}
/**
* Task that creates a new document in the background.
*/
- final class CreateFinishTask extends AsyncTask<Void, Void, Uri> {
+ private static final class CreateFinishTask extends PairedTask<DocumentsActivity, Void, Uri> {
private final String mMimeType;
private final String mDisplayName;
- public CreateFinishTask(String mimeType, String displayName) {
+ public CreateFinishTask(DocumentsActivity activity, String mimeType, String displayName) {
+ super(activity);
mMimeType = mimeType;
mDisplayName = displayName;
}
@Override
- protected void onPreExecute() {
- setPending(true);
+ protected void prepare() {
+ mOwner.setPending(true);
}
@Override
- protected Uri doInBackground(Void... params) {
- final ContentResolver resolver = getContentResolver();
- final DocumentInfo cwd = getCurrentDirectory();
+ protected Uri run(Void... params) {
+ final ContentResolver resolver = mOwner.getContentResolver();
+ final DocumentInfo cwd = mOwner.getCurrentDirectory();
ContentProviderClient client = null;
Uri childUri = null;
@@ -516,22 +591,22 @@ public class DocumentsActivity extends BaseActivity {
}
if (childUri != null) {
- saveStackBlocking();
+ mOwner.writeStackToRecentsBlocking();
}
return childUri;
}
@Override
- protected void onPostExecute(Uri result) {
+ protected void finish(Uri result) {
if (result != null) {
- onTaskFinished(result);
+ mOwner.onTaskFinished(result);
} else {
Snackbars.makeSnackbar(
- DocumentsActivity.this, R.string.save_error, Snackbar.LENGTH_SHORT).show();
+ mOwner, R.string.save_error, Snackbar.LENGTH_SHORT).show();
}
- setPending(false);
+ mOwner.setPending(false);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
index 89be9107e077..dae4bf7418df 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
@@ -24,8 +24,6 @@ import android.app.Fragment;
import android.app.FragmentManager;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
-import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -37,10 +35,8 @@ import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toolbar;
-import com.android.documentsui.RecentsProvider.ResumeColumns;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.model.DocumentInfo;
-import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
import com.android.internal.util.Preconditions;
@@ -72,23 +68,19 @@ public class DownloadsActivity extends BaseActivity {
// talkback from reading aloud the default title, we clear it here.
setTitle("");
final Uri rootUri = getIntent().getData();
- new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
+ new RestoreRootTask(this, rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
} else {
refreshCurrentRootAndDirectory(ANIM_NONE);
}
}
@Override
- State buildState() {
- State state = buildDefaultState();
-
+ void includeState(State state) {
state.action = ACTION_MANAGE;
state.acceptMimes = new String[] { "*/*" };
state.allowMultiple = true;
state.showSize = true;
state.excludedAuthorities = getExcludedAuthorities();
-
- return state;
}
@Override
@@ -170,21 +162,6 @@ public class DownloadsActivity extends BaseActivity {
public void onDocumentsPicked(List<DocumentInfo> docs) {}
@Override
- void saveStackBlocking() {
- final ContentResolver resolver = getContentResolver();
- final ContentValues values = new ContentValues();
-
- final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
-
- // Remember location for next app launch
- final String packageName = getCallingPackageMaybeExtra();
- values.clear();
- values.put(ResumeColumns.STACK, rawStack);
- values.put(ResumeColumns.EXTERNAL, 0);
- resolver.insert(RecentsProvider.buildResume(packageName), values);
- }
-
- @Override
void onTaskFinished(Uri... uris) {
Log.d(TAG, "onFinished() " + Arrays.toString(uris));
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 3aba356793df..c55f814dfef2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -30,7 +30,6 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
@@ -98,19 +97,19 @@ public class FilesActivity extends BaseActivity {
refreshCurrentRootAndDirectory(ANIM_NONE);
} else if (intent.getAction() == Intent.ACTION_VIEW) {
checkArgument(uri != null);
- new OpenUriForViewTask().executeOnExecutor(
+ new OpenUriForViewTask(this).executeOnExecutor(
ProviderExecutor.forAuthority(uri.getAuthority()), uri);
} else if (DocumentsContract.isRootUri(this, uri)) {
if (DEBUG) Log.d(TAG, "Launching with root URI.");
// If we've got a specific root to display, restore that root using a dedicated
// authority. That way a misbehaving provider won't result in an ANR.
- new RestoreRootTask(uri).executeOnExecutor(
+ new RestoreRootTask(this, uri).executeOnExecutor(
ProviderExecutor.forAuthority(uri.getAuthority()));
} else {
if (DEBUG) Log.d(TAG, "Launching into Home directory.");
// If all else fails, try to load "Home" directory.
final Uri homeUri = DocumentsContract.buildHomeUri();
- new RestoreRootTask(homeUri).executeOnExecutor(
+ new RestoreRootTask(this, homeUri).executeOnExecutor(
ProviderExecutor.forAuthority(homeUri.getAuthority()));
}
@@ -134,9 +133,7 @@ public class FilesActivity extends BaseActivity {
}
@Override
- State buildState() {
- State state = buildDefaultState();
-
+ void includeState(State state) {
final Intent intent = getIntent();
state.action = State.ACTION_BROWSE;
@@ -149,8 +146,6 @@ public class FilesActivity extends BaseActivity {
if (stack != null) {
state.stack = stack;
}
-
- return state;
}
@Override
@@ -363,13 +358,15 @@ public class FilesActivity extends BaseActivity {
}
}
- @Override
- void saveStackBlocking() {
+ // Turns out only DocumentsActivity was ever calling saveStackBlocking.
+ // There may be a case where we want to contribute entries from
+ // Behavior here in FilesActivity, but it isn't yet obvious.
+ // TODO: Contribute to recents, or remove this.
+ void writeStackToRecentsBlocking() {
final ContentResolver resolver = getContentResolver();
final ContentValues values = new ContentValues();
- final byte[] rawStack = DurableUtils.writeToArrayOrNull(
- getDisplayState().stack);
+ final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
// Remember location for next app launch
final String packageName = getCallingPackageMaybeExtra();
@@ -408,12 +405,19 @@ public class FilesActivity extends BaseActivity {
* to know which root to select. Also, the stack doesn't contain intermediate directories.
* It's primarly used for opening ZIP archives from Downloads app.
*/
- final class OpenUriForViewTask extends AsyncTask<Uri, Void, Void> {
+ private static final class OpenUriForViewTask extends PairedTask<FilesActivity, Uri, Void> {
+
+ private final State mState;
+ public OpenUriForViewTask(FilesActivity activity) {
+ super(activity);
+ mState = activity.mState;
+ }
+
@Override
- protected Void doInBackground(Uri... params) {
+ protected Void run(Uri... params) {
final Uri uri = params[0];
- final RootsCache rootsCache = DocumentsApplication.getRootsCache(FilesActivity.this);
+ final RootsCache rootsCache = DocumentsApplication.getRootsCache(mOwner);
final String authority = uri.getAuthority();
final Collection<RootInfo> roots =
@@ -426,20 +430,17 @@ public class FilesActivity extends BaseActivity {
final RootInfo root = roots.iterator().next();
mState.stack.root = root;
try {
- mState.stack.add(DocumentInfo.fromUri(getContentResolver(), uri));
+ mState.stack.add(DocumentInfo.fromUri(mOwner.getContentResolver(), uri));
} catch (FileNotFoundException e) {
Log.e(TAG, "Failed to resolve DocumentInfo from Uri: " + uri);
}
- mState.stack.add(getRootDocumentBlocking(root));
+ mState.stack.add(mOwner.getRootDocumentBlocking(root));
return null;
}
@Override
- protected void onPostExecute(Void result) {
- if (isDestroyed()) {
- return;
- }
- refreshCurrentRootAndDirectory(ANIM_NONE);
+ protected void finish(Void result) {
+ mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PairedTask.java b/packages/DocumentsUI/src/com/android/documentsui/PairedTask.java
new file mode 100644
index 000000000000..b74acb8e38c3
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/PairedTask.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.app.Activity;
+import android.os.AsyncTask;
+
+/**
+ * An {@link AsyncTask} that guards work with checks that a paired {@link Activity}
+ * is still alive. Instances of this class make no progress.
+ *
+ * <p>Use this type of task for greater safety when executing tasks that might complete
+ * after an Activity is destroyed.
+ *
+ * <p>Also useful as tasks can be static, limiting scope, but still have access to
+ * the owning class (by way the A template and the mActivity field).
+ *
+ * @template Owner Activity type.
+ * @template Input input type
+ * @template Output output type
+ */
+abstract class PairedTask<Owner extends Activity, Input, Output>
+ extends AsyncTask<Input, Void, Output> {
+
+ protected final Owner mOwner;
+
+ public PairedTask(Owner owner) {
+ mOwner = owner;
+ }
+
+ /** Called prior to run being executed. Analogous to {@link AsyncTask#onPreExecute} */
+ void prepare() {}
+
+ /** Analogous to {@link AsyncTask#doInBackground} */
+ abstract Output run(Input... input);
+
+ /** Analogous to {@link AsyncTask#onPostExecute} */
+ abstract void finish(Output output);
+
+ @Override
+ final protected void onPreExecute() {
+ if (mOwner.isDestroyed()) {
+ return;
+ }
+ prepare();
+ }
+
+ @Override
+ final protected Output doInBackground(Input... input) {
+ if (mOwner.isDestroyed()) {
+ return null;
+ }
+ return run(input);
+ }
+
+ @Override
+ final protected void onPostExecute(Output result) {
+ if (mOwner.isDestroyed()) {
+ return;
+ }
+ finish(result);
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java b/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java
new file mode 100644
index 000000000000..9048b9d45ee7
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.net.Uri;
+import android.provider.DocumentsContract;
+import android.util.Log;
+
+import com.android.documentsui.model.RootInfo;
+
+final class RestoreRootTask extends PairedTask<BaseActivity, Void, RootInfo> {
+ private static final String TAG = "RestoreRootTask";
+
+ private final Uri mRootUri;
+
+ public RestoreRootTask(BaseActivity activity, Uri rootUri) {
+ super(activity);
+ mRootUri = rootUri;
+ }
+
+ @Override
+ protected RootInfo run(Void... params) {
+ String rootId = DocumentsContract.getRootId(mRootUri);
+ return mOwner.mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
+ }
+
+ @Override
+ protected void finish(RootInfo root) {
+ mOwner.mState.restored = true;
+
+ if (root != null) {
+ mOwner.onRootPicked(root);
+ } else {
+ Log.w(TAG, "Failed to find root: " + mRootUri);
+ mOwner.finish();
+ }
+ }
+}