blob: df7ed4a6b77e09862be4281a45641e284cd5d767 [file] [log] [blame]
Jeff Sharkey92d7e692013-08-02 10:33:21 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.documentsui;
18
19import android.content.ContentProvider;
Jeff Sharkeydc2963a2013-08-02 15:55:26 -070020import android.content.ContentResolver;
Jeff Sharkey92d7e692013-08-02 10:33:21 -070021import android.content.ContentValues;
22import android.content.Context;
23import android.content.UriMatcher;
24import android.database.Cursor;
25import android.database.sqlite.SQLiteDatabase;
26import android.database.sqlite.SQLiteOpenHelper;
27import android.net.Uri;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070028import android.provider.DocumentsContract.Document;
29import android.provider.DocumentsContract.Root;
Jeff Sharkey92d7e692013-08-02 10:33:21 -070030import android.text.format.DateUtils;
31import android.util.Log;
32
33public class RecentsProvider extends ContentProvider {
34 private static final String TAG = "RecentsProvider";
35
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070036 public static final long MAX_HISTORY_IN_MILLIS = DateUtils.DAY_IN_MILLIS * 45;
Jeff Sharkeydc2963a2013-08-02 15:55:26 -070037
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070038 private static final String AUTHORITY = "com.android.documentsui.recents";
Jeff Sharkey92d7e692013-08-02 10:33:21 -070039
40 private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
41
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070042 private static final int URI_RECENT = 1;
43 private static final int URI_STATE = 2;
Jeff Sharkey92d7e692013-08-02 10:33:21 -070044 private static final int URI_RESUME = 3;
45
46 static {
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070047 sMatcher.addURI(AUTHORITY, "recent", URI_RECENT);
48 // state/authority/rootId/docId
49 sMatcher.addURI(AUTHORITY, "state/*/*/*", URI_STATE);
50 // resume/packageName
Jeff Sharkey92d7e692013-08-02 10:33:21 -070051 sMatcher.addURI(AUTHORITY, "resume/*", URI_RESUME);
52 }
53
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070054 public static final String TABLE_RECENT = "recent";
55 public static final String TABLE_STATE = "state";
56 public static final String TABLE_RESUME = "resume";
Jeff Sharkey92d7e692013-08-02 10:33:21 -070057
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070058 public static class RecentColumns {
59 public static final String STACK = "stack";
60 public static final String TIMESTAMP = "timestamp";
Jeff Sharkeydc2963a2013-08-02 15:55:26 -070061 }
62
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070063 public static class StateColumns {
64 public static final String AUTHORITY = "authority";
65 public static final String ROOT_ID = Root.COLUMN_ROOT_ID;
66 public static final String DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID;
67 public static final String MODE = "mode";
68 public static final String SORT_ORDER = "sortOrder";
69 }
70
71 public static class ResumeColumns {
72 public static final String PACKAGE_NAME = "package_name";
73 public static final String STACK = "stack";
74 public static final String TIMESTAMP = "timestamp";
75 }
76
77 public static Uri buildRecent() {
Jeff Sharkeydc2963a2013-08-02 15:55:26 -070078 return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070079 .authority(AUTHORITY).appendPath("recent").build();
80 }
81
82 public static Uri buildState(String authority, String rootId, String documentId) {
83 return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
84 .appendPath("state").appendPath(authority).appendPath(rootId).appendPath(documentId)
85 .build();
Jeff Sharkeydc2963a2013-08-02 15:55:26 -070086 }
87
88 public static Uri buildResume(String packageName) {
89 return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
90 .authority(AUTHORITY).appendPath("resume").appendPath(packageName).build();
91 }
92
Jeff Sharkey92d7e692013-08-02 10:33:21 -070093 private DatabaseHelper mHelper;
94
95 private static class DatabaseHelper extends SQLiteOpenHelper {
Jeff Sharkeydc2963a2013-08-02 15:55:26 -070096 private static final String DB_NAME = "recents.db";
Jeff Sharkey92d7e692013-08-02 10:33:21 -070097
98 private static final int VERSION_INIT = 1;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -070099 private static final int VERSION_AS_BLOB = 3;
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700100
101 public DatabaseHelper(Context context) {
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700102 super(context, DB_NAME, null, VERSION_AS_BLOB);
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700103 }
104
105 @Override
106 public void onCreate(SQLiteDatabase db) {
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700107
108 db.execSQL("CREATE TABLE " + TABLE_RECENT + " (" +
109 RecentColumns.STACK + " BLOB PRIMARY KEY ON CONFLICT REPLACE," +
110 RecentColumns.TIMESTAMP + " INTEGER" +
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700111 ")");
112
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700113 db.execSQL("CREATE TABLE " + TABLE_STATE + " (" +
114 StateColumns.AUTHORITY + " TEXT," +
115 StateColumns.ROOT_ID + " TEXT," +
116 StateColumns.DOCUMENT_ID + " TEXT," +
117 StateColumns.MODE + " INTEGER," +
118 StateColumns.SORT_ORDER + " INTEGER," +
119 "PRIMARY KEY (" + StateColumns.AUTHORITY + ", " + StateColumns.ROOT_ID + ", "
120 + StateColumns.DOCUMENT_ID + ")" +
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700121 ")");
122
123 db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" +
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700124 ResumeColumns.PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," +
125 ResumeColumns.STACK + " BLOB," +
126 ResumeColumns.TIMESTAMP + " INTEGER" +
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700127 ")");
128 }
129
130 @Override
131 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
132 Log.w(TAG, "Upgrading database; wiping app data");
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700133 db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECENT);
134 db.execSQL("DROP TABLE IF EXISTS " + TABLE_STATE);
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700135 db.execSQL("DROP TABLE IF EXISTS " + TABLE_RESUME);
136 onCreate(db);
137 }
138 }
139
140 @Override
141 public boolean onCreate() {
142 mHelper = new DatabaseHelper(getContext());
143 return true;
144 }
145
146 @Override
147 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
148 String sortOrder) {
149 final SQLiteDatabase db = mHelper.getReadableDatabase();
150 switch (sMatcher.match(uri)) {
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700151 case URI_RECENT:
152 return db.query(TABLE_RECENT, projection,
153 RecentColumns.TIMESTAMP + "<" + MAX_HISTORY_IN_MILLIS, null, null, null,
154 null);
155 case URI_STATE:
156 final String authority = uri.getPathSegments().get(1);
157 final String rootId = uri.getPathSegments().get(2);
158 final String documentId = uri.getPathSegments().get(3);
159 return db.query(TABLE_STATE, projection, StateColumns.AUTHORITY + "=? AND "
160 + StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
161 new String[] { authority, rootId, documentId }, null, null, null);
162 case URI_RESUME:
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700163 final String packageName = uri.getPathSegments().get(1);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700164 return db.query(TABLE_RESUME, projection, ResumeColumns.PACKAGE_NAME + "=?",
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700165 new String[] { packageName }, null, null, null);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700166 default:
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700167 throw new UnsupportedOperationException("Unsupported Uri " + uri);
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700168 }
169 }
170
171 @Override
172 public String getType(Uri uri) {
173 return null;
174 }
175
176 @Override
177 public Uri insert(Uri uri, ContentValues values) {
178 final SQLiteDatabase db = mHelper.getWritableDatabase();
179 switch (sMatcher.match(uri)) {
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700180 case URI_RECENT:
181 values.put(RecentColumns.TIMESTAMP, System.currentTimeMillis());
182 db.insert(TABLE_RECENT, null, values);
183 db.delete(
184 TABLE_RECENT, RecentColumns.TIMESTAMP + ">" + MAX_HISTORY_IN_MILLIS, null);
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700185 return uri;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700186 case URI_STATE:
187 final String authority = uri.getPathSegments().get(1);
188 final String rootId = uri.getPathSegments().get(2);
189 final String documentId = uri.getPathSegments().get(3);
190
191 final ContentValues key = new ContentValues();
192 key.put(StateColumns.AUTHORITY, authority);
193 key.put(StateColumns.ROOT_ID, rootId);
194 key.put(StateColumns.DOCUMENT_ID, documentId);
195
196 // Ensure that row exists, then update with changed values
197 db.insertWithOnConflict(TABLE_STATE, null, key, SQLiteDatabase.CONFLICT_IGNORE);
198 db.update(TABLE_STATE, values, StateColumns.AUTHORITY + "=? AND "
199 + StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
200 new String[] { authority, rootId, documentId });
201
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700202 return uri;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700203 case URI_RESUME:
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700204 final String packageName = uri.getPathSegments().get(1);
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700205 values.put(ResumeColumns.PACKAGE_NAME, packageName);
206 values.put(ResumeColumns.TIMESTAMP, System.currentTimeMillis());
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700207 db.insert(TABLE_RESUME, null, values);
208 return uri;
Jeff Sharkeyd182bb62013-09-07 14:45:03 -0700209 default:
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700210 throw new UnsupportedOperationException("Unsupported Uri " + uri);
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700211 }
212 }
213
214 @Override
215 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
216 throw new UnsupportedOperationException("Unsupported Uri " + uri);
217 }
218
219 @Override
220 public int delete(Uri uri, String selection, String[] selectionArgs) {
221 throw new UnsupportedOperationException("Unsupported Uri " + uri);
222 }
Jeff Sharkey92d7e692013-08-02 10:33:21 -0700223}