PhotoProvider.java revision 8324b3355817e8f6d08ac0b1f7349926df8a9bc7
1c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount/*
2c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Copyright (C) 2013 The Android Open Source Project
3c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *
4c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Licensed under the Apache License, Version 2.0 (the "License");
5c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * you may not use this file except in compliance with the License.
6c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * You may obtain a copy of the License at
7c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *
8c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *      http://www.apache.org/licenses/LICENSE-2.0
9c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *
10c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Unless required by applicable law or agreed to in writing, software
11c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * distributed under the License is distributed on an "AS IS" BASIS,
12c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * See the License for the specific language governing permissions and
14c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * limitations under the License.
15c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */
16c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountpackage com.android.photos.data;
17c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
185139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mountimport android.content.ContentResolver;
19aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mountimport android.content.ContentUris;
20c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.ContentValues;
215139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mountimport android.content.Context;
22c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.UriMatcher;
23c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.Cursor;
24c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.DatabaseUtils;
25c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.sqlite.SQLiteDatabase;
26c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.sqlite.SQLiteOpenHelper;
27135c2e576f3dfea954ba628942c55adcb35a7cf6George Mountimport android.database.sqlite.SQLiteQueryBuilder;
282f5a064980ad79e88616ba124268e4d7298c68a5George Mountimport android.media.ExifInterface;
29c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.net.Uri;
30c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.os.CancellationSignal;
31c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.provider.BaseColumns;
32c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
33091314b7ea73e774ce96c981bd7007c94ad80e30George Mountimport com.android.gallery3d.common.ApiHelper;
34091314b7ea73e774ce96c981bd7007c94ad80e30George Mount
35c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport java.util.List;
36c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
37c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount/**
38c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * A provider that gives access to photo and video information for media stored
39c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * on the server. Only media that is or will be put on the server will be
40c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * accessed by this provider. Use Photos.CONTENT_URI to query all photos and
41c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI
42c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * to query metadata about a photo or video, based on the ID of the media. Use
43c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or
44c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview,
45c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * or original-sized image respectfully. <br/>
46c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * To add or update metadata, use the update function rather than insert. All
47c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * values for the metadata must be in the ContentValues, even if they are also
48c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * in the selection. The selection and selectionArgs are not used when updating
49c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * metadata. If the metadata values are null, the row will be deleted.
50c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */
515139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mountpublic class PhotoProvider extends SQLiteContentProvider {
52c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @SuppressWarnings("unused")
53c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private static final String TAG = PhotoProvider.class.getSimpleName();
54135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
55135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    protected static final String DB_NAME = "photo.db";
56135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    public static final String AUTHORITY = PhotoProviderAuthority.AUTHORITY;
57c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY)
58c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            .build();
59c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
60135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    // Used to allow mocking out the change notification because
61135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    // MockContextResolver disallows system-wide notification.
62135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    public static interface ChangeNotification {
635139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        void notifyChange(Uri uri, boolean syncToNetwork);
64135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    }
65135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
66c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
672f5a064980ad79e88616ba124268e4d7298c68a5George Mount     * Contains columns that can be accessed via Accounts.CONTENT_URI
68c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
692f5a064980ad79e88616ba124268e4d7298c68a5George Mount    public static interface Accounts extends BaseColumns {
70c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
712f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * Internal database table used for account information
72c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
732f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String TABLE = "accounts";
74c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
752f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * Content URI for account information
76c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
77c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
78c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
792f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * User name for this account.
80c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
812f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ACCOUNT_NAME = "name";
822f5a064980ad79e88616ba124268e4d7298c68a5George Mount    }
832f5a064980ad79e88616ba124268e4d7298c68a5George Mount
842f5a064980ad79e88616ba124268e4d7298c68a5George Mount    /**
852f5a064980ad79e88616ba124268e4d7298c68a5George Mount     * Contains columns that can be accessed via Photos.CONTENT_URI.
862f5a064980ad79e88616ba124268e4d7298c68a5George Mount     */
872f5a064980ad79e88616ba124268e4d7298c68a5George Mount    public static interface Photos extends BaseColumns {
882f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used for basic photo information. */
89693a5b7a18066d4757d49a44214356a3dd9f61a0Mangesh Ghiware        public static final String TABLE = "photos";
902f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Content URI for basic photo and video information. */
912f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
922f5a064980ad79e88616ba124268e4d7298c68a5George Mount
932f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Long foreign key to Accounts._ID */
942f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ACCOUNT_ID = "account_id";
952f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Column name for the width of the original image. Integer value. */
96c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String WIDTH = "width";
972f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Column name for the height of the original image. Integer value. */
98c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String HEIGHT = "height";
99c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
100c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Column name for the date that the original image was taken. Long
101c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * value indicating the milliseconds since epoch in the GMT time zone.
102c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
103c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String DATE_TAKEN = "date_taken";
104c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
105c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Column name indicating the long value of the album id that this image
106c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * resides in. Will be NULL if it it has not been uploaded to the
107c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * server.
108c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
109c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String ALBUM_ID = "album_id";
1102f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The column name for the mime-type String. */
1112f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String MIME_TYPE = "mime_type";
1122f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The title of the photo. String value. */
1132f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String TITLE = "title";
1142f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the photo entry was last updated. Long value. */
1152f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String DATE_MODIFIED = "date_modified";
116c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
1172f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * The rotation of the photo in degrees, if rotation has not already
1182f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * been applied. Integer value.
119c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
1202f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ROTATION = "rotation";
121c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
122c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
123c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
124c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * Contains columns and Uri for accessing album information.
125c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
126c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public static interface Albums extends BaseColumns {
1272f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used album information. */
128693a5b7a18066d4757d49a44214356a3dd9f61a0Mangesh Ghiware        public static final String TABLE = "albums";
1292f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Content URI for album information. */
130c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
1312f5a064980ad79e88616ba124268e4d7298c68a5George Mount
1322f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Long foreign key to Accounts._ID */
1332f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ACCOUNT_ID = "account_id";
1342f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Parent directory or null if this is in the root. */
1352f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String PARENT_ID = "parent_id";
136c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
137c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Column name for the visibility level of the album. Can be any of the
138c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * VISIBILITY_* values.
139c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
140c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String VISIBILITY = "visibility";
1412f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The user-specified location associated with the album. String value. */
1422f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String LOCATION_STRING = "location_string";
1432f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The title of the album. String value. */
1442f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String TITLE = "title";
1452f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** A short summary of the contents of the album. String value. */
1462f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String SUMMARY = "summary";
1472f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the album was created. Long value */
1482f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String DATE_PUBLISHED = "date_published";
1492f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the album entry was last updated. Long value. */
1502f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String DATE_MODIFIED = "date_modified";
151c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
152c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // Privacy values for Albums.VISIBILITY
153c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final int VISIBILITY_PRIVATE = 1;
154c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final int VISIBILITY_SHARED = 2;
155c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final int VISIBILITY_PUBLIC = 3;
156c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
157c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
158c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
159c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * Contains columns and Uri for accessing photo and video metadata
160c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
161c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public static interface Metadata extends BaseColumns {
1622f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used metadata information. */
163c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String TABLE = "metadata";
1642f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Content URI for photo and video metadata. */
165c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
1662f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Foreign key to photo_id. Long value. */
167c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String PHOTO_ID = "photo_id";
1682f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Metadata key. String value */
169c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String KEY = "key";
170c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
171c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Metadata value. Type is based on key.
172c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
173c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String VALUE = "value";
1742f5a064980ad79e88616ba124268e4d7298c68a5George Mount
1752f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** A short summary of the photo. String value. */
1762f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_SUMMARY = "summary";
1772f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the photo was added. Long value. */
1782f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_PUBLISHED = "date_published";
1792f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the photo was last updated. Long value. */
1802f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_DATE_UPDATED = "date_updated";
1812f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The size of the photo is bytes. Integer value. */
1822f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_SIZE_IN_BTYES = "size";
1832f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The latitude associated with the photo. Double value. */
1842f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_LATITUDE = "latitude";
1852f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The longitude associated with the photo. Double value. */
1862f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_LONGITUDE = "longitude";
1872f5a064980ad79e88616ba124268e4d7298c68a5George Mount
1882f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The make of the camera used. String value. */
1892f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_MAKE = ExifInterface.TAG_MAKE;
1902f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The model of the camera used. String value. */
1912f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_MODEL = ExifInterface.TAG_MODEL;;
1922f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The exposure time used. Float value. */
1932f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_EXPOSURE = ExifInterface.TAG_EXPOSURE_TIME;
1942f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Whether the flash was used. Boolean value. */
1952f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_FLASH = ExifInterface.TAG_FLASH;
1962f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The focal length used. Float value. */
1972f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_FOCAL_LENGTH = ExifInterface.TAG_FOCAL_LENGTH;
1982f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The fstop value used. Float value. */
1992f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_FSTOP = ExifInterface.TAG_APERTURE;
2002f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The ISO equivalent value used. Integer value. */
2012f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_ISO = ExifInterface.TAG_ISO;
202c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
203c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
204c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
205c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * Contains columns and Uri for maintaining the image cache.
206c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
207c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public static interface ImageCache extends BaseColumns {
2082f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used for the image cache */
209c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String TABLE = "image_cache";
210c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
211c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
212c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * The image_type query parameter required for accessing a specific
213c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * image
214c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
215c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String IMAGE_TYPE_QUERY_PARAMETER = "image_type";
216c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
217c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // ImageCache.IMAGE_TYPE values
218cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_ALBUM_COVER = 1;
219cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_THUMBNAIL = 2;
220cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_PREVIEW = 3;
221cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_ORIGINAL = 4;
222c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
223c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
224c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Content URI for retrieving image paths. The
225c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * IMAGE_TYPE_QUERY_PARAMETER must be used in queries.
226c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
227c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
228c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
229cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        /**
230cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * Content URI for retrieving the album cover art. The album ID must be
231cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * appended to the URI.
232cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         */
233cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final Uri ALBUM_COVER_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI,
234cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount                Albums.TABLE);
235cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount
236cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        /**
237cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * An _ID from Albums or Photos, depending on whether IMAGE_TYPE is
238cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * IMAGE_TYPE_ALBUM or not. Long value.
239cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         */
240cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final String REMOTE_ID = "remote_id";
2412f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** One of IMAGE_TYPE_* values. */
242c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String IMAGE_TYPE = "image_type";
2432f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The String path to the image. */
244c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String PATH = "path";
245c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    };
246c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
247c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    // SQL used within this class.
248c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String WHERE_ID = BaseColumns._ID + " = ?";
249c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND "
250c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            + Metadata.KEY + " = ?";
251c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
252c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM "
253c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            + Albums.TABLE;
254c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM "
255c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            + Photos.TABLE;
256c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE;
257c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE;
258c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE;
259c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE;
260c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String WHERE = " WHERE ";
261c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String IN = " IN ";
262c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String NESTED_SELECT_START = "(";
263c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String NESTED_SELECT_END = ")";
264c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
265c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
266c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * For selecting the mime-type for an image.
267c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
268c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private static final String[] PROJECTION_MIME_TYPE = {
269c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        Photos.MIME_TYPE,
270c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    };
271c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
27209bfc1d566621498d08903559ae707161a701571George Mount    protected static final String[] BASE_COLUMNS_ID = {
273135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        BaseColumns._ID,
274135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    };
275135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
276135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    protected ChangeNotification mNotifier = null;
277c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
278c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
279c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_PHOTO = 1;
280c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_PHOTO_ID = 2;
281c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_ALBUM = 3;
282c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_ALBUM_ID = 4;
283c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_METADATA = 5;
284c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_METADATA_ID = 6;
285c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_IMAGE = 7;
286cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount    protected static final int MATCH_ALBUM_COVER = 8;
287dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware    protected static final int MATCH_ACCOUNT = 9;
288dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware    protected static final int MATCH_ACCOUNT_ID = 10;
289c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
290c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    static {
291c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO);
292c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against Photos._ID
293c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID);
294c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM);
295c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against Albums._ID
296c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID);
297c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA);
298c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against metadata/<Metadata._ID>
299c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID);
300c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against image_cache/<ImageCache.PHOTO_ID>
301c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/#", MATCH_IMAGE);
302cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        // match against image_cache/album/<Albums._ID>
303cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/" + Albums.TABLE + "/#",
304cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount                MATCH_ALBUM_COVER);
305dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware        sUriMatcher.addURI(AUTHORITY, Accounts.TABLE, MATCH_ACCOUNT);
306dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware        // match against Accounts._ID
307dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware        sUriMatcher.addURI(AUTHORITY, Accounts.TABLE + "/#", MATCH_ACCOUNT_ID);
308c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
309c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
310c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
3115139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
3125139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            boolean callerIsSyncAdapter) {
313c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = matchUri(uri);
314c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selection = addIdToSelection(match, selection);
315c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
3168324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return deleteCascade(uri, match, selection, selectionArgs);
317c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
318c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
319c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
320c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public String getType(Uri uri) {
321c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null);
322c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String mimeType = null;
323c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        if (cursor.moveToNext()) {
324c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            mimeType = cursor.getString(0);
325c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
326c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        cursor.close();
327c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return mimeType;
328c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
329c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
330c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
3315139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public Uri insertInTransaction(Uri uri, ContentValues values, boolean callerIsSyncAdapter) {
332aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        int match = matchUri(uri);
333aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        validateMatchTable(match);
334aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        String table = getTableFromMatch(match, uri);
3355139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
336aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        Uri insertedUri = null;
3375139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        long id = db.insert(table, null, values);
3385139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        if (id != -1) {
3395139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            // uri already matches the table.
3405139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            insertedUri = ContentUris.withAppendedId(uri, id);
3415139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            postNotifyUri(insertedUri);
342aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        }
343aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        return insertedUri;
344c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
345c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
346c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
347c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
348c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            String sortOrder) {
349c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return query(uri, projection, selection, selectionArgs, sortOrder, null);
350c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
351c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
352c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
353c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
354c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            String sortOrder, CancellationSignal cancellationSignal) {
355c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = matchUri(uri);
356c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selection = addIdToSelection(match, selection);
357c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
358c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String table = getTableFromMatch(match, uri);
359091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        return query(table, projection, selection, selectionArgs, sortOrder, cancellationSignal);
360c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
361c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
362c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
3635139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public int updateInTransaction(Uri uri, ContentValues values, String selection,
3645139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            String[] selectionArgs, boolean callerIsSyncAdapter) {
365c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = matchUri(uri);
366c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int rowsUpdated = 0;
3675139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
3685139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        if (match == MATCH_METADATA) {
3695139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            rowsUpdated = modifyMetadata(db, values);
3705139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        } else {
3715139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            selection = addIdToSelection(match, selection);
3725139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
3735139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            String table = getTableFromMatch(match, uri);
3745139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            rowsUpdated = db.update(table, values, selection, selectionArgs);
375c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
3765139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        postNotifyUri(uri);
377c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return rowsUpdated;
378c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
379c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
380135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    public void setMockNotification(ChangeNotification notification) {
381135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        mNotifier = notification;
382135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    }
383135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
384c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String addIdToSelection(int match, String selection) {
385c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String where;
386c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
387c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO_ID:
388c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM_ID:
389c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA_ID:
390c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                where = WHERE_ID;
391c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
392c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            default:
393c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                return selection;
394c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
395c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return DatabaseUtils.concatenateWhere(selection, where);
396c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
397c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
398c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) {
399c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String[] whereArgs;
400c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
401c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO_ID:
402c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM_ID:
403c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA_ID:
404c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                whereArgs = new String[] {
405c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                    uri.getPathSegments().get(1),
406c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                };
407c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
408c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            default:
409c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                return selectionArgs;
410c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
411c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs);
412c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
413c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
414c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) {
415c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        List<String> segments = uri.getPathSegments();
416c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String[] additionalArgs = {
417c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                segments.get(1),
418c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                segments.get(2),
419c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        };
420c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
421c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs);
422c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
423c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
424c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String getTableFromMatch(int match, Uri uri) {
425c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String table;
426c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
427c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO:
428c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO_ID:
429c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                table = Photos.TABLE;
430c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
431c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM:
432c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM_ID:
433c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                table = Albums.TABLE;
434c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
435c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA:
436c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA_ID:
437c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                table = Metadata.TABLE;
438c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
439dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware            case MATCH_ACCOUNT:
440dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware            case MATCH_ACCOUNT_ID:
441dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware                table = Accounts.TABLE;
442dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware                break;
443c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            default:
444c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                throw unknownUri(uri);
445c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
446c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return table;
447c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
448c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
4495139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    @Override
4505139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public SQLiteOpenHelper getDatabaseHelper(Context context) {
4515139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        return new PhotoDatabase(context, DB_NAME);
452c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
453c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
454c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private int modifyMetadata(SQLiteDatabase db, ContentValues values) {
455c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int rowCount;
456c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        if (values.get(Metadata.VALUE) == null) {
457aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            String[] selectionArgs = {
458aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount                    values.getAsString(Metadata.PHOTO_ID), values.getAsString(Metadata.KEY),
459aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            };
460c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs);
461c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        } else {
462aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            long rowId = db.replace(Metadata.TABLE, null, values);
463aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            rowCount = (rowId == -1) ? 0 : 1;
464c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
465c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return rowCount;
466c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
467c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
468c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private int matchUri(Uri uri) {
469c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = sUriMatcher.match(uri);
470c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        if (match == UriMatcher.NO_MATCH) {
471c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            throw unknownUri(uri);
472c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
473aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        if (match == MATCH_IMAGE || match == MATCH_ALBUM_COVER) {
474aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            throw new IllegalArgumentException("Operation not allowed on image cache database");
475aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        }
476c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return match;
477c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
478c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
4795139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    @Override
4805139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    protected void notifyChange(ContentResolver resolver, Uri uri, boolean syncToNetwork) {
481135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        if (mNotifier != null) {
4825139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            mNotifier.notifyChange(uri, syncToNetwork);
483135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        } else {
4845139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            resolver.notifyChange(uri, null, syncToNetwork);
485135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        }
486c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
487c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
488c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static IllegalArgumentException unknownUri(Uri uri) {
489c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return new IllegalArgumentException("Unknown Uri format: " + uri);
490c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
491c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
492135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    protected static String nestWhere(String matchColumn, String table, String nestedWhere) {
493135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        String query = SQLiteQueryBuilder.buildQueryString(false, table, BASE_COLUMNS_ID,
494135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount                nestedWhere, null, null, null, null);
495135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        return matchColumn + IN + NESTED_SELECT_START + query + NESTED_SELECT_END;
496c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
497c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
4988324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String metadataSelectionFromPhotos(String where) {
4998324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Metadata.PHOTO_ID, Photos.TABLE, where);
5008324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5018324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5028324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String photoSelectionFromAlbums(String where) {
5038324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Photos.ALBUM_ID, Albums.TABLE, where);
5048324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5058324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5068324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String photoSelectionFromAccounts(String where) {
5078324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Photos.ACCOUNT_ID, Accounts.TABLE, where);
5088324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5098324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5108324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String albumSelectionFromAccounts(String where) {
5118324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Albums.ACCOUNT_ID, Accounts.TABLE, where);
5128324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5138324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5148324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected int deleteCascade(Uri uri, int match, String selection, String[] selectionArgs) {
515c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
516c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO:
51756c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_PHOTO_ID:
5188324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Metadata.CONTENT_URI, MATCH_METADATA,
5198324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        metadataSelectionFromPhotos(selection), selectionArgs);
520c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
521c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM:
52256c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_ALBUM_ID:
5238324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO,
5248324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        photoSelectionFromAlbums(selection), selectionArgs);
525c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
52656c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_ACCOUNT:
52756c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_ACCOUNT_ID:
5288324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO,
5298324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        photoSelectionFromAccounts(selection), selectionArgs);
5308324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Albums.CONTENT_URI, MATCH_ALBUM,
5318324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        albumSelectionFromAccounts(selection), selectionArgs);
53256c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount                break;
533c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
5348324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
535c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String table = getTableFromMatch(match, uri);
536135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        int deleted = db.delete(table, selection, selectionArgs);
537135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        if (deleted > 0) {
5385139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            postNotifyUri(uri);
539c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
540135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        return deleted;
541c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
542c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
543aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount    private static void validateMatchTable(int match) {
544aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        switch (match) {
545aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            case MATCH_PHOTO:
546aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            case MATCH_ALBUM:
547aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            case MATCH_METADATA:
548dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware            case MATCH_ACCOUNT:
549aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount                break;
550aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            default:
551aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount                throw new IllegalArgumentException("Operation not allowed on an existing row.");
552aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        }
553aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount    }
554091314b7ea73e774ce96c981bd7007c94ad80e30George Mount
555091314b7ea73e774ce96c981bd7007c94ad80e30George Mount    protected Cursor query(String table, String[] columns, String selection,
556091314b7ea73e774ce96c981bd7007c94ad80e30George Mount            String[] selectionArgs, String orderBy, CancellationSignal cancellationSignal) {
557091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        SQLiteDatabase db = getDatabaseHelper().getReadableDatabase();
558091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        if (ApiHelper.HAS_CANCELLATION_SIGNAL) {
559091314b7ea73e774ce96c981bd7007c94ad80e30George Mount            return db.query(false, table, columns, selection, selectionArgs, null, null,
560091314b7ea73e774ce96c981bd7007c94ad80e30George Mount                    orderBy, null, cancellationSignal);
561091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        } else {
562091314b7ea73e774ce96c981bd7007c94ad80e30George Mount            return db.query(table, columns, selection, selectionArgs, null, null, orderBy);
563091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        }
564091314b7ea73e774ce96c981bd7007c94ad80e30George Mount    }
565c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount}
566