Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7232bf03 authored by Ben Lin's avatar Ben Lin
Browse files

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
parent 107b5f5b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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">
+11 −107
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.content.ContentResolver;
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.util.Log;
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 @@ public class DocumentsActivity extends BaseActivity {
                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 @@ public class DocumentsActivity extends BaseActivity {
            // 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 @@ public class DocumentsActivity extends BaseActivity {
        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 @@ public class DocumentsActivity extends BaseActivity {
        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 @@ public class DocumentsActivity extends BaseActivity {
        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 @@ public class DocumentsActivity extends BaseActivity {

        @Override
        protected Void run(Void... params) {
            mOwner.writeStackToRecentsBlocking();
            mOwner.updateLastAccessed();
            return null;
        }

@@ -516,7 +420,7 @@ public class DocumentsActivity extends BaseActivity {

        @Override
        protected Void run(Void... params) {
            mOwner.writeStackToRecentsBlocking();
            mOwner.updateLastAccessed();
            return null;
        }

@@ -563,7 +467,7 @@ public class DocumentsActivity extends BaseActivity {
            }

            if (childUri != null) {
                mOwner.writeStackToRecentsBlocking();
                mOwner.updateLastAccessed();
            }

            return childUri;
+0 −22
Original line number Diff line number Diff line
@@ -23,8 +23,6 @@ import android.app.Activity;
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 android.view.MenuItem;

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.FragmentTuner.FilesTuner;
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 @@ public class FilesActivity extends BaseActivity {
        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));
+260 −0
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.documentsui;

import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.model.DocumentInfo.getCursorString;

import android.content.ContentProvider;
@@ -32,9 +31,6 @@ 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;
@@ -48,51 +44,29 @@ import libcore.io.IoUtils;
import java.io.IOException;
import java.util.Set;

public class RecentsProvider extends ContentProvider {
    private static final String TAG = "RecentsProvider";
/*
 * 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 long MAX_HISTORY_IN_MILLIS = 45 * DateUtils.DAY_IN_MILLIS;

    private static final String AUTHORITY = "com.android.documentsui.recents";
    private static final String AUTHORITY = "com.android.documentsui.lastAccessed";

    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;
    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, "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";
        sMatcher.addURI(AUTHORITY, "lastAccessed/*", URI_LAST_ACCESSED);
    }

    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;
    public static final String TABLE_LAST_ACCESSED = "lastAccessed";

        @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 class Columns {
        public static final String PACKAGE_NAME = "package_name";
        public static final String STACK = "stack";
        public static final String TIMESTAMP = "timestamp";
@@ -100,73 +74,57 @@ public class RecentsProvider extends ContentProvider {
        public static final String EXTERNAL = "external";
    }

    public static Uri buildRecent() {
    public static Uri buildLastAccessed(String packageName) {
        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();
                .authority(AUTHORITY).appendPath("lastAccessed").appendPath(packageName).build();
    }

    private DatabaseHelper mHelper;

    private static class DatabaseHelper extends SQLiteOpenHelper {
        private static final String DB_NAME = "recents.db";
        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_ADD_RECENT_KEY);
            super(context, DB_NAME, null, VERSION_LAST_ACCESS_REFACTOR);
        }

        @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" +
            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_RECENT);
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_STATE);
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_RESUME);
            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());
@@ -176,26 +134,14 @@ public class RecentsProvider extends ContentProvider {
    @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();
        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 + "=?",
        return db.query(TABLE_LAST_ACCESSED, projection, Columns.PACKAGE_NAME + "=?",
                        new String[] { packageName }, null, null, sortOrder);
            default:
                throw new UnsupportedOperationException("Unsupported Uri " + uri);
        }
    }

    @Override
@@ -205,45 +151,23 @@ public class RecentsProvider extends ContentProvider {

    @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();
        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());
        values.put(Columns.TIMESTAMP, System.currentTimeMillis());

        final String packageName = uri.getPathSegments().get(1);
                key.put(ResumeColumns.PACKAGE_NAME, packageName);
        key.put(Columns.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 + "=?",
        db.insertWithOnConflict(TABLE_LAST_ACCESSED, null, key, SQLiteDatabase.CONFLICT_IGNORE);
        db.update(TABLE_LAST_ACCESSED, values, Columns.PACKAGE_NAME + "=?",
                        new String[] { packageName });
        return uri;
            default:
                throw new UnsupportedOperationException("Unsupported Uri " + uri);
        }
    }

    @Override
@@ -312,52 +236,18 @@ public class RecentsProvider extends ContentProvider {
        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);
        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(ResumeColumns.STACK));
                            cursor.getColumnIndex(Columns.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 + "=?",
                                cursor, Columns.PACKAGE_NAME);
                        db.delete(TABLE_LAST_ACCESSED, Columns.PACKAGE_NAME + "=?",
                                new String[] { packageName });
                    }
                } catch (IOException ignored) {
+102 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading