DbModifierWithNotification.java revision 2e757d904e62dbf5bc0b028626fa9319ccc38c45
1929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee/* 2929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * Copyright (C) 2011 The Android Open Source Project 3929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 4929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * 5929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * Licensed under the Apache License, Version 2.0 (the "License"); 6929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * you may not use this file except in compliance with the License. 7929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * You may obtain a copy of the License at 8929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * 9929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * http://www.apache.org/licenses/LICENSE-2.0 10929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * 11929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * Unless required by applicable law or agreed to in writing, software 12929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * distributed under the License is distributed on an "AS IS" BASIS, 13929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * See the License for the specific language governing permissions and 15929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * limitations under the License 16929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee */ 17929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 18929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeepackage com.android.providers.contacts; 19929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 2098a77ec8057c5fe0ff487ca7d0910312693e5689Debashish Chatterjeeimport static android.Manifest.permission.ADD_VOICEMAIL; 21929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport static com.android.providers.contacts.Manifest.permission.READ_WRITE_ALL_VOICEMAIL; 22929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 2313cb841466fefcd041cd86b7877d000dfe73e8ecDebashish Chatterjeeimport com.android.common.io.MoreCloseables; 24929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 25929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport com.android.providers.contacts.util.DbQueryUtils; 26929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport com.google.android.collect.Lists; 27929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 28929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.ComponentName; 29929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.ContentUris; 30929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.ContentValues; 31929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.Context; 32929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.Intent; 33929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.pm.ActivityInfo; 34929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.content.pm.ResolveInfo; 35929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.database.Cursor; 36929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.database.DatabaseUtils.InsertHelper; 37929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.database.sqlite.SQLiteDatabase; 38929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.net.Uri; 39929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.os.Binder; 402e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjeeimport android.provider.CallLog.Calls; 41929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.provider.VoicemailContract; 42929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.provider.VoicemailContract.Status; 43929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.provider.VoicemailContract.Voicemails; 44929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport android.util.Log; 45929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 46929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport java.util.ArrayList; 47929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport java.util.Collection; 48929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport java.util.HashSet; 49929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport java.util.List; 50929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjeeimport java.util.Set; 51929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 52929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee/** 53929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * An implementation of {@link DatabaseModifier} for voicemail related tables which additionally 54929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * generates necessary notifications after the modification operation is performed. 552e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee * The class generates notifications for both voicemail as well as call log URI depending on which 562e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee * of then got affected by the change. 57929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee */ 582e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjeepublic class DbModifierWithNotification implements DatabaseModifier { 59929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private static final String TAG = "DbModifierWithVmNotification"; 60929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 61929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private static final String[] PROJECTION = new String[] { 62929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee VoicemailContract.SOURCE_PACKAGE_FIELD 63929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee }; 64929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private static final int SOURCE_PACKAGE_COLUMN_INDEX = 0; 65929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private static final String NON_NULL_SOURCE_PACKAGE_SELECTION = 66929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee VoicemailContract.SOURCE_PACKAGE_FIELD + " IS NOT NULL"; 67929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 68929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private final String mTableName; 69929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private final SQLiteDatabase mDb; 70929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private final InsertHelper mInsertHelper; 71929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private final Context mContext; 72929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private final Uri mBaseUri; 732e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee private final boolean mIsCallsTable; 74929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private final VoicemailPermissions mVoicemailPermissions; 75929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 762e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee public DbModifierWithNotification(String tableName, SQLiteDatabase db, Context context) { 77929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee this(tableName, db, null, context); 78929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 79929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 802e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee public DbModifierWithNotification(String tableName, InsertHelper insertHelper, 81929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Context context) { 82929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee this(tableName, null, insertHelper, context); 83929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 84929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 852e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee private DbModifierWithNotification(String tableName, SQLiteDatabase db, 86929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee InsertHelper insertHelper, Context context) { 87929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mTableName = tableName; 88929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mDb = db; 89929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mInsertHelper = insertHelper; 90929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mContext = context; 91929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mBaseUri = mTableName.equals(Tables.VOICEMAIL_STATUS) ? 92929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Status.CONTENT_URI : Voicemails.CONTENT_URI; 932e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee mIsCallsTable = mTableName.equals(Tables.CALLS); 94929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mVoicemailPermissions = new VoicemailPermissions(mContext); 95929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 96929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 97929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee @Override 98929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee public long insert(String table, String nullColumnHack, ContentValues values) { 99929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Set<String> packagesModified = getModifiedPackages(values); 100929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee long rowId = mDb.insert(table, nullColumnHack, values); 101929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if (rowId > 0 && packagesModified.size() != 0) { 1022e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyVoicemailChangeOnInsert(ContentUris.withAppendedId(mBaseUri, rowId), 1032e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee packagesModified); 1042e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee } 1052e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee if (rowId > 0 && mIsCallsTable) { 1062e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyCallLogChange(); 107929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 108929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return rowId; 109929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 110929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 111929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee @Override 112929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee public long insert(ContentValues values) { 113929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Set<String> packagesModified = getModifiedPackages(values); 114929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee long rowId = mInsertHelper.insert(values); 115929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if (rowId > 0 && packagesModified.size() != 0) { 1162e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyVoicemailChangeOnInsert( 1172e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee ContentUris.withAppendedId(mBaseUri, rowId), packagesModified); 1182e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee } 1192e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee if (rowId > 0 && mIsCallsTable) { 1202e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyCallLogChange(); 121929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 122929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return rowId; 123929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 124929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 1252e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee private void notifyCallLogChange() { 1262e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee mContext.getContentResolver().notifyChange(Calls.CONTENT_URI, null, false); 1272e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee } 1282e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee 1292e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee private void notifyVoicemailChangeOnInsert(Uri notificationUri, Set<String> packagesModified) { 1302e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee if (mIsCallsTable) { 1312e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyVoicemailChange(notificationUri, packagesModified, 1322e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee VoicemailContract.ACTION_NEW_VOICEMAIL, Intent.ACTION_PROVIDER_CHANGED); 133929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } else { 1342e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyVoicemailChange(notificationUri, packagesModified, 1352e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee Intent.ACTION_PROVIDER_CHANGED); 136929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 137929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 138929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 139929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee @Override 140929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { 141929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs); 142929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee packagesModified.addAll(getModifiedPackages(values)); 143929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee int count = mDb.update(table, values, whereClause, whereArgs); 144929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if (count > 0 && packagesModified.size() != 0) { 1452e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyVoicemailChange(mBaseUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED); 1462e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee } 1472e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee if (count > 0 && mIsCallsTable) { 1482e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyCallLogChange(); 149929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 150929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return count; 151929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 152929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 153929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee @Override 154929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee public int delete(String table, String whereClause, String[] whereArgs) { 155929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs); 156929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee int count = mDb.delete(table, whereClause, whereArgs); 157929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if (count > 0 && packagesModified.size() != 0) { 1582e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyVoicemailChange(mBaseUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED); 1592e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee } 1602e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee if (count > 0 && mIsCallsTable) { 1612e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee notifyCallLogChange(); 162929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 163929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return count; 164929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 165929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 166929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee /** 167929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * Returns the set of packages affected when a modify operation is run for the specified 168929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * where clause. When called from an insert operation an empty set returned by this method 169929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * implies (indirectly) that this does not affect any voicemail entry, as a voicemail entry is 170929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * always expected to have the source package field set. 171929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee */ 172929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private Set<String> getModifiedPackages(String whereClause, String[] whereArgs) { 173929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Set<String> modifiedPackages = new HashSet<String>(); 174929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Cursor cursor = mDb.query(mTableName, PROJECTION, 175929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee DbQueryUtils.concatenateClauses(NON_NULL_SOURCE_PACKAGE_SELECTION, whereClause), 176929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee whereArgs, null, null, null); 177929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee while(cursor.moveToNext()) { 178929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee modifiedPackages.add(cursor.getString(SOURCE_PACKAGE_COLUMN_INDEX)); 179929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 18013cb841466fefcd041cd86b7877d000dfe73e8ecDebashish Chatterjee MoreCloseables.closeQuietly(cursor); 181929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return modifiedPackages; 182929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 183929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 184929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee /** 185929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * Returns the source package that gets affected (in an insert/update operation) by the supplied 186929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * content values. An empty set returned by this method also implies (indirectly) that this does 187929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * not affect any voicemail entry, as a voicemail entry is always expected to have the source 188929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * package field set. 189929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee */ 190929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private Set<String> getModifiedPackages(ContentValues values) { 191929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Set<String> impactedPackages = new HashSet<String>(); 192929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if(values.containsKey(VoicemailContract.SOURCE_PACKAGE_FIELD)) { 193929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee impactedPackages.add(values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD)); 194929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 195929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return impactedPackages; 196929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 197929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 1982e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee private void notifyVoicemailChange(Uri notificationUri, Set<String> modifiedPackages, 199929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee String... intentActions) { 200929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // Notify the observers. 201929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // Must be done only once, even if there are multiple broadcast intents. 202929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mContext.getContentResolver().notifyChange(notificationUri, null, true); 203929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Collection<String> callingPackages = getCallingPackages(); 204929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // Now fire individual intents. 205929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee for (String intentAction : intentActions) { 206929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // self_change extra should be included only for provider_changed events. 207929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee boolean includeSelfChangeExtra = intentAction.equals(Intent.ACTION_PROVIDER_CHANGED); 208929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee for (ComponentName component : 209929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee getBroadcastReceiverComponents(intentAction, notificationUri)) { 2108d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee // Ignore any package that is not affected by the change and don't have full access 2118d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee // either. 2128d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee if (!modifiedPackages.contains(component.getPackageName()) && 2138d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee !mVoicemailPermissions.packageHasFullAccess(component.getPackageName())) { 2148d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee continue; 2158d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee } 2168d5a094810ce8c60b83e534d903a0d662e621252Debashish Chatterjee 217929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Intent intent = new Intent(intentAction, notificationUri); 218929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee intent.setComponent(component); 219929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if (includeSelfChangeExtra && callingPackages != null) { 220929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE, 221929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee callingPackages.contains(component.getPackageName())); 222929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 223929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee String permissionNeeded = modifiedPackages.contains(component.getPackageName()) ? 22498a77ec8057c5fe0ff487ca7d0910312693e5689Debashish Chatterjee ADD_VOICEMAIL : READ_WRITE_ALL_VOICEMAIL; 225929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mContext.sendBroadcast(intent, permissionNeeded); 226929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s, perm:%s," + 227929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee " self_change:%s", intent.getAction(), intent.getData(), 228929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee component.getClassName(), permissionNeeded, 229929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee intent.hasExtra(VoicemailContract.EXTRA_SELF_CHANGE) ? 230929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false) : 231929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee null)); 232929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 233929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 234929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 235929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 236929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee /** Determines the components that can possibly receive the specified intent. */ 237929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private List<ComponentName> getBroadcastReceiverComponents(String intentAction, Uri uri) { 238929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee Intent intent = new Intent(intentAction, uri); 239929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee List<ComponentName> receiverComponents = new ArrayList<ComponentName>(); 240929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // For broadcast receivers ResolveInfo.activityInfo is the one that is populated. 241929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee for (ResolveInfo resolveInfo : 242929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee mContext.getPackageManager().queryBroadcastReceivers(intent, 0)) { 243929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee ActivityInfo activityInfo = resolveInfo.activityInfo; 244929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee receiverComponents.add(new ComponentName(activityInfo.packageName, activityInfo.name)); 245929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 246929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return receiverComponents; 247929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 248929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 249929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee /** 250929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * Returns the package names of the calling process. If the calling process has more than 251929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee * one packages, this returns them all 252929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee */ 253929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private Collection<String> getCallingPackages() { 254929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee int caller = Binder.getCallingUid(); 255929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee if (caller == 0) { 256929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return null; 257929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 258929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return Lists.newArrayList(mContext.getPackageManager().getPackagesForUid(caller)); 259929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 260929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee} 261