1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.datamodel; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ContentResolver; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.MatrixCursor; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.MatrixCursor.RowBuilder; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.OpenableColumns; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.util.SimpleArrayMap; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.annotations.VisibleForTesting; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.File; 35a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylorimport java.io.IOException; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * A very simple content provider that can serve media files from our cache directory. 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class MediaScratchFileProvider extends FileProvider { 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = LogUtil.BUGLE_TAG; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final SimpleArrayMap<Uri, String> sUriToDisplayNameMap = 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new SimpleArrayMap<Uri, String>(); 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String AUTHORITY = 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "com.android.messaging.datamodel.MediaScratchFileProvider"; 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String MEDIA_SCRATCH_SPACE_DIR = "mediascratchspace"; 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean isMediaScratchSpaceUri(final Uri uri) { 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (uri == null) { 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<String> segments = uri.getPathSegments(); 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return (TextUtils.equals(uri.getScheme(), ContentResolver.SCHEME_CONTENT) && 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TextUtils.equals(uri.getAuthority(), AUTHORITY) && 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd segments.size() == 1 && FileProvider.isValidFileId(segments.get(0))); 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns a uri that can be used to access a raw mms file. 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return the URI for an raw mms file 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static Uri buildMediaScratchSpaceUri(final String extension) { 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = FileProvider.buildFileUri(AUTHORITY, extension); 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final File file = getFileWithExtension(uri.getPath(), extension); 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ensureFileExists(file)) { 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(TAG, "Failed to create temp file " + file.getAbsolutePath()); 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return uri; 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static File getFileFromUri(final Uri uri) { 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.equals(AUTHORITY, uri.getAuthority()); 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return getFileWithExtension(uri.getPath(), getExtensionFromUri(uri)); 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static Uri.Builder getUriBuilder() { 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return (new Uri.Builder()).authority(AUTHORITY).scheme(ContentResolver.SCHEME_CONTENT); 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd File getFile(final String path, final String extension) { 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return getFileWithExtension(path, extension); 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static File getFileWithExtension(final String path, final String extension) { 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Context context = Factory.get().getApplicationContext(); 93a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor final File filePath = new File(getDirectory(context), 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TextUtils.isEmpty(extension) ? path : path + "." + extension); 95a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor 96a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor try { 97a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor if (!filePath.getCanonicalPath() 98a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor .startsWith(getDirectory(context).getCanonicalPath())) { 99a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor LogUtil.e(TAG, "getFileWithExtension: path " 100a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor + filePath.getCanonicalPath() 101a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor + " does not start with " 102a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor + getDirectory(context).getCanonicalPath()); 103a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor return null; 104a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor } 105a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor } catch (IOException e) { 106a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor LogUtil.e(TAG, "getFileWithExtension: getCanonicalPath failed ", e); 107a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor return null; 108a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor } 109a2aa53f83afbd13b04cbdcca494fd3cf659c155dTom Taylor return filePath; 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static File getDirectory(final Context context) { 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new File(context.getCacheDir(), MEDIA_SCRATCH_SPACE_DIR); 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public Cursor query(final Uri uri, final String[] projection, final String selection, 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String[] selectionArgs, final String sortOrder) { 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (projection != null && projection.length > 0 && 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd TextUtils.equals(projection[0], OpenableColumns.DISPLAY_NAME) && 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd isMediaScratchSpaceUri(uri)) { 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Retrieve the display name associated with a temp file. This is used by the Contacts 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // ImportVCardActivity to retrieve the name of the contact(s) being imported. 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String displayName; 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (sUriToDisplayNameMap) { 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd displayName = sUriToDisplayNameMap.get(uri); 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!TextUtils.isEmpty(displayName)) { 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MatrixCursor cursor = 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new MatrixCursor(new String[] { OpenableColumns.DISPLAY_NAME }); 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd RowBuilder row = cursor.newRow(); 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd row.add(displayName); 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return cursor; 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void addUriToDisplayNameEntry(final Uri scratchFileUri, 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String displayName) { 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (TextUtils.isEmpty(displayName)) { 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (sUriToDisplayNameMap) { 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sUriToDisplayNameMap.put(scratchFileUri, displayName); 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 149