Remove RecentsCreateFragment, rename RecentsProvider.
RecentsProvider was poorly named, given that it has nothing to do with
"Recents" root. I renamed it so, although a bit wordy, at least decouple
any assumptions of its relationship with Recents root.
Also stripped out RecentsCreateFragment, and now make
CREATE/OPEN_TREE/PICK_COPY_DESTINATION open to default root if last
accessed directory does not exist.
Finally, reverted ag/875528 because I don't think that applies anymore.
Bug: 27307743
Change-Id: I83ed9cc45308f881a58f02beb95922f9b79b3658
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 25b609b..206f9fc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -96,8 +96,8 @@
</activity>
<provider
- android:name=".RecentsProvider"
- android:authorities="com.android.documentsui.recents"
+ android:name=".LastAccessedProvider"
+ android:authorities="com.android.documentsui.lastAccessed"
android:exported="false"/>
<receiver android:name=".PackageReceiver">
diff --git a/src/com/android/documentsui/DocumentsActivity.java b/src/com/android/documentsui/DocumentsActivity.java
index 8f9c787..555fbde 100644
--- a/src/com/android/documentsui/DocumentsActivity.java
+++ b/src/com/android/documentsui/DocumentsActivity.java
@@ -33,7 +33,6 @@
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.ResolveInfo;
-import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
@@ -43,25 +42,16 @@
import android.view.Menu;
import com.android.documentsui.MenuManager.DirectoryDetails;
-import com.android.documentsui.RecentsProvider.RecentColumns;
-import com.android.documentsui.RecentsProvider.ResumeColumns;
-import com.android.documentsui.dirlist.AnimationView;
+import com.android.documentsui.LastAccessedProvider.Columns;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.dirlist.FragmentTuner;
import com.android.documentsui.dirlist.FragmentTuner.DocumentsTuner;
import com.android.documentsui.dirlist.Model;
import com.android.documentsui.model.DocumentInfo;
-import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
-import com.android.documentsui.sorting.SortController;
-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 {
@@ -118,7 +108,7 @@
loadRoot(getDefaultRoot());
} else {
if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
- new LoadLastUsedStackTask(this).execute();
+ new LoadLastAccessedStackTask(this).execute();
}
}
}
@@ -180,8 +170,8 @@
// Remember that we last picked via external app
final String packageName = getCallingPackageMaybeExtra();
final ContentValues values = new ContentValues();
- values.put(ResumeColumns.EXTERNAL, 1);
- getContentResolver().insert(RecentsProvider.buildResume(packageName), values);
+ values.put(Columns.EXTERNAL, 1);
+ getContentResolver().insert(LastAccessedProvider.buildLastAccessed(packageName), values);
// Pass back result to original caller
setResult(resultCode, data);
@@ -242,9 +232,8 @@
if (cwd == null) {
// No directory means recents
if (mState.action == ACTION_CREATE ||
- mState.action == ACTION_OPEN_TREE ||
mState.action == ACTION_PICK_COPY_DESTINATION) {
- RecentsCreateFragment.show(fm);
+ loadRoot(getDefaultRoot());
} else {
DirectoryFragment.showRecentsOpen(fm, anim);
@@ -336,27 +325,9 @@
new PickFinishTask(this, result).executeOnExecutor(getExecutorForCurrentDirectory());
}
- void writeStackToRecentsBlocking() {
- final ContentResolver resolver = getContentResolver();
- final ContentValues values = new ContentValues();
-
- final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
- if (mState.action == ACTION_CREATE ||
- mState.action == ACTION_OPEN_TREE ||
- mState.action == ACTION_PICK_COPY_DESTINATION) {
- // Remember stack for last create
- values.clear();
- values.put(RecentColumns.KEY, mState.stack.buildKey());
- values.put(RecentColumns.STACK, rawStack);
- resolver.insert(RecentsProvider.buildRecent(), values);
- }
-
- // 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);
+ void updateLastAccessed() {
+ LastAccessedProvider.setLastAccessed(
+ getContentResolver(), getCallingPackageMaybeExtra(), mState.stack);
}
@Override
@@ -419,73 +390,6 @@
return mDetails;
}
- /**
- * Loads the last used path (stack) from Recents (history).
- * The path selected is based on the calling package name. So the last
- * path for an app like Gmail can be different than the last path
- * for an app like DropBox.
- */
- private static final class LoadLastUsedStackTask
- extends PairedTask<DocumentsActivity, Void, Void> {
-
- private volatile boolean mRestoredStack;
- private volatile boolean mExternal;
- private State mState;
-
- public LoadLastUsedStackTask(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(mOwner);
-
- 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;
- mState.external = mExternal;
- mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
- }
- }
-
private static final class PickFinishTask extends PairedTask<DocumentsActivity, Void, Void> {
private final Uri mUri;
@@ -496,7 +400,7 @@
@Override
protected Void run(Void... params) {
- mOwner.writeStackToRecentsBlocking();
+ mOwner.updateLastAccessed();
return null;
}
@@ -516,7 +420,7 @@
@Override
protected Void run(Void... params) {
- mOwner.writeStackToRecentsBlocking();
+ mOwner.updateLastAccessed();
return null;
}
@@ -563,7 +467,7 @@
}
if (childUri != null) {
- mOwner.writeStackToRecentsBlocking();
+ mOwner.updateLastAccessed();
}
return childUri;
diff --git a/src/com/android/documentsui/FilesActivity.java b/src/com/android/documentsui/FilesActivity.java
index 46a663c..c059db1 100644
--- a/src/com/android/documentsui/FilesActivity.java
+++ b/src/com/android/documentsui/FilesActivity.java
@@ -23,8 +23,6 @@
import android.app.FragmentManager;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
-import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -38,7 +36,6 @@
import com.android.documentsui.MenuManager.DirectoryDetails;
import com.android.documentsui.OperationDialogFragment.DialogType;
-import com.android.documentsui.RecentsProvider.ResumeColumns;
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.dirlist.AnimationView;
import com.android.documentsui.dirlist.DirectoryFragment;
@@ -47,7 +44,6 @@
import com.android.documentsui.dirlist.Model;
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.documentsui.services.FileOperationService;
@@ -439,24 +435,6 @@
return false;
}
- // 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(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) {
if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
diff --git a/src/com/android/documentsui/LastAccessedProvider.java b/src/com/android/documentsui/LastAccessedProvider.java
new file mode 100644
index 0000000..ba818cb
--- /dev/null
+++ b/src/com/android/documentsui/LastAccessedProvider.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2013 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 static com.android.documentsui.model.DocumentInfo.getCursorString;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.UriMatcher;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.util.Log;
+
+import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.DurableUtils;
+import com.android.internal.util.Predicate;
+
+import com.google.android.collect.Sets;
+
+import libcore.io.IoUtils;
+
+import java.io.IOException;
+import java.util.Set;
+
+/*
+ * Provider used to keep track of the last known directory navigation trail done by the user
+ */
+public class LastAccessedProvider extends ContentProvider {
+ private static final String TAG = "LastAccessedProvider";
+
+
+ private static final String AUTHORITY = "com.android.documentsui.lastAccessed";
+
+ private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ private static final int URI_LAST_ACCESSED = 1;
+
+ public static final String METHOD_PURGE = "purge";
+ public static final String METHOD_PURGE_PACKAGE = "purgePackage";
+
+ static {
+ sMatcher.addURI(AUTHORITY, "lastAccessed/*", URI_LAST_ACCESSED);
+ }
+
+ public static final String TABLE_LAST_ACCESSED = "lastAccessed";
+
+ public static class Columns {
+ public static final String PACKAGE_NAME = "package_name";
+ public static final String STACK = "stack";
+ public static final String TIMESTAMP = "timestamp";
+ // Indicates handler was an external app, like photos.
+ public static final String EXTERNAL = "external";
+ }
+
+ public static Uri buildLastAccessed(String packageName) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY).appendPath("lastAccessed").appendPath(packageName).build();
+ }
+
+ private DatabaseHelper mHelper;
+
+ private static class DatabaseHelper extends SQLiteOpenHelper {
+ private static final String DB_NAME = "lastAccess.db";
+
+ // Used for backwards compatibility
+ private static final int VERSION_INIT = 1;
+ private static final int VERSION_AS_BLOB = 3;
+ private static final int VERSION_ADD_EXTERNAL = 4;
+ private static final int VERSION_ADD_RECENT_KEY = 5;
+
+ private static final int VERSION_LAST_ACCESS_REFACTOR = 6;
+
+ public DatabaseHelper(Context context) {
+ super(context, DB_NAME, null, VERSION_LAST_ACCESS_REFACTOR);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+
+ db.execSQL("CREATE TABLE " + TABLE_LAST_ACCESSED + " (" +
+ Columns.PACKAGE_NAME + " TEXT NOT NULL PRIMARY KEY," +
+ Columns.STACK + " BLOB DEFAULT NULL," +
+ Columns.TIMESTAMP + " INTEGER," +
+ Columns.EXTERNAL + " INTEGER NOT NULL DEFAULT 0" +
+ ")");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.w(TAG, "Upgrading database; wiping app data");
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_LAST_ACCESSED);
+ onCreate(db);
+ }
+ }
+
+ public static void setLastAccessed(
+ ContentResolver resolver, String packageName, DocumentStack stack) {
+ final ContentValues values = new ContentValues();
+ final byte[] rawStack = DurableUtils.writeToArrayOrNull(stack);
+ values.clear();
+ values.put(Columns.STACK, rawStack);
+ values.put(Columns.EXTERNAL, 0);
+ resolver.insert(buildLastAccessed(packageName), values);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ if (sMatcher.match(uri) != URI_LAST_ACCESSED) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ final SQLiteDatabase db = mHelper.getReadableDatabase();
+ final String packageName = uri.getPathSegments().get(1);
+ return db.query(TABLE_LAST_ACCESSED, projection, Columns.PACKAGE_NAME + "=?",
+ new String[] { packageName }, null, null, sortOrder);
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ if (sMatcher.match(uri) != URI_LAST_ACCESSED) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ final SQLiteDatabase db = mHelper.getWritableDatabase();
+ final ContentValues key = new ContentValues();
+
+ values.put(Columns.TIMESTAMP, System.currentTimeMillis());
+
+ final String packageName = uri.getPathSegments().get(1);
+ key.put(Columns.PACKAGE_NAME, packageName);
+
+ // Ensure that row exists, then update with changed values
+ db.insertWithOnConflict(TABLE_LAST_ACCESSED, null, key, SQLiteDatabase.CONFLICT_IGNORE);
+ db.update(TABLE_LAST_ACCESSED, values, Columns.PACKAGE_NAME + "=?",
+ new String[] { packageName });
+ return uri;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ if (METHOD_PURGE.equals(method)) {
+ // Purge references to unknown authorities
+ final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+ final Set<String> knownAuth = Sets.newHashSet();
+ for (ResolveInfo info : getContext()
+ .getPackageManager().queryIntentContentProviders(intent, 0)) {
+ knownAuth.add(info.providerInfo.authority);
+ }
+
+ purgeByAuthority(new Predicate<String>() {
+ @Override
+ public boolean apply(String authority) {
+ // Purge unknown authorities
+ return !knownAuth.contains(authority);
+ }
+ });
+
+ return null;
+
+ } else if (METHOD_PURGE_PACKAGE.equals(method)) {
+ // Purge references to authorities in given package
+ final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+ intent.setPackage(arg);
+ final Set<String> packageAuth = Sets.newHashSet();
+ for (ResolveInfo info : getContext()
+ .getPackageManager().queryIntentContentProviders(intent, 0)) {
+ packageAuth.add(info.providerInfo.authority);
+ }
+
+ if (!packageAuth.isEmpty()) {
+ purgeByAuthority(new Predicate<String>() {
+ @Override
+ public boolean apply(String authority) {
+ // Purge authority matches
+ return packageAuth.contains(authority);
+ }
+ });
+ }
+
+ return null;
+
+ } else {
+ return super.call(method, arg, extras);
+ }
+ }
+
+ /**
+ * Purge all internal data whose authority matches the given
+ * {@link Predicate}.
+ */
+ private void purgeByAuthority(Predicate<String> predicate) {
+ final SQLiteDatabase db = mHelper.getWritableDatabase();
+ final DocumentStack stack = new DocumentStack();
+
+ Cursor cursor = db.query(TABLE_LAST_ACCESSED, null, null, null, null, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ try {
+ final byte[] rawStack = cursor.getBlob(
+ cursor.getColumnIndex(Columns.STACK));
+ DurableUtils.readFromArray(rawStack, stack);
+
+ if (stack.root != null && predicate.apply(stack.root.authority)) {
+ final String packageName = getCursorString(
+ cursor, Columns.PACKAGE_NAME);
+ db.delete(TABLE_LAST_ACCESSED, Columns.PACKAGE_NAME + "=?",
+ new String[] { packageName });
+ }
+ } catch (IOException ignored) {
+ }
+ }
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ }
+ }
+}
diff --git a/src/com/android/documentsui/LoadLastAccessedStackTask.java b/src/com/android/documentsui/LoadLastAccessedStackTask.java
new file mode 100644
index 0000000..78e79c7
--- /dev/null
+++ b/src/com/android/documentsui/LoadLastAccessedStackTask.java
@@ -0,0 +1,102 @@
+/*
+ * 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 static com.android.documentsui.Shared.DEBUG;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.documentsui.LastAccessedProvider.Columns;
+import com.android.documentsui.dirlist.AnimationView;
+import com.android.documentsui.model.DurableUtils;
+import com.android.documentsui.model.RootInfo;
+
+import libcore.io.IoUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Loads the last used path (stack) from Recents (history).
+ * The path selected is based on the calling package name. So the last
+ * path for an app like Gmail can be different than the last path
+ * for an app like DropBox.
+ */
+final class LoadLastAccessedStackTask
+ extends PairedTask<DocumentsActivity, Void, Void> {
+
+ private static final String TAG = "LoadLastAccessedStackTask";
+ private volatile boolean mRestoredStack;
+ private volatile boolean mExternal;
+ private State mState;
+
+ public LoadLastAccessedStackTask(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(mOwner);
+
+ String packageName = mOwner.getCallingPackageMaybeExtra();
+ Uri resumeUri = LastAccessedProvider.buildLastAccessed(packageName);
+ Cursor cursor = mOwner.getContentResolver().query(resumeUri, null, null, null, null);
+ try {
+ if (cursor.moveToFirst()) {
+ mExternal = cursor.getInt(cursor.getColumnIndex(Columns.EXTERNAL)) != 0;
+ final byte[] rawStack = cursor.getBlob(
+ cursor.getColumnIndex(Columns.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 = mRestoredStack;
+ mState.external = mExternal;
+ mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/documentsui/PackageReceiver.java b/src/com/android/documentsui/PackageReceiver.java
index b5c7c87..8789171 100644
--- a/src/com/android/documentsui/PackageReceiver.java
+++ b/src/com/android/documentsui/PackageReceiver.java
@@ -23,7 +23,7 @@
import android.net.Uri;
/**
- * Clean up {@link RecentsProvider} and {@link LocalPreferences} when packages are removed.
+ * Clean up {@link LastAccessedProvider} and {@link LocalPreferences} when packages are removed.
*/
public class PackageReceiver extends BroadcastReceiver {
@Override
@@ -35,13 +35,19 @@
final String packageName = data == null ? null : data.getSchemeSpecificPart();
if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
- resolver.call(RecentsProvider.buildRecent(), RecentsProvider.METHOD_PURGE, null, null);
+ resolver.call(
+ LastAccessedProvider.buildLastAccessed(packageName),
+ LastAccessedProvider.METHOD_PURGE,
+ null,
+ null);
if (packageName != null) {
LocalPreferences.clearPackagePreferences(context, packageName);
}
} else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
if (packageName != null) {
- resolver.call(RecentsProvider.buildRecent(), RecentsProvider.METHOD_PURGE_PACKAGE,
+ resolver.call(
+ LastAccessedProvider.buildLastAccessed(packageName),
+ LastAccessedProvider.METHOD_PURGE_PACKAGE,
packageName, null);
LocalPreferences.clearPackagePreferences(context, packageName);
}
diff --git a/src/com/android/documentsui/RecentsCreateFragment.java b/src/com/android/documentsui/RecentsCreateFragment.java
deleted file mode 100644
index 019ca86..0000000
--- a/src/com/android/documentsui/RecentsCreateFragment.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2013 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 static com.android.documentsui.Shared.TAG;
-import static com.android.documentsui.State.ACTION_CREATE;
-
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Loader;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.TextUtils.TruncateAt;
-import android.text.style.ImageSpan;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.documentsui.Events.MotionInputEvent;
-import com.android.documentsui.RecentsProvider.RecentColumns;
-import com.android.documentsui.model.DocumentStack;
-import com.android.documentsui.model.DurableUtils;
-import com.android.documentsui.model.RootInfo;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import libcore.io.IoUtils;
-
-/**
- * Display directories where recent creates took place.
- */
-public class RecentsCreateFragment extends Fragment {
-
- private View mEmptyView;
- private RecyclerView mRecView;
- private DocumentStackAdapter mAdapter;
- private LoaderCallbacks<List<DocumentStack>> mCallbacks;
-
- private static final int LOADER_RECENTS = 3;
-
- public static void show(FragmentManager fm) {
- final RecentsCreateFragment fragment = new RecentsCreateFragment();
- final FragmentTransaction ft = fm.beginTransaction();
- ft.replace(R.id.container_directory, fragment);
- ft.commitAllowingStateLoss();
- }
-
- @Override
- public View onCreateView(
- LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final Context context = inflater.getContext();
-
- final View view = inflater.inflate(R.layout.fragment_directory, container, false);
-
- mRecView = (RecyclerView) view.findViewById(R.id.dir_list);
- mRecView.setLayoutManager(new LinearLayoutManager(getContext()));
- mRecView.addOnItemTouchListener(mItemListener);
-
- mEmptyView = view.findViewById(android.R.id.empty);
-
- mAdapter = new DocumentStackAdapter();
- mRecView.setAdapter(mAdapter);
-
- final RootsCache roots = DocumentsApplication.getRootsCache(context);
- final State state = ((BaseActivity) getActivity()).getDisplayState();
-
- mCallbacks = new LoaderCallbacks<List<DocumentStack>>() {
- @Override
- public Loader<List<DocumentStack>> onCreateLoader(int id, Bundle args) {
- return new RecentsCreateLoader(context, roots, state);
- }
-
- @Override
- public void onLoadFinished(
- Loader<List<DocumentStack>> loader, List<DocumentStack> data) {
- mAdapter.update(data);
-
- // When launched into empty recents, show drawer
- if (mAdapter.isEmpty() && !state.hasLocationChanged()
- && state.action != ACTION_CREATE
- && context instanceof DocumentsActivity) {
- ((DocumentsActivity) context).setRootsDrawerOpen(true);
- }
- }
-
- @Override
- public void onLoaderReset(Loader<List<DocumentStack>> loader) {
- mAdapter.update(null);
- }
- };
-
- return view;
- }
-
- @Override
- public void onStart() {
- super.onStart();
- getLoaderManager().restartLoader(LOADER_RECENTS, getArguments(), mCallbacks);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- getLoaderManager().destroyLoader(LOADER_RECENTS);
- }
-
- private RecyclerView.OnItemTouchListener mItemListener =
- new RecyclerView.OnItemTouchListener() {
- @Override
- public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
- try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
- if (event.isOverItem() && event.isActionUp()) {
- final DocumentStack stack = mAdapter.getItem(event.getItemPosition());
- ((BaseActivity) getActivity()).onStackPicked(stack);
- return true;
- }
- return false;
- }
- }
-
- @Override
- public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
- @Override
- public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
- };
-
- public static class RecentsCreateLoader extends UriDerivativeLoader<Uri, List<DocumentStack>> {
- private final RootsCache mRoots;
- private final State mState;
-
- public RecentsCreateLoader(Context context, RootsCache roots, State state) {
- super(context, RecentsProvider.buildRecent());
- mRoots = roots;
- mState = state;
- }
-
- @Override
- public List<DocumentStack> loadInBackground(Uri uri, CancellationSignal signal) {
- final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
- final ArrayList<DocumentStack> result = new ArrayList<>();
-
- final ContentResolver resolver = getContext().getContentResolver();
- final Cursor cursor = resolver.query(
- uri, null, null, null, RecentColumns.TIMESTAMP + " DESC", signal);
- try {
- while (cursor != null && cursor.moveToNext()) {
- final byte[] rawStack = cursor.getBlob(
- cursor.getColumnIndex(RecentColumns.STACK));
- try {
- final DocumentStack stack = new DocumentStack();
- DurableUtils.readFromArray(rawStack, stack);
-
- // Only update root here to avoid spinning up all
- // providers; we update the stack during the actual
- // restore. This also filters away roots that don't
- // match current filter.
- stack.updateRoot(matchingRoots);
- result.add(stack);
- } catch (IOException e) {
- Log.w(TAG, "Failed to resolve stack: " + e);
- }
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
-
- return result;
- }
- }
-
- private static final class StackHolder extends RecyclerView.ViewHolder {
- public View view;
- public StackHolder(View view) {
- super(view);
- this.view = view;
- }
- }
-
- private class DocumentStackAdapter extends RecyclerView.Adapter<StackHolder> {
- @Nullable private List<DocumentStack> mItems;
-
- DocumentStack getItem(int position) {
- return mItems.get(position);
- }
-
- @Override
- public int getItemCount() {
- return mItems == null ? 0 : mItems.size();
- }
-
- boolean isEmpty() {
- return mItems == null ? true : mItems.isEmpty();
- }
-
- void update(@Nullable List<DocumentStack> items) {
- mItems = items;
-
- if (isEmpty()) {
- mEmptyView.setVisibility(View.VISIBLE);
- } else {
- mEmptyView.setVisibility(View.GONE);
- }
-
- notifyDataSetChanged();
- }
-
- @Override
- public StackHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- final Context context = parent.getContext();
-
- final LayoutInflater inflater = LayoutInflater.from(context);
- return new StackHolder(
- inflater.inflate(R.layout.item_doc_list, parent, false));
- }
-
- @Override
- public void onBindViewHolder(StackHolder holder, int position) {
- Context context = getContext();
- View view = holder.view;
-
- final ImageView iconMime = (ImageView) view.findViewById(R.id.icon_mime);
- final TextView title = (TextView) view.findViewById(android.R.id.title);
- final View line2 = view.findViewById(R.id.line2);
-
- final DocumentStack stack = getItem(position);
- iconMime.setImageDrawable(stack.root.loadIcon(context));
-
- final Drawable crumb = context.getDrawable(R.drawable.ic_breadcrumb_arrow);
- crumb.setBounds(0, 0, crumb.getIntrinsicWidth(), crumb.getIntrinsicHeight());
-
- final SpannableStringBuilder builder = new SpannableStringBuilder();
- builder.append(stack.root.title);
- for (int i = stack.size() - 2; i >= 0; i--) {
- appendDrawable(builder, crumb);
- builder.append(stack.get(i).displayName);
- }
- title.setText(builder);
- title.setEllipsize(TruncateAt.MIDDLE);
-
- if (line2 != null) line2.setVisibility(View.GONE);
- }
- }
-
- private static void appendDrawable(SpannableStringBuilder b, Drawable d) {
- final int length = b.length();
- b.append("\u232a");
- b.setSpan(new ImageSpan(d), length, b.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-}
diff --git a/src/com/android/documentsui/RecentsProvider.java b/src/com/android/documentsui/RecentsProvider.java
deleted file mode 100644
index 6ef9154..0000000
--- a/src/com/android/documentsui/RecentsProvider.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2013 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 static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.model.DocumentInfo.getCursorString;
-
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.UriMatcher;
-import android.content.pm.ResolveInfo;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-import android.text.format.DateUtils;
-import android.util.Log;
-
-import com.android.documentsui.model.DocumentStack;
-import com.android.documentsui.model.DurableUtils;
-import com.android.internal.util.Predicate;
-
-import com.google.android.collect.Sets;
-
-import libcore.io.IoUtils;
-
-import java.io.IOException;
-import java.util.Set;
-
-public class RecentsProvider extends ContentProvider {
- private static final String TAG = "RecentsProvider";
-
- private static final long MAX_HISTORY_IN_MILLIS = 45 * DateUtils.DAY_IN_MILLIS;
-
- private static final String AUTHORITY = "com.android.documentsui.recents";
-
- private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-
- private static final int URI_RECENT = 1;
- private static final int URI_STATE = 2;
- private static final int URI_RESUME = 3;
-
- public static final String METHOD_PURGE = "purge";
- public static final String METHOD_PURGE_PACKAGE = "purgePackage";
-
- static {
- sMatcher.addURI(AUTHORITY, "recent", URI_RECENT);
- // state/authority/rootId/docId
- sMatcher.addURI(AUTHORITY, "state/*/*/*", URI_STATE);
- // resume/packageName
- sMatcher.addURI(AUTHORITY, "resume/*", URI_RESUME);
- }
-
- public static final String TABLE_RECENT = "recent";
- public static final String TABLE_STATE = "state";
- public static final String TABLE_RESUME = "resume";
-
- public static class RecentColumns {
- public static final String KEY = "key";
- public static final String STACK = "stack";
- public static final String TIMESTAMP = "timestamp";
- }
-
- public static class StateColumns {
- public static final String AUTHORITY = "authority";
- public static final String ROOT_ID = Root.COLUMN_ROOT_ID;
- public static final String DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID;
-
- @Deprecated // mode is tracked in local preferences now...by root only
- public static final String MODE = "mode";
- public static final String SORT_ORDER = "sortOrder";
- }
-
- public static class ResumeColumns {
- public static final String PACKAGE_NAME = "package_name";
- public static final String STACK = "stack";
- public static final String TIMESTAMP = "timestamp";
- // Indicates handler was an external app, like photos.
- public static final String EXTERNAL = "external";
- }
-
- public static Uri buildRecent() {
- return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
- .authority(AUTHORITY).appendPath("recent").build();
- }
-
- public static Uri buildState(String authority, String rootId, String documentId) {
- return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
- .appendPath("state").appendPath(authority).appendPath(rootId).appendPath(documentId)
- .build();
- }
-
- public static Uri buildResume(String packageName) {
- return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
- .authority(AUTHORITY).appendPath("resume").appendPath(packageName).build();
- }
-
- private DatabaseHelper mHelper;
-
- private static class DatabaseHelper extends SQLiteOpenHelper {
- private static final String DB_NAME = "recents.db";
-
- private static final int VERSION_INIT = 1;
- private static final int VERSION_AS_BLOB = 3;
- private static final int VERSION_ADD_EXTERNAL = 4;
- private static final int VERSION_ADD_RECENT_KEY = 5;
-
- public DatabaseHelper(Context context) {
- super(context, DB_NAME, null, VERSION_ADD_RECENT_KEY);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
-
- db.execSQL("CREATE TABLE " + TABLE_RECENT + " (" +
- RecentColumns.KEY + " TEXT PRIMARY KEY ON CONFLICT REPLACE," +
- RecentColumns.STACK + " BLOB DEFAULT NULL," +
- RecentColumns.TIMESTAMP + " INTEGER" +
- ")");
-
- db.execSQL("CREATE TABLE " + TABLE_STATE + " (" +
- StateColumns.AUTHORITY + " TEXT," +
- StateColumns.ROOT_ID + " TEXT," +
- StateColumns.DOCUMENT_ID + " TEXT," +
- StateColumns.MODE + " INTEGER," +
- StateColumns.SORT_ORDER + " INTEGER," +
- "PRIMARY KEY (" + StateColumns.AUTHORITY + ", " + StateColumns.ROOT_ID + ", "
- + StateColumns.DOCUMENT_ID + ")" +
- ")");
-
- db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" +
- ResumeColumns.PACKAGE_NAME + " TEXT NOT NULL PRIMARY KEY," +
- ResumeColumns.STACK + " BLOB DEFAULT NULL," +
- ResumeColumns.TIMESTAMP + " INTEGER," +
- ResumeColumns.EXTERNAL + " INTEGER NOT NULL DEFAULT 0" +
- ")");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- Log.w(TAG, "Upgrading database; wiping app data");
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECENT);
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_STATE);
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_RESUME);
- onCreate(db);
- }
- }
-
- @Override
- public boolean onCreate() {
- mHelper = new DatabaseHelper(getContext());
- return true;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- final SQLiteDatabase db = mHelper.getReadableDatabase();
- switch (sMatcher.match(uri)) {
- case URI_RECENT:
- final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
- return db.query(TABLE_RECENT, projection, RecentColumns.TIMESTAMP + ">" + cutoff,
- null, null, null, sortOrder);
- case URI_STATE:
- final String authority = uri.getPathSegments().get(1);
- final String rootId = uri.getPathSegments().get(2);
- final String documentId = uri.getPathSegments().get(3);
- return db.query(TABLE_STATE, projection, StateColumns.AUTHORITY + "=? AND "
- + StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
- new String[] { authority, rootId, documentId }, null, null, sortOrder);
- case URI_RESUME:
- final String packageName = uri.getPathSegments().get(1);
- return db.query(TABLE_RESUME, projection, ResumeColumns.PACKAGE_NAME + "=?",
- new String[] { packageName }, null, null, sortOrder);
- default:
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
- }
-
- @Override
- public String getType(Uri uri) {
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- final SQLiteDatabase db = mHelper.getWritableDatabase();
- final ContentValues key = new ContentValues();
- switch (sMatcher.match(uri)) {
- case URI_RECENT:
- values.put(RecentColumns.TIMESTAMP, System.currentTimeMillis());
- db.insert(TABLE_RECENT, null, values);
- final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
- db.delete(TABLE_RECENT, RecentColumns.TIMESTAMP + "<" + cutoff, null);
- return uri;
- case URI_STATE:
- final String authority = uri.getPathSegments().get(1);
- final String rootId = uri.getPathSegments().get(2);
- final String documentId = uri.getPathSegments().get(3);
-
- key.put(StateColumns.AUTHORITY, authority);
- key.put(StateColumns.ROOT_ID, rootId);
- key.put(StateColumns.DOCUMENT_ID, documentId);
-
- // Ensure that row exists, then update with changed values
- db.insertWithOnConflict(TABLE_STATE, null, key, SQLiteDatabase.CONFLICT_IGNORE);
- db.update(TABLE_STATE, values, StateColumns.AUTHORITY + "=? AND "
- + StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
- new String[] { authority, rootId, documentId });
-
- return uri;
- case URI_RESUME:
- values.put(ResumeColumns.TIMESTAMP, System.currentTimeMillis());
-
- final String packageName = uri.getPathSegments().get(1);
- key.put(ResumeColumns.PACKAGE_NAME, packageName);
-
- // Ensure that row exists, then update with changed values
- db.insertWithOnConflict(TABLE_RESUME, null, key, SQLiteDatabase.CONFLICT_IGNORE);
- db.update(TABLE_RESUME, values, ResumeColumns.PACKAGE_NAME + "=?",
- new String[] { packageName });
- return uri;
- default:
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
-
- @Override
- public Bundle call(String method, String arg, Bundle extras) {
- if (METHOD_PURGE.equals(method)) {
- // Purge references to unknown authorities
- final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
- final Set<String> knownAuth = Sets.newHashSet();
- for (ResolveInfo info : getContext()
- .getPackageManager().queryIntentContentProviders(intent, 0)) {
- knownAuth.add(info.providerInfo.authority);
- }
-
- purgeByAuthority(new Predicate<String>() {
- @Override
- public boolean apply(String authority) {
- // Purge unknown authorities
- return !knownAuth.contains(authority);
- }
- });
-
- return null;
-
- } else if (METHOD_PURGE_PACKAGE.equals(method)) {
- // Purge references to authorities in given package
- final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
- intent.setPackage(arg);
- final Set<String> packageAuth = Sets.newHashSet();
- for (ResolveInfo info : getContext()
- .getPackageManager().queryIntentContentProviders(intent, 0)) {
- packageAuth.add(info.providerInfo.authority);
- }
-
- if (!packageAuth.isEmpty()) {
- purgeByAuthority(new Predicate<String>() {
- @Override
- public boolean apply(String authority) {
- // Purge authority matches
- return packageAuth.contains(authority);
- }
- });
- }
-
- return null;
-
- } else {
- return super.call(method, arg, extras);
- }
- }
-
- /**
- * Purge all internal data whose authority matches the given
- * {@link Predicate}.
- */
- private void purgeByAuthority(Predicate<String> predicate) {
- final SQLiteDatabase db = mHelper.getWritableDatabase();
- final DocumentStack stack = new DocumentStack();
-
- Cursor cursor = db.query(TABLE_RECENT, null, null, null, null, null, null);
- try {
- while (cursor.moveToNext()) {
- try {
- final byte[] rawStack = cursor.getBlob(
- cursor.getColumnIndex(RecentColumns.STACK));
- DurableUtils.readFromArray(rawStack, stack);
-
- if (stack.root != null && predicate.apply(stack.root.authority)) {
- final String key = getCursorString(cursor, RecentColumns.KEY);
- db.delete(TABLE_RECENT, RecentColumns.KEY + "=?", new String[] { key });
- }
- } catch (IOException ignored) {
- }
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
-
- cursor = db.query(TABLE_STATE, new String[] {
- StateColumns.AUTHORITY }, null, null, StateColumns.AUTHORITY, null, null);
- try {
- while (cursor.moveToNext()) {
- final String authority = getCursorString(cursor, StateColumns.AUTHORITY);
- if (predicate.apply(authority)) {
- db.delete(TABLE_STATE, StateColumns.AUTHORITY + "=?", new String[] {
- authority });
- if (DEBUG) Log.d(TAG, "Purged state for " + authority);
- }
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
-
- cursor = db.query(TABLE_RESUME, null, null, null, null, null, null);
- try {
- while (cursor.moveToNext()) {
- try {
- final byte[] rawStack = cursor.getBlob(
- cursor.getColumnIndex(ResumeColumns.STACK));
- DurableUtils.readFromArray(rawStack, stack);
-
- if (stack.root != null && predicate.apply(stack.root.authority)) {
- final String packageName = getCursorString(
- cursor, ResumeColumns.PACKAGE_NAME);
- db.delete(TABLE_RESUME, ResumeColumns.PACKAGE_NAME + "=?",
- new String[] { packageName });
- }
- } catch (IOException ignored) {
- }
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
- }
-}
diff --git a/src/com/android/documentsui/RootsCache.java b/src/com/android/documentsui/RootsCache.java
index 117bb01..e6fe31b 100644
--- a/src/com/android/documentsui/RootsCache.java
+++ b/src/com/android/documentsui/RootsCache.java
@@ -96,8 +96,7 @@
// Special root for recents
derivedIcon = R.drawable.ic_root_recent;
derivedType = RootInfo.TYPE_RECENTS;
- flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD
- | Root.FLAG_SUPPORTS_CREATE;
+ flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD;
title = mContext.getString(R.string.root_recent);
availableBytes = -1;
}};
@@ -134,9 +133,7 @@
assert(mRecentsRoot.rootId == null);
assert(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
assert(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
- assert(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY
- | Root.FLAG_SUPPORTS_IS_CHILD
- | Root.FLAG_SUPPORTS_CREATE));
+ assert(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD));
assert(mRecentsRoot.availableBytes == -1);
new UpdateTask(forceRefreshAll, null)