diff options
5 files changed, 125 insertions, 21 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index bb8158a..bc8ddea 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3,18 +3,19 @@ android:sharedUserId="android.uid.shared" android:sharedUserLabel="@string/sharedUserLabel"> - <uses-permission android:name="android.permission.READ_CONTACTS" /> - <uses-permission android:name="android.permission.WRITE_CONTACTS" /> - <uses-permission android:name="android.permission.READ_PROFILE" /> - <uses-permission android:name="android.permission.WRITE_PROFILE" /> - <uses-permission android:name="android.permission.GET_ACCOUNTS" /> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.BIND_DIRECTORY_SEARCH" /> - <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> - <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> + <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> + <uses-permission android:name="android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION" /> + <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.READ_PROFILE" /> + <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> + <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> + <uses-permission android:name="android.permission.WRITE_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_PROFILE" /> <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" /> <uses-permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL" /> <uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" /> @@ -71,6 +72,14 @@ </intent-filter> </receiver> + <receiver android:name="PhoneAccountRegistrationReceiver" + android:permission="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION"> + <!-- Broadcast sent after a phone account is registered in telecom. --> + <intent-filter> + <action android:name="android.telecom.action.PHONE_ACCOUNT_REGISTERED"/> + </intent-filter> + </receiver> + <receiver android:name="PackageIntentReceiver"> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> diff --git a/src/com/android/providers/contacts/CallLogBackupAgent.java b/src/com/android/providers/contacts/CallLogBackupAgent.java index 8e160c8..6de5a5e 100644 --- a/src/com/android/providers/contacts/CallLogBackupAgent.java +++ b/src/com/android/providers/contacts/CallLogBackupAgent.java @@ -289,8 +289,8 @@ public class CallLogBackupAgent extends BackupAgent { call.type = dataInput.readInt(); call.numberPresentation = dataInput.readInt(); call.accountComponentName = readString(dataInput, version); - call.accountId = dataInput.readUTF(); - call.accountAddress = dataInput.readUTF(); + call.accountId = readString(dataInput, version); + call.accountAddress = readString(dataInput, version); call.dataUsage = dataInput.readLong(); call.features = dataInput.readInt(); } diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java index 6bf913e..1899393 100644 --- a/src/com/android/providers/contacts/CallLogProvider.java +++ b/src/com/android/providers/contacts/CallLogProvider.java @@ -39,6 +39,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.CallLog; import android.provider.CallLog.Calls; +import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import android.util.Log; @@ -46,7 +47,6 @@ import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties; import com.android.providers.contacts.ContactsDatabaseHelper.Tables; import com.android.providers.contacts.util.SelectionBuilder; import com.android.providers.contacts.util.UserUtils; - import com.google.common.annotations.VisibleForTesting; import java.util.HashMap; @@ -60,12 +60,16 @@ public class CallLogProvider extends ContentProvider { private static final String TAG = CallLogProvider.class.getSimpleName(); private static final int BACKGROUND_TASK_INITIALIZE = 0; + private static final int BACKGROUND_TASK_ADJUST_PHONE_ACCOUNT = 1; /** Selection clause for selecting all calls that were made after a certain time */ private static final String MORE_RECENT_THAN_SELECTION = Calls.DATE + "> ?"; /** Selection clause to use to exclude voicemail records. */ private static final String EXCLUDE_VOICEMAIL_SELECTION = getInequalityClause( Calls.TYPE, Calls.VOICEMAIL_TYPE); + /** Selection clause to exclude hidden records. */ + private static final String EXCLUDE_HIDDEN_SELECTION = getEqualityClause( + Calls.PHONE_ACCOUNT_HIDDEN, 0); @VisibleForTesting static final String[] CALL_LOG_SYNC_PROJECTION = new String[] { @@ -86,6 +90,10 @@ public class CallLogProvider extends ContentProvider { private static final int CALLS_FILTER = 3; + private static final String ADJUST_FOR_NEW_PHONE_ACCOUNT_QUERY = + "UPDATE " + Tables.CALLS + " SET " + Calls.PHONE_ACCOUNT_HIDDEN + "=0 WHERE " + + Calls.PHONE_ACCOUNT_COMPONENT_NAME + "=? AND " + Calls.PHONE_ACCOUNT_ID + "=?;"; + private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sURIMatcher.addURI(CallLog.AUTHORITY, "calls", CALLS); @@ -109,6 +117,7 @@ public class CallLogProvider extends ContentProvider { sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_COMPONENT_NAME, Calls.PHONE_ACCOUNT_COMPONENT_NAME); sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ID, Calls.PHONE_ACCOUNT_ID); sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ADDRESS, Calls.PHONE_ACCOUNT_ADDRESS); + sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_HIDDEN, Calls.PHONE_ACCOUNT_HIDDEN); sCallsProjectionMap.put(Calls.NEW, Calls.NEW); sCallsProjectionMap.put(Calls.VOICEMAIL_URI, Calls.VOICEMAIL_URI); sCallsProjectionMap.put(Calls.TRANSCRIPTION, Calls.TRANSCRIPTION); @@ -155,13 +164,13 @@ public class CallLogProvider extends ContentProvider { mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { @Override public void handleMessage(Message msg) { - performBackgroundTask(msg.what); + performBackgroundTask(msg.what, msg.obj); } }; mReadAccessLatch = new CountDownLatch(1); - scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); + scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE, null); if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { Log.d(Constants.PERFORMANCE_TAG, "CallLogProvider.onCreate finish"); @@ -190,6 +199,7 @@ public class CallLogProvider extends ContentProvider { final SelectionBuilder selectionBuilder = new SelectionBuilder(selection); checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder, true /*isQuery*/); + selectionBuilder.addClause(EXCLUDE_HIDDEN_SELECTION); final int match = sURIMatcher.match(uri); switch (match) { @@ -357,6 +367,10 @@ public class CallLogProvider extends ContentProvider { return getContext(); } + void adjustForNewPhoneAccount(PhoneAccountHandle handle) { + scheduleBackgroundTask(BACKGROUND_TASK_ADJUST_PHONE_ACCOUNT, handle); + } + /** * Returns a {@link DatabaseModifier} that takes care of sending necessary notifications * after the operation is performed. @@ -467,6 +481,16 @@ public class CallLogProvider extends ContentProvider { } /** + * Un-hides any hidden call log entries that are associated with the specified handle. + * + * @param handle The handle to the newly registered {@link android.telecom.PhoneAccount}. + */ + private void adjustForNewPhoneAccountInternal(PhoneAccountHandle handle) { + mDbHelper.getWritableDatabase().execSQL(ADJUST_FOR_NEW_PHONE_ACCOUNT_QUERY, + new String[] { handle.getComponentName().flattenToString(), handle.getId() }); + } + + /** * @param cursor to copy call log entries from * * @return the timestamp of the last synced entry. @@ -544,11 +568,11 @@ public class CallLogProvider extends ContentProvider { } } - private void scheduleBackgroundTask(int task) { - mBackgroundHandler.sendEmptyMessage(task); + private void scheduleBackgroundTask(int task, Object arg) { + mBackgroundHandler.obtainMessage(task, arg).sendToTarget(); } - private void performBackgroundTask(int task) { + private void performBackgroundTask(int task, Object arg) { if (task == BACKGROUND_TASK_INITIALIZE) { try { final Context context = getContext(); @@ -563,6 +587,8 @@ public class CallLogProvider extends ContentProvider { mReadAccessLatch.countDown(); mReadAccessLatch = null; } + } else if (task == BACKGROUND_TASK_ADJUST_PHONE_ACCOUNT) { + adjustForNewPhoneAccountInternal((PhoneAccountHandle) arg); } } diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java index fc4d343..1fe874a 100644 --- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java +++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java @@ -16,15 +16,14 @@ package com.android.providers.contacts; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.UserInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.CharArrayBuffer; import android.database.Cursor; @@ -90,12 +89,12 @@ import com.android.providers.contacts.util.NeededForTesting; import com.google.android.collect.Sets; import com.google.common.annotations.VisibleForTesting; +import libcore.icu.ICU; + import java.util.Locale; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import libcore.icu.ICU; - /** * Database helper for contacts. Designed as a singleton to make sure that all * {@link android.content.ContentProvider} users get the same reference. @@ -121,7 +120,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { * 1000-1100 M * </pre> */ - static final int DATABASE_VERSION = 1003; + static final int DATABASE_VERSION = 1004; public interface Tables { public static final String CONTACTS = "contacts"; @@ -1519,6 +1518,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { Calls.PHONE_ACCOUNT_COMPONENT_NAME + " TEXT," + Calls.PHONE_ACCOUNT_ID + " TEXT," + Calls.PHONE_ACCOUNT_ADDRESS + " TEXT," + + Calls.PHONE_ACCOUNT_HIDDEN + " INTEGER NOT NULL DEFAULT 0," + Calls.SUB_ID + " INTEGER DEFAULT -1," + Calls.NEW + " INTEGER," + Calls.CACHED_NAME + " TEXT," + @@ -2881,6 +2881,11 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { oldVersion = 1003; } + if (oldVersion < 1004) { + upgradeToVersion1004(db); + oldVersion = 1004; + } + if (upgradeViewsAndTriggers) { createContactsViews(db); createGroupsView(db); @@ -4374,6 +4379,14 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { } } + /** + * Add a "hidden" column for call log entries we want to hide after an upgrade until the user + * adds the right phone account to the device. + */ + public void upgradeToVersion1004(SQLiteDatabase db) { + db.execSQL("ALTER TABLE calls ADD phone_account_hidden INTEGER NOT NULL DEFAULT 0;"); + } + public String extractHandleFromEmailAddress(String email) { Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); if (tokens.length == 0) { diff --git a/src/com/android/providers/contacts/PhoneAccountRegistrationReceiver.java b/src/com/android/providers/contacts/PhoneAccountRegistrationReceiver.java new file mode 100644 index 0000000..8a68889 --- /dev/null +++ b/src/com/android/providers/contacts/PhoneAccountRegistrationReceiver.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.providers.contacts; + +import android.content.BroadcastReceiver; +import android.content.ContentProvider; +import android.content.Context; +import android.content.IContentProvider; +import android.content.Intent; +import android.provider.CallLog; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; + +/** + * This will be launched when a new phone account is registered in telecom. It is used by the call + * log to un-hide any entries which were previously hidden after a backup-restore until it's + * associated phone-account is registered with telecom. + * + * IOW, after a restore, we hide call log entries until the user inserts the corresponding SIM, + * registers the corresponding SIP account, or registers a corresponding alternative phone-account. + */ +public class PhoneAccountRegistrationReceiver extends BroadcastReceiver { + static final String TAG = "PhoneAccountReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + // We are now running with the system up, but no apps started, + // so can do whatever cleanup after an upgrade that we want. + if (TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED.equals(intent.getAction())) { + + PhoneAccountHandle handle = (PhoneAccountHandle) intent.getParcelableExtra( + TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE); + + IContentProvider iprovider = + context.getContentResolver().acquireProvider(CallLog.AUTHORITY); + ContentProvider provider = ContentProvider.coerceToLocalContentProvider(iprovider); + if (provider instanceof CallLogProvider) { + ((CallLogProvider) provider).adjustForNewPhoneAccount(handle); + } + } + } +} |