VoicemailContentProvider.java revision 9cf06e7bcb0be759f1c930412fd2e41eba4f5f03
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; 25975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee 2606f995b614e0ebe59ff75f170e20ca96c9b17f0cDebashish Chatterjeeimport android.content.ComponentName; 2752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.ContentProvider; 2852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.ContentResolver; 2952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.ContentValues; 3052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.Context; 3152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.content.Intent; 3206f995b614e0ebe59ff75f170e20ca96c9b17f0cDebashish Chatterjeeimport android.content.pm.ActivityInfo; 3342e8dddb940a502e97151a08f16b87aed7b30de5Debashish Chatterjeeimport android.content.pm.ResolveInfo; 3452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.database.Cursor; 3552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.net.Uri; 3652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.os.Binder; 3752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.os.ParcelFileDescriptor; 389cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjeeimport android.provider.BaseColumns; 3952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.provider.VoicemailContract; 4052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.provider.VoicemailContract.Voicemails; 4152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 4252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport java.io.FileNotFoundException; 43975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjeeimport java.util.ArrayList; 4452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport java.util.List; 4552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 4652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee/** 479cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * An implementation of the Voicemail content provider. This class in the entry point for both 489cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * voicemail content ('calls') table and 'voicemail_status' table. This class performs all common 499cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * permission checks and then delegates database level operations to respective table delegate 509cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * objects. 5152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 524b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeepublic class VoicemailContentProvider extends ContentProvider 534b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee implements VoicemailTable.DelegateHelper { 5452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private static final String TAG = "VoicemailContentProvider"; 5552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 5652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private ContentResolver mContentResolver; 57aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private VoicemailPermissions mVoicemailPermissions; 584b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private VoicemailTable.Delegate mVoicemailContentTable; 599cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private VoicemailTable.Delegate mVoicemailStatusTable; 6052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 6152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 6252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee public boolean onCreate() { 6352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee Context context = context(); 6452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee mContentResolver = context.getContentResolver(); 65aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee mVoicemailPermissions = new VoicemailPermissions(context); 669cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee mVoicemailContentTable = new VoicemailContentTable(Tables.CALLS, context, 679cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee getDatabaseHelper(context), this); 689cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee mVoicemailStatusTable = new VoicemailStatusTable(Tables.VOICEMAIL_STATUS, context, 694b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee getDatabaseHelper(context), this); 7052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return true; 7152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 7252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 731975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee /*package for testing*/ ContactsDatabaseHelper getDatabaseHelper(Context context) { 741975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee return ContactsDatabaseHelper.getInstance(context); 751975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee } 761975b56a3368b4b7684429ffa79e7b9dbc35b475Debashish Chatterjee 7752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /*package for testing*/ Context context() { 7852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return getContext(); 7952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 8052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 8152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 8252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee public String getType(Uri uri) { 8352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee UriData uriData = null; 8452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee try { 854b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData = UriData.createUriData(uri); 8652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } catch (IllegalArgumentException ignored) { 8752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Special case: for illegal URIs, we return null rather than thrown an exception. 8852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 8952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 909cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).getType(uriData); 9152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 9252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 9352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 944b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int bulkInsert(Uri uri, ContentValues[] valuesArray) { 959cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri, valuesArray); 969cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).bulkInsert(uriData, valuesArray); 9752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 9852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 9952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 1004b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public Uri insert(Uri uri, ContentValues values) { 1019cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri, values); 1029cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).insert(uriData, values); 10352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 10452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 10552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee @Override 1064b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 1074b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String sortOrder) { 1084b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri); 1094b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 1104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionBuilder.addClause(getPackageRestrictionClause()); 1119cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).query(uriData, projection, selectionBuilder.build(), 1124b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionArgs, sortOrder); 11352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 11452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1154b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1164b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1179cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri, values); 1184b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 1194b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionBuilder.addClause(getPackageRestrictionClause()); 1209cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).update(uriData, values, selectionBuilder.build(), 1214b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionArgs); 12252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 12352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1254b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int delete(Uri uri, String selection, String[] selectionArgs) { 1264b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri); 1274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 1284b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee selectionBuilder.addClause(getPackageRestrictionClause()); 1299cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).delete(uriData, selectionBuilder.build(), selectionArgs); 13052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 13152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1324b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1334b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 1344b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri); 1354b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // openFileHelper() relies on "_data" column to be populated with the file path. 1369cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return getTableDelegate(uriData).openFile(uriData, mode); 1379cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 1389cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 1399cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Returns the correct table delegate object that can handle this URI. */ 1409cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private VoicemailTable.Delegate getTableDelegate(UriData uriData) { 1419cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee switch (uriData.getUriType()) { 1429cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS: 1439cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS_ID: 1449cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return mVoicemailStatusTable; 1459cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case VOICEMAILS: 1469cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case VOICEMAILS_ID: 1479cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return mVoicemailContentTable; 1489cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case NO_MATCH: 1499cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throw new IllegalStateException("Invalid uri type for uri: " + uriData.getUri()); 1509cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee default: 1519cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throw new IllegalStateException("Impossible, all cases are covered."); 1529cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 15352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 15452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 15552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 1564b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Decorates a URI by providing methods to get various properties from the URI. 15752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 1584b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public static class UriData { 1594b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final Uri mUri; 1604b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final String mId; 1614b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final String mSourcePackage; 1629cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private final VoicemailUriType mUriType; 16352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1649cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public UriData(Uri uri, VoicemailUriType uriType, String id, String sourcePackage) { 1659cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee mUriType = uriType; 1664b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mUri = uri; 1674b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mId = id; 1684b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mSourcePackage = sourcePackage; 16952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 17052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1714b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Gets the original URI to which this {@link UriData} corresponds. */ 1724b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final Uri getUri() { 1734b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mUri; 17452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 17552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1764b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Tells us if our URI has an individual voicemail id. */ 1774b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final boolean hasId() { 1784b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mId != null; 17952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 18052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1814b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Gets the ID for the voicemail. */ 1824b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final String getId() { 1834b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mId; 18452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 18552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1864b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Tells us if our URI has a source package string. */ 1874b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final boolean hasSourcePackage() { 1884b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mSourcePackage != null; 18952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 19052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1914b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Gets the source package. */ 1924b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public final String getSourcePackage() { 1934b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return mSourcePackage; 19452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 19552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1969cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Gets the Voicemail URI type. */ 1979cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public final VoicemailUriType getUriType() { 1989cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return mUriType; 1999cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2009cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2019cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Builds a where clause from the URI data. */ 2029cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public final String getWhereClause() { 2039cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return concatenateClauses( 2049cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee (hasId() ? getEqualityClause(BaseColumns._ID, getId()) : null), 2059cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee (hasSourcePackage() ? getEqualityClause(SOURCE_PACKAGE_FIELD, 2069cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee getSourcePackage()) : null)); 2079cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2089cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2094b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Create a {@link UriData} corresponding to a given uri. */ 2104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public static UriData createUriData(Uri uri) { 2114b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String sourcePackage = uri.getQueryParameter( 2124b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee VoicemailContract.PARAM_KEY_SOURCE_PACKAGE); 2134b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee List<String> segments = uri.getPathSegments(); 2149cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee VoicemailUriType uriType = createUriMatcher().match(uri); 2159cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee switch (uriType) { 2164b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee case VOICEMAILS: 2179cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS: 2189cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return new UriData(uri, uriType, null, sourcePackage); 2194b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee case VOICEMAILS_ID: 2209cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee case STATUS_ID: 2219cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return new UriData(uri, uriType, segments.get(1), sourcePackage); 2224b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee case NO_MATCH: 2234b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new IllegalArgumentException("Invalid URI: " + uri); 2244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee default: 2254b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new IllegalStateException("Impossible, all cases are covered"); 2264b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2289cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2299cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private static TypedUriMatcherImpl<VoicemailUriType> createUriMatcher() { 2309cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return new TypedUriMatcherImpl<VoicemailUriType>( 2319cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee VoicemailContract.AUTHORITY, VoicemailUriType.values()); 2329cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 23352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 23452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 2354b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2364b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // VoicemailTable.DelegateHelper interface. 2374b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public void notifyChange(Uri notificationUri, String... intentActions) { 23852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Notify the observers. 23952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee mContentResolver.notifyChange(notificationUri, null, true); 24042e8dddb940a502e97151a08f16b87aed7b30de5Debashish Chatterjee String callingPackage = getCallingPackage(); 24152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Fire notification intents. 24252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee for (String intentAction : intentActions) { 24352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // TODO: We can possibly be more intelligent here and send targeted intents based on 24452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // what voicemail permission the package has. If possible, here is what we would like to 24552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // do for a given broadcast intent - 24652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // 1) Send it to all packages that have READ_WRITE_ALL_VOICEMAIL permission. 24752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // 2) Send it to only the owner package that has just READ_WRITE_OWN_VOICEMAIL, if not 24852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // already sent in (1). 24906f995b614e0ebe59ff75f170e20ca96c9b17f0cDebashish Chatterjee for (ComponentName component : 25006f995b614e0ebe59ff75f170e20ca96c9b17f0cDebashish Chatterjee getBroadcastReceiverComponents(intentAction, notificationUri)) { 25142e8dddb940a502e97151a08f16b87aed7b30de5Debashish Chatterjee Intent intent = new Intent(intentAction, notificationUri); 25206f995b614e0ebe59ff75f170e20ca96c9b17f0cDebashish Chatterjee intent.setComponent(component); 25342e8dddb940a502e97151a08f16b87aed7b30de5Debashish Chatterjee intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE, 25406f995b614e0ebe59ff75f170e20ca96c9b17f0cDebashish Chatterjee callingPackage.equals(component.getPackageName())); 25542e8dddb940a502e97151a08f16b87aed7b30de5Debashish Chatterjee context().sendBroadcast(intent, Manifest.permission.READ_WRITE_OWN_VOICEMAIL); 25642e8dddb940a502e97151a08f16b87aed7b30de5Debashish Chatterjee } 25752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 25852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 25952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 2604b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2614b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // VoicemailTable.DelegateHelper interface. 2624b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public void checkAndAddSourcePackageIntoValues(UriData uriData, ContentValues values) { 2634b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // If content values don't contain the provider, calculate the right provider to use. 2649cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (!values.containsKey(SOURCE_PACKAGE_FIELD)) { 2654b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String provider = uriData.hasSourcePackage() ? 2664b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData.getSourcePackage() : getCallingPackage(); 2679cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee values.put(SOURCE_PACKAGE_FIELD, provider); 2684b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2694b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // You must have access to the provider given in values. 2704b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (!mVoicemailPermissions.callerHasFullAccess()) { 2714b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee checkPackagesMatch(getCallingPackage(), 2724b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD), 2734b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData.getUri()); 274975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee } 275975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee } 276975d52af754e6f05089fcd9f7066df05c290c3b7Debashish Chatterjee 2779cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** 2789cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * Checks that the source_package field is same in uriData and ContentValues, if it happens 2799cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * to be set in both. 2809cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee */ 2819cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private void checkSourcePackageSameIfSet(UriData uriData, ContentValues values) { 2829cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (uriData.hasSourcePackage() && values.containsKey(SOURCE_PACKAGE_FIELD)) { 2839cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (!uriData.getSourcePackage().equals(values.get(SOURCE_PACKAGE_FIELD))) { 2849cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throw new SecurityException( 2859cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee "source_package in URI was " + uriData.getSourcePackage() + 2869cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee " but doesn't match source_package in ContentValues which was " 2879cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee + values.get(SOURCE_PACKAGE_FIELD)); 2889cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2899cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2909cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 2919cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 2929cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee @Override 2939cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** Implementation of {@link VoicemailTable.DelegateHelper#openDataFile(UriData, String)} */ 2949cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public ParcelFileDescriptor openDataFile(UriData uriData, String mode) 2959cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throws FileNotFoundException { 2969cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return openFileHelper(uriData.getUri(), mode); 29752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 29852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 29952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 3004b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Performs necessary voicemail permission checks common to all operations and returns 3014b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * the structured representation, {@link UriData}, of the supplied uri. 30252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 3034b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private UriData checkPermissionsAndCreateUriData(Uri uri) { 3044b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mVoicemailPermissions.checkCallerHasOwnVoicemailAccess(); 3054b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee UriData uriData = UriData.createUriData(uri); 3064b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee checkPackagePermission(uriData); 3074b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return uriData; 3084b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 30952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 3104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** 3119cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * Same as {@link #checkPackagePermission(UriData)}. In addition does permission check 3129cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * on the ContentValues. 3139cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee */ 3149cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private UriData checkPermissionsAndCreateUriData(Uri uri, ContentValues... valuesArray) { 3159cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee UriData uriData = checkPermissionsAndCreateUriData(uri); 3169cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee for (ContentValues values : valuesArray) { 3179cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee checkSourcePackageSameIfSet(uriData, values); 3189cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 3199cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee return uriData; 3209cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee } 3219cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee 3229cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee /** 3239cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * Checks that the callingPackage is same as voicemailSourcePackage. Throws {@link 3244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * SecurityException} if they don't match. 3254b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee */ 3269cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee private final void checkPackagesMatch(String callingPackage, String voicemailSourcePackage, 3274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Uri uri) { 3289cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee if (!voicemailSourcePackage.equals(callingPackage)) { 3294b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String errorMsg = String.format("Permission denied for URI: %s\n. " + 3309cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee "Package %s cannot perform this operation for %s. Requires %s permission.", 3319cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee uri, callingPackage, voicemailSourcePackage, 3324b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Manifest.permission.READ_WRITE_ALL_VOICEMAIL); 3334b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new SecurityException(errorMsg); 33452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 33552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 33652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 33752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 33852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Checks that either the caller has READ_WRITE_ALL_VOICEMAIL permission, or has the 33952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * READ_WRITE_OWN_VOICEMAIL permission and is using a URI that matches 3409cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee * /voicemail/?source_package=[source-package] where [source-package] is the same as the calling 34152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * package. 34252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 34352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * @throws SecurityException if the check fails. 34452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 34552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private void checkPackagePermission(UriData uriData) { 346aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (!mVoicemailPermissions.callerHasFullAccess()) { 34752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (!uriData.hasSourcePackage()) { 3489cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee // You cannot have a match if this is not a provider URI. 34952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee throw new SecurityException(String.format( 35052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee "Provider %s does not have %s permission." + 3514b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee "\nPlease set query parameter '%s' in the URI.\nURI: %s", 35252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee getCallingPackage(), Manifest.permission.READ_WRITE_ALL_VOICEMAIL, 3534b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee VoicemailContract.PARAM_KEY_SOURCE_PACKAGE, uriData.getUri())); 35452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 35552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee checkPackagesMatch(getCallingPackage(), uriData.getSourcePackage(), uriData.getUri()); 35652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 35752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 35852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 35952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 36052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Gets the name of the calling package. 36152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * <p> 36252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * It's possible (though unlikely) for there to be more than one calling package (requires that 36352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * your manifest say you want to share process ids) in which case we will return an arbitrary 36452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * package name. It's also possible (though very unlikely) for us to be unable to work out what 36552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * your calling package is, in which case we will return null. 36652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 36752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /* package for test */String getCallingPackage() { 36852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee int caller = Binder.getCallingUid(); 36952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (caller == 0) { 37052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 37152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 37252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee String[] callerPackages = context().getPackageManager().getPackagesForUid(caller); 37352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (callerPackages == null || callerPackages.length == 0) { 37452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 37552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 37652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (callerPackages.length == 1) { 37752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return callerPackages[0]; 37852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 37952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // If we have more than one caller package, which is very unlikely, let's return the one 38052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // with the highest permissions. If more than one has the same permission, we don't care 38152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // which one we return. 38252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee String bestSoFar = callerPackages[0]; 38352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee for (String callerPackage : callerPackages) { 384aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (mVoicemailPermissions.packageHasFullAccess(callerPackage)) { 38552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Full always wins, we can return early. 38652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return callerPackage; 38752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 388aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (mVoicemailPermissions.packageHasOwnVoicemailAccess(callerPackage)) { 38952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee bestSoFar = callerPackage; 39052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 39152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 39252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return bestSoFar; 39352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 39452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 39552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** 39652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Creates a clause to restrict the selection to the calling provider or null if the caller has 39752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * access to all data. 39852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 39952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private String getPackageRestrictionClause() { 400aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (mVoicemailPermissions.callerHasFullAccess()) { 40152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return null; 40252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 40352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return getEqualityClause(Voicemails.SOURCE_PACKAGE, getCallingPackage()); 40452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 40552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 4064b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Determines the components that can possibly receive the specified intent. */ 4074b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee protected List<ComponentName> getBroadcastReceiverComponents(String intentAction, Uri uri) { 4084b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Intent intent = new Intent(intentAction, uri); 4094b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee List<ComponentName> receiverComponents = new ArrayList<ComponentName>(); 4104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // For broadcast receivers ResolveInfo.activityInfo is the one that is populated. 4114b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee for (ResolveInfo resolveInfo : 4124b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee context().getPackageManager().queryBroadcastReceivers(intent, 0)) { 4134b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee ActivityInfo activityInfo = resolveInfo.activityInfo; 4144b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee receiverComponents.add(new ComponentName(activityInfo.packageName, activityInfo.name)); 4154b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 4164b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return receiverComponents; 41752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 41852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee} 419