123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan/*
223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * Copyright (C) 2017 The Android Open Source Project
323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan *
423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * Licensed under the Apache License, Version 2.0 (the "License");
523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * you may not use this file except in compliance with the License.
623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * You may obtain a copy of the License at
723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan *
823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan *      http://www.apache.org/licenses/LICENSE-2.0
923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan *
1023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * Unless required by applicable law or agreed to in writing, software
1123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * distributed under the License is distributed on an "AS IS" BASIS,
1223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * See the License for the specific language governing permissions and
1423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * limitations under the License.
1523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan */
1623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
1723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanpackage com.android.documentsui.picker;
1823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
1923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport android.app.Activity;
2023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport android.content.ContentResolver;
2123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport android.content.ContentValues;
2223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport android.database.Cursor;
2323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport android.net.Uri;
2423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport android.util.Log;
2523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
2623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport com.android.documentsui.base.DocumentStack;
2723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport com.android.documentsui.base.Shared;
2823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport com.android.documentsui.base.State;
299bd4099ee27f8302a06fc66980079f29127318f8Jon Mannimport com.android.documentsui.roots.ProvidersAccess;
3023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
3123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport libcore.io.IoUtils;
3223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
3323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport java.io.IOException;
3423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
3523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanimport javax.annotation.Nullable;
3623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
3723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan/**
3823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan * An interface that stores the last accessed stack of the caller
3923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan */
4023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tanpublic interface LastAccessedStorage {
4123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
4223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    @Nullable DocumentStack getLastAccessed(
439bd4099ee27f8302a06fc66980079f29127318f8Jon Mann            Activity activity, ProvidersAccess providers, State state);
4423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
4523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    void setLastAccessed(Activity activity, DocumentStack stack);
4623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
4723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    void setLastAccessedToExternalApp(Activity activity);
4823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
4923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    static LastAccessedStorage create() {
5023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        return new RuntimeLastAccessedStorage();
5123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    }
5223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
5323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    class RuntimeLastAccessedStorage implements LastAccessedStorage {
5423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
5523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        private static final String TAG = "LastAccessedStorage";
5623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
5723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        private RuntimeLastAccessedStorage() {}
5823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
5923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        @Override
6023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        public @Nullable DocumentStack getLastAccessed(
619bd4099ee27f8302a06fc66980079f29127318f8Jon Mann                Activity activity, ProvidersAccess providers, State state) {
6223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            final String packageName = Shared.getCallingPackageName(activity);
6323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            final Uri resumeUri = LastAccessedProvider.buildLastAccessed(packageName);
6423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            final ContentResolver resolver = activity.getContentResolver();
6523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            Cursor cursor = resolver.query(resumeUri, null, null, null, null);
6623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            try {
6723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan                return DocumentStack.fromLastAccessedCursor(
689bd4099ee27f8302a06fc66980079f29127318f8Jon Mann                        cursor, providers.getMatchingRootsBlocking(state), resolver);
6923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            } catch (IOException e) {
7023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan                Log.w(TAG, "Failed to resume: ", e);
7123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            } finally {
7223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan                IoUtils.closeQuietly(cursor);
7323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            }
7423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
7523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            return null;
7623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        }
7723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
7823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        @Override
7923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        public void setLastAccessed(Activity activity, DocumentStack stack) {
8023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            String packageName = Shared.getCallingPackageName(activity);
8123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            LastAccessedProvider.setLastAccessed(activity.getContentResolver(), packageName, stack);
8223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        }
8323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan
8423ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        @Override
8523ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        public void setLastAccessedToExternalApp(Activity activity) {
8623ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            final String packageName = Shared.getCallingPackageName(activity);
8723ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            final ContentValues values = new ContentValues();
8823ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            values.put(LastAccessedProvider.Columns.EXTERNAL, 1);
8923ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan            activity.getContentResolver().insert(
9023ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan                    LastAccessedProvider.buildLastAccessed(packageName), values);
9123ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan        }
9223ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan    }
9323ac60cd2b1beb59b6cd760b91c7e1b1f7e8fe49Garfield Tan}
94