152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee/* 252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Copyright (C) 2011 The Android Open Source Project 352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Licensed under the Apache License, Version 2.0 (the "License"); 552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * you may not use this file except in compliance with the License. 652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * You may obtain a copy of the License at 752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * http://www.apache.org/licenses/LICENSE-2.0 952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 1052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Unless required by applicable law or agreed to in writing, software 1152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * distributed under the License is distributed on an "AS IS" BASIS, 1252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * See the License for the specific language governing permissions and 1452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * limitations under the License 1552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 1652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeepackage com.android.providers.contacts; 1752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 189cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjeeimport static android.provider.VoicemailContract.SOURCE_PACKAGE_FIELD; 199cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses; 2052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause; 2152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 22975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjeeimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 234b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport com.android.providers.contacts.util.SelectionBuilder; 24975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjeeimport com.android.providers.contacts.util.TypedUriMatcherImpl; 25aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerdaimport com.google.common.annotations.VisibleForTesting; 26975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee 2752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.ContentProvider; 2852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.ContentValues; 2952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.Context; 30eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjeeimport android.content.Intent; 31eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjeeimport android.content.pm.PackageManager; 3252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.database.Cursor; 3352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.net.Uri; 3452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.os.Binder; 3552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.os.ParcelFileDescriptor; 369cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjeeimport android.provider.BaseColumns; 3752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.provider.VoicemailContract; 3852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.provider.VoicemailContract.Voicemails; 39663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onukiimport android.util.Log; 4052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 4152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport java.io.FileNotFoundException; 4252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport java.util.List; 4352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 4452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee/** 459cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * An implementation of the Voicemail content provider. This class in the entry point for both 469cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * voicemail content ('calls') table and 'voicemail_status' table. This class performs all common 479cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * permission checks and then delegates database level operations to respective table delegate 489cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * objects. 4952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 504b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeepublic class VoicemailContentProvider extends ContentProvider 514b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee implements VoicemailTable.DelegateHelper { 5252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private static final String TAG = "VoicemailContentProvider"; 5352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 54aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private VoicemailPermissions mVoicemailPermissions; 554b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private VoicemailTable.Delegate mVoicemailContentTable; 569cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private VoicemailTable.Delegate mVoicemailStatusTable; 5752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 5852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 5952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee public boolean onCreate() { 60663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 61663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "VoicemailContentProvider.onCreate start"); 62663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 6352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee Context context = context(); 64aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee mVoicemailPermissions = new VoicemailPermissions(context); 659cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee mVoicemailContentTable = new VoicemailContentTable(Tables.CALLS, context, 66aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda getDatabaseHelper(context), this, createCallLogInsertionHelper(context)); 679cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee mVoicemailStatusTable = new VoicemailStatusTable(Tables.VOICEMAIL_STATUS, context, 684b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee getDatabaseHelper(context), this); 69663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 70663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "VoicemailContentProvider.onCreate finish"); 71663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 7252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return true; 7352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 7452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 75aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda @VisibleForTesting 76aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda /*package*/ CallLogInsertionHelper createCallLogInsertionHelper(Context context) { 77c4144727cd740079f47e74ae5078d1613874f72aMakoto Onuki return DefaultCallLogInsertionHelper.getInstance(context); 78aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda } 79aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda 80aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda @VisibleForTesting 81aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda /*package*/ ContactsDatabaseHelper getDatabaseHelper(Context context) { 821975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee return ContactsDatabaseHelper.getInstance(context); 831975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee } 841975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee 85aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda @VisibleForTesting 86aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda /*package*/ Context context() { 8752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return getContext(); 8852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 8952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 9052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 9152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee public String getType(Uri uri) { 9252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee UriData uriData = null; 9352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee try { 944b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData = UriData.createUriData(uri); 9552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } catch (IllegalArgumentException ignored) { 9652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Special case: for illegal URIs, we return null rather than thrown an exception. 9752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 9852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 999cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).getType(uriData); 10052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 10152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 10252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 1034b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public Uri insert(Uri uri, ContentValues values) { 1049cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri, values); 1059cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).insert(uriData, values); 10652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 10752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 10852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 1094b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 1104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String sortOrder) { 111eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriDataForReadOperation(uri); 1124b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 1134b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionBuilder.addClause(getPackageRestrictionClause()); 1149cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).query(uriData, projection, selectionBuilder.build(), 1154b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionArgs, sortOrder); 11652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 11752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1184b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1194b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1209cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri, values); 1214b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 1224b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionBuilder.addClause(getPackageRestrictionClause()); 1239cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).update(uriData, values, selectionBuilder.build(), 1244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionArgs); 12552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 12652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1284b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int delete(Uri uri, String selection, String[] selectionArgs) { 1294b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri); 1304b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 1314b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionBuilder.addClause(getPackageRestrictionClause()); 1329cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).delete(uriData, selectionBuilder.build(), selectionArgs); 13352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 13452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1354b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1364b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 137eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee UriData uriData = null; 138eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee if (mode.equals("r")) { 139eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee uriData = checkPermissionsAndCreateUriDataForReadOperation(uri); 140eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } else { 141eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee uriData = checkPermissionsAndCreateUriData(uri); 142eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 1434b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // openFileHelper() relies on "_data" column to be populated with the file path. 1449cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).openFile(uriData, mode); 1459cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 1469cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 1479cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Returns the correct table delegate object that can handle this URI. */ 1489cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private VoicemailTable.Delegate getTableDelegate(UriData uriData) { 1499cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee switch (uriData.getUriType()) { 1509cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS: 1519cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS_ID: 1529cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return mVoicemailStatusTable; 1539cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case VOICEMAILS: 1549cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case VOICEMAILS_ID: 1559cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return mVoicemailContentTable; 1569cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case NO_MATCH: 1579cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throw new IllegalStateException("Invalid uri type for uri: " + uriData.getUri()); 1589cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee default: 1599cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throw new IllegalStateException("Impossible, all cases are covered."); 1609cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 16152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 16252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 16352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 1644b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Decorates a URI by providing methods to get various properties from the URI. 16552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 1664b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public static class UriData { 1674b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final Uri mUri; 1684b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final String mId; 1694b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final String mSourcePackage; 1709cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private final VoicemailUriType mUriType; 17152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1729cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public UriData(Uri uri, VoicemailUriType uriType, String id, String sourcePackage) { 1739cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee mUriType = uriType; 1744b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mUri = uri; 1754b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mId = id; 1764b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mSourcePackage = sourcePackage; 17752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 17852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1794b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Gets the original URI to which this {@link UriData} corresponds. */ 1804b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final Uri getUri() { 1814b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mUri; 18252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 18352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1844b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Tells us if our URI has an individual voicemail id. */ 1854b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final boolean hasId() { 1864b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mId != null; 18752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 18852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1894b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Gets the ID for the voicemail. */ 1904b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final String getId() { 1914b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mId; 19252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 19352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1944b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Tells us if our URI has a source package string. */ 1954b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final boolean hasSourcePackage() { 1964b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mSourcePackage != null; 19752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 19852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1994b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Gets the source package. */ 2004b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final String getSourcePackage() { 2014b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mSourcePackage; 20252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 20352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 2049cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Gets the Voicemail URI type. */ 2059cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public final VoicemailUriType getUriType() { 2069cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return mUriType; 2079cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2089cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2099cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Builds a where clause from the URI data. */ 2109cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public final String getWhereClause() { 2119cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return concatenateClauses( 2129cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee (hasId() ? getEqualityClause(BaseColumns._ID, getId()) : null), 2139cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee (hasSourcePackage() ? getEqualityClause(SOURCE_PACKAGE_FIELD, 2149cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee getSourcePackage()) : null)); 2159cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2169cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2174b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Create a {@link UriData} corresponding to a given uri. */ 2184b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public static UriData createUriData(Uri uri) { 2194b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String sourcePackage = uri.getQueryParameter( 2204b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee VoicemailContract.PARAM_KEY_SOURCE_PACKAGE); 2214b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee List<String> segments = uri.getPathSegments(); 2229cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee VoicemailUriType uriType = createUriMatcher().match(uri); 2239cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee switch (uriType) { 2244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee case VOICEMAILS: 2259cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS: 2269cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return new UriData(uri, uriType, null, sourcePackage); 2274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee case VOICEMAILS_ID: 2289cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS_ID: 2299cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return new UriData(uri, uriType, segments.get(1), sourcePackage); 2304b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee case NO_MATCH: 2314b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new IllegalArgumentException("Invalid URI: " + uri); 2324b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee default: 2334b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new IllegalStateException("Impossible, all cases are covered"); 2344b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2354b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2369cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2379cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private static TypedUriMatcherImpl<VoicemailUriType> createUriMatcher() { 2389cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return new TypedUriMatcherImpl<VoicemailUriType>( 2399cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee VoicemailContract.AUTHORITY, VoicemailUriType.values()); 2409cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 24152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 24252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 2434b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2444b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // VoicemailTable.DelegateHelper interface. 2454b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public void checkAndAddSourcePackageIntoValues(UriData uriData, ContentValues values) { 2464b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // If content values don't contain the provider, calculate the right provider to use. 2479cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (!values.containsKey(SOURCE_PACKAGE_FIELD)) { 2484b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String provider = uriData.hasSourcePackage() ? 2494b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData.getSourcePackage() : getCallingPackage(); 2509cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee values.put(SOURCE_PACKAGE_FIELD, provider); 2514b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2524b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // You must have access to the provider given in values. 2534b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (!mVoicemailPermissions.callerHasFullAccess()) { 2544b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee checkPackagesMatch(getCallingPackage(), 2554b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD), 2564b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData.getUri()); 257975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee } 258975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee } 259975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee 2609cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** 2619cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * Checks that the source_package field is same in uriData and ContentValues, if it happens 2629cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * to be set in both. 2639cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee */ 2649cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private void checkSourcePackageSameIfSet(UriData uriData, ContentValues values) { 2659cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (uriData.hasSourcePackage() && values.containsKey(SOURCE_PACKAGE_FIELD)) { 2669cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (!uriData.getSourcePackage().equals(values.get(SOURCE_PACKAGE_FIELD))) { 2679cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throw new SecurityException( 2689cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee "source_package in URI was " + uriData.getSourcePackage() + 2699cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee " but doesn't match source_package in ContentValues which was " 2709cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee + values.get(SOURCE_PACKAGE_FIELD)); 2719cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2729cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2739cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2749cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2759cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee @Override 2769cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Implementation of {@link VoicemailTable.DelegateHelper#openDataFile(UriData, String)} */ 2779cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public ParcelFileDescriptor openDataFile(UriData uriData, String mode) 2789cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throws FileNotFoundException { 2799cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return openFileHelper(uriData.getUri(), mode); 28052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 28152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 28252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 2834b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Performs necessary voicemail permission checks common to all operations and returns 2844b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * the structured representation, {@link UriData}, of the supplied uri. 28552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 286eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee private UriData checkPermissionsAndCreateUriDataForReadOperation(Uri uri) { 287eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee // If the caller has been explicitly granted read permission to this URI then no need to 288eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee // check further. 289eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee if (context().checkCallingUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION) 290eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee == PackageManager.PERMISSION_GRANTED) { 291eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return UriData.createUriData(uri); 292eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 293eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee return checkPermissionsAndCreateUriData(uri); 294eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee } 295eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee 296eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee /** 297eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee * Performs necessary voicemail permission checks common to all operations and returns 298eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee * the structured representation, {@link UriData}, of the supplied uri. 299eeffa7edb048e785ebc665c830dc84d87f174b07Debashish Chatterjee */ 3004b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private UriData checkPermissionsAndCreateUriData(Uri uri) { 3014b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mVoicemailPermissions.checkCallerHasOwnVoicemailAccess(); 3024b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee UriData uriData = UriData.createUriData(uri); 3034b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee checkPackagePermission(uriData); 3044b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return uriData; 3054b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 30652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 3074b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** 3089cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * Same as {@link #checkPackagePermission(UriData)}. In addition does permission check 3099cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * on the ContentValues. 3109cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee */ 3119cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private UriData checkPermissionsAndCreateUriData(Uri uri, ContentValues... valuesArray) { 3129cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri); 3139cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee for (ContentValues values : valuesArray) { 3149cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee checkSourcePackageSameIfSet(uriData, values); 3159cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 3169cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return uriData; 3179cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 3189cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 3199cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** 3209cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * Checks that the callingPackage is same as voicemailSourcePackage. Throws {@link 3214b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * SecurityException} if they don't match. 3224b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee */ 3239cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private final void checkPackagesMatch(String callingPackage, String voicemailSourcePackage, 3244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Uri uri) { 3259cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (!voicemailSourcePackage.equals(callingPackage)) { 3264b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String errorMsg = String.format("Permission denied for URI: %s\n. " + 3279cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee "Package %s cannot perform this operation for %s. Requires %s permission.", 3289cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee uri, callingPackage, voicemailSourcePackage, 3294b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Manifest.permission.READ_WRITE_ALL_VOICEMAIL); 3304b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new SecurityException(errorMsg); 33152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 33252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 33352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 33452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 33552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Checks that either the caller has READ_WRITE_ALL_VOICEMAIL permission, or has the 33698a77ec8057c5fe0ff487ca7d0910312693e5689Debashish Chatterjee * ADD_VOICEMAIL permission and is using a URI that matches 3379cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * /voicemail/?source_package=[source-package] where [source-package] is the same as the calling 33852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * package. 33952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 34052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * @throws SecurityException if the check fails. 34152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 34252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private void checkPackagePermission(UriData uriData) { 343aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (!mVoicemailPermissions.callerHasFullAccess()) { 34452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (!uriData.hasSourcePackage()) { 3459cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee // You cannot have a match if this is not a provider URI. 34652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee throw new SecurityException(String.format( 34752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee "Provider %s does not have %s permission." + 3484b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee "\nPlease set query parameter '%s' in the URI.\nURI: %s", 34952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee getCallingPackage(), Manifest.permission.READ_WRITE_ALL_VOICEMAIL, 3504b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee VoicemailContract.PARAM_KEY_SOURCE_PACKAGE, uriData.getUri())); 35152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 35252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee checkPackagesMatch(getCallingPackage(), uriData.getSourcePackage(), uriData.getUri()); 35352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 35452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 35552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 35652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 35752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Gets the name of the calling package. 35852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * <p> 35952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * It's possible (though unlikely) for there to be more than one calling package (requires that 36052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * your manifest say you want to share process ids) in which case we will return an arbitrary 36152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * package name. It's also possible (though very unlikely) for us to be unable to work out what 36252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * your calling package is, in which case we will return null. 36352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 36452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /* package for test */String getCallingPackage() { 36552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee int caller = Binder.getCallingUid(); 36652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (caller == 0) { 36752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 36852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 36952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee String[] callerPackages = context().getPackageManager().getPackagesForUid(caller); 37052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (callerPackages == null || callerPackages.length == 0) { 37152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 37252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 37352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (callerPackages.length == 1) { 37452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return callerPackages[0]; 37552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 37652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // If we have more than one caller package, which is very unlikely, let's return the one 37752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // with the highest permissions. If more than one has the same permission, we don't care 37852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // which one we return. 37952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee String bestSoFar = callerPackages[0]; 38052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee for (String callerPackage : callerPackages) { 381aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (mVoicemailPermissions.packageHasFullAccess(callerPackage)) { 38252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Full always wins, we can return early. 38352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return callerPackage; 38452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 385aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (mVoicemailPermissions.packageHasOwnVoicemailAccess(callerPackage)) { 38652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee bestSoFar = callerPackage; 38752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 38852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 38952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return bestSoFar; 39052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 39152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 39252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 39352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Creates a clause to restrict the selection to the calling provider or null if the caller has 39452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * access to all data. 39552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 39652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private String getPackageRestrictionClause() { 397aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (mVoicemailPermissions.callerHasFullAccess()) { 39852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 39952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 40052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return getEqualityClause(Voicemails.SOURCE_PACKAGE, getCallingPackage()); 40152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 40252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee} 403