resolve merge conflicts of 253b129 to nyc-mr1-dev-plus-aosp
Change-Id: I9d37a418982377eb1b94596998e22467d6c86402
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 80f1da2..64e266d 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -172,7 +172,8 @@
new LogCallCompletedListener() {
@Override
public void onLogCompleted(@Nullable Uri uri) {
- mMissedCallNotifier.showMissedCallNotification(call);
+ mMissedCallNotifier.showMissedCallNotification(
+ new MissedCallNotifier.CallInfo(call));
}
});
} else {
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index fefca78..5318f16 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -410,7 +410,8 @@
result.shouldShowNotification);
} else if (result.shouldShowNotification) {
Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
- mMissedCallNotifier.showMissedCallNotification(incomingCall);
+ mMissedCallNotifier.showMissedCallNotification(
+ new MissedCallNotifier.CallInfo(incomingCall));
}
}
}
@@ -2112,8 +2113,13 @@
}
private void reloadMissedCallsOfUser(UserHandle userHandle) {
- mMissedCallNotifier.reloadFromDatabase(
- mLock, this, mContactsAsyncHelper, mCallerInfoAsyncQueryFactory, userHandle);
+ mMissedCallNotifier.reloadFromDatabase(mCallerInfoLookupHelper,
+ new MissedCallNotifier.CallInfoFactory(), userHandle);
+ }
+
+ public void onBootCompleted() {
+ mMissedCallNotifier.reloadAfterBootComplete(mCallerInfoLookupHelper,
+ new MissedCallNotifier.CallInfoFactory());
}
/**
diff --git a/src/com/android/server/telecom/MissedCallNotifier.java b/src/com/android/server/telecom/MissedCallNotifier.java
index 1125a8e..500122b 100644
--- a/src/com/android/server/telecom/MissedCallNotifier.java
+++ b/src/com/android/server/telecom/MissedCallNotifier.java
@@ -16,23 +16,82 @@
package com.android.server.telecom;
+import android.net.Uri;
import android.os.UserHandle;
+import android.telecom.PhoneAccountHandle;
+
+import com.android.internal.telephony.CallerInfo;
/**
* Creates a notification for calls that the user missed (neither answered nor rejected).
*/
public interface MissedCallNotifier extends CallsManager.CallsManagerListener {
+ class CallInfoFactory {
+ public CallInfo makeCallInfo(CallerInfo callerInfo, PhoneAccountHandle phoneAccountHandle,
+ Uri handle, long creationTimeMillis) {
+ return new CallInfo(callerInfo, phoneAccountHandle, handle, creationTimeMillis);
+ }
+ }
+
+ class CallInfo {
+ private CallerInfo mCallerInfo;
+ private PhoneAccountHandle mPhoneAccountHandle;
+ private Uri mHandle;
+ private long mCreationTimeMillis;
+
+ public CallInfo(CallerInfo callerInfo, PhoneAccountHandle phoneAccountHandle, Uri handle,
+ long creationTimeMillis) {
+ mCallerInfo = callerInfo;
+ mPhoneAccountHandle = phoneAccountHandle;
+ mHandle = handle;
+ mCreationTimeMillis = creationTimeMillis;
+ }
+
+ public CallInfo(Call call) {
+ mCallerInfo = call.getCallerInfo();
+ mPhoneAccountHandle = call.getTargetPhoneAccount();
+ mHandle = call.getHandle();
+ mCreationTimeMillis = call.getCreationTimeMillis();
+ }
+
+ public CallerInfo getCallerInfo() {
+ return mCallerInfo;
+ }
+
+ public PhoneAccountHandle getPhoneAccountHandle() {
+ return mPhoneAccountHandle;
+ }
+
+ public Uri getHandle() {
+ return mHandle;
+ }
+
+ public String getHandleSchemeSpecificPart() {
+ return mHandle == null ? null : mHandle.getSchemeSpecificPart();
+ }
+
+ public long getCreationTimeMillis() {
+ return mCreationTimeMillis;
+ }
+
+ public String getPhoneNumber() {
+ return mCallerInfo == null ? null : mCallerInfo.phoneNumber;
+ }
+
+ public String getName() {
+ return mCallerInfo == null ? null : mCallerInfo.name;
+ }
+ }
void clearMissedCalls(UserHandle userHandle);
- void showMissedCallNotification(Call call);
+ void showMissedCallNotification(CallInfo call);
- void reloadFromDatabase(
- TelecomSystem.SyncRoot lock,
- CallsManager callsManager,
- ContactsAsyncHelper contactsAsyncHelper,
- CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
- UserHandle userHandle);
+ void reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper,
+ CallInfoFactory callInfoFactory);
+
+ void reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper,
+ CallInfoFactory callInfoFactory, UserHandle userHandle);
void setCurrentUserHandle(UserHandle userHandle);
}
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 24d925d..d665a82 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -38,7 +38,7 @@
/**
* Top-level Application class for Telecom.
*/
-public final class TelecomSystem {
+public class TelecomSystem {
/**
* This interface is implemented by system-instantiated components (e.g., Services and
@@ -68,6 +68,9 @@
private static final IntentFilter USER_STARTING_FILTER =
new IntentFilter(Intent.ACTION_USER_STARTING);
+ private static final IntentFilter BOOT_COMPLETE_FILTER =
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+
/** Intent filter for dialer secret codes. */
private static final IntentFilter DIALER_SECRET_CODE_FILTER;
@@ -102,15 +105,19 @@
private final ContactsAsyncHelper mContactsAsyncHelper;
private final DialerCodeReceiver mDialerCodeReceiver;
+ private boolean mIsBootComplete = false;
+
private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.startSession("TSSwR.oR");
try {
- int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
- UserHandle currentUserHandle = new UserHandle(userHandleId);
- mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
- mCallsManager.onUserSwitch(currentUserHandle);
+ synchronized (mLock) {
+ int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ UserHandle currentUserHandle = new UserHandle(userHandleId);
+ mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
+ mCallsManager.onUserSwitch(currentUserHandle);
+ }
} finally {
Log.endSession();
}
@@ -122,9 +129,26 @@
public void onReceive(Context context, Intent intent) {
Log.startSession("TSStR.oR");
try {
- int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
- UserHandle addingUserHandle = new UserHandle(userHandleId);
- mCallsManager.onUserStarting(addingUserHandle);
+ synchronized (mLock) {
+ int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ UserHandle addingUserHandle = new UserHandle(userHandleId);
+ mCallsManager.onUserStarting(addingUserHandle);
+ }
+ } finally {
+ Log.endSession();
+ }
+ }
+ };
+
+ private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.startSession("TSBCR.oR");
+ try {
+ synchronized (mLock) {
+ mIsBootComplete = true;
+ mCallsManager.onBootCompleted();
+ }
} finally {
Log.endSession();
}
@@ -137,7 +161,7 @@
public static void setInstance(TelecomSystem instance) {
if (INSTANCE != null) {
- throw new RuntimeException("Attempt to set TelecomSystem.INSTANCE twice");
+ Log.w("TelecomSystem", "Attempt to set TelecomSystem.INSTANCE twice");
}
Log.i(TelecomSystem.class, "TelecomSystem.INSTANCE being set");
INSTANCE = instance;
@@ -177,8 +201,7 @@
SystemStateProvider systemStateProvider = new SystemStateProvider(mContext);
mMissedCallNotifier = missedCallNotifierImplFactory
- .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar,
- phoneNumberUtilsAdapter);
+ .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar);
DefaultDialerManagerAdapter defaultDialerAdapter =
new TelecomServiceImpl.DefaultDialerManagerAdapterImpl();
@@ -208,6 +231,7 @@
mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
mContext.registerReceiver(mUserStartingReceiver, USER_STARTING_FILTER);
+ mContext.registerReceiver(mBootCompletedReceiver, BOOT_COMPLETE_FILTER);
mBluetoothPhoneServiceImpl = bluetoothPhoneServiceImplFactory.makeBluetoothPhoneServiceImpl(
mContext, mLock, mCallsManager, mPhoneAccountRegistrar);
@@ -264,4 +288,8 @@
public Object getLock() {
return mLock;
}
+
+ public boolean isBootComplete() {
+ return mIsBootComplete;
+ }
}
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index f36a892..c7fd9e0 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -86,10 +86,9 @@
@Override
public MissedCallNotifierImpl makeMissedCallNotifierImpl(
Context context,
- PhoneAccountRegistrar phoneAccountRegistrar,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter) {
+ PhoneAccountRegistrar phoneAccountRegistrar) {
return new MissedCallNotifierImpl(context,
- phoneAccountRegistrar, phoneNumberUtilsAdapter);
+ phoneAccountRegistrar);
}
},
new CallerInfoAsyncQueryFactory() {
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index 89ef95f..9530f63 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -18,19 +18,16 @@
import static android.Manifest.permission.READ_PHONE_STATE;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.pm.PackageManager.NameNotFoundException;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
-import com.android.server.telecom.Call;
-import com.android.server.telecom.CallState;
-import com.android.server.telecom.CallerInfoAsyncQueryFactory;
-import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.Constants;
-import com.android.server.telecom.ContactsAsyncHelper;
import com.android.server.telecom.Log;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
@@ -60,7 +57,6 @@
import android.os.UserHandle;
import android.provider.CallLog.Calls;
import android.telecom.DefaultDialerManager;
-import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
@@ -74,6 +70,8 @@
import java.lang.String;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
@@ -84,18 +82,12 @@
* Creates a notification for calls that the user missed (neither answered nor rejected).
*
* TODO: Make TelephonyManager.clearMissedCalls call into this class.
- *
- * TODO: Reduce dependencies in this implementation; remove the need to create a new Call
- * simply to look up caller metadata, and if possible, make it unnecessary to get a
- * direct reference to the CallsManager. Try to make this class simply handle the UI
- * and Android-framework entanglements of missed call notification.
*/
public class MissedCallNotifierImpl extends CallsManagerListenerBase implements MissedCallNotifier {
public interface MissedCallNotifierImplFactory {
MissedCallNotifier makeMissedCallNotifierImpl(Context context,
- PhoneAccountRegistrar phoneAccountRegistrar,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter);
+ PhoneAccountRegistrar phoneAccountRegistrar);
}
public interface NotificationBuilderFactory {
@@ -120,12 +112,16 @@
Calls.TYPE,
};
- private static final int CALL_LOG_COLUMN_ID = 0;
- private static final int CALL_LOG_COLUMN_NUMBER = 1;
- private static final int CALL_LOG_COLUMN_NUMBER_PRESENTATION = 2;
- private static final int CALL_LOG_COLUMN_DATE = 3;
- private static final int CALL_LOG_COLUMN_DURATION = 4;
- private static final int CALL_LOG_COLUMN_TYPE = 5;
+ private static final String CALL_LOG_WHERE_CLAUSE = "type=" + Calls.MISSED_TYPE +
+ " AND new=1" +
+ " AND is_read=0";
+
+ public static final int CALL_LOG_COLUMN_ID = 0;
+ public static final int CALL_LOG_COLUMN_NUMBER = 1;
+ public static final int CALL_LOG_COLUMN_NUMBER_PRESENTATION = 2;
+ public static final int CALL_LOG_COLUMN_DATE = 3;
+ public static final int CALL_LOG_COLUMN_DURATION = 4;
+ public static final int CALL_LOG_COLUMN_TYPE = 5;
private static final int MISSED_CALL_NOTIFICATION_ID = 1;
@@ -134,25 +130,22 @@
private final NotificationManager mNotificationManager;
private final NotificationBuilderFactory mNotificationBuilderFactory;
private final ComponentName mNotificationComponent;
- private final PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
private UserHandle mCurrentUserHandle;
// Used to track the number of missed calls.
private ConcurrentMap<UserHandle, AtomicInteger> mMissedCallCounts;
- public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter) {
- this(context, phoneAccountRegistrar, phoneNumberUtilsAdapter,
- new DefaultNotificationBuilderFactory());
+ private UserHandle userToLoadAfterBootComplete;
+
+ public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar) {
+ this(context, phoneAccountRegistrar, new DefaultNotificationBuilderFactory());
}
public MissedCallNotifierImpl(Context context,
PhoneAccountRegistrar phoneAccountRegistrar,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
NotificationBuilderFactory notificationBuilderFactory) {
mContext = context;
mPhoneAccountRegistrar = phoneAccountRegistrar;
- mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
final String notificationComponent = context.getString(R.string.notification_component);
@@ -206,7 +199,7 @@
* @param userHandle The user that has the missed call(s).
* @return {@code true} if the broadcast was sent. {@code false} otherwise.
*/
- private boolean sendNotificationCustomComponent(Call call, UserHandle userHandle) {
+ private boolean sendNotificationCustomComponent(CallInfo callInfo, UserHandle userHandle) {
if (mNotificationComponent != null) {
int count = mMissedCallCounts.get(userHandle).get();
Intent intent = new Intent();
@@ -215,19 +208,18 @@
intent.setAction(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION);
intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count);
intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER,
- call != null ? call.getPhoneNumber() : null);
+ callInfo == null ? null : callInfo.getPhoneNumber());
intent.putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT,
createClearMissedCallsPendingIntent(userHandle));
- if (count == 1 && call != null) {
- final Uri handleUri = call.getHandle();
- String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart();
+ if (count == 1 && callInfo != null) {
+ String handle = callInfo.getHandleSchemeSpecificPart();
if (!TextUtils.isEmpty(handle) && !TextUtils.equals(handle,
mContext.getString(R.string.handle_restricted))) {
intent.putExtra(TelecomManager.EXTRA_CALL_BACK_INTENT,
- createCallBackPendingIntent(handleUri, userHandle));
+ createCallBackPendingIntent(callInfo.getHandle(), userHandle));
}
}
@@ -239,7 +231,8 @@
}
/**
- * Returns the missed-call notificatino intent to send to the default dialer for the given user. * Note, the passed in userHandle is always the non-managed user for SIM calls (multi-user
+ * Returns the missed-call notification intent to send to the default dialer for the given user.
+ * Note, the passed in userHandle is always the non-managed user for SIM calls (multi-user
* calls). In this case we return the default dialer for the logged in user. This is never the
* managed (work profile) dialer.
*
@@ -268,13 +261,13 @@
return receivers.size() > 0;
}
- private void sendNotificationThroughDefaultDialer(Call call, UserHandle userHandle) {
+ private void sendNotificationThroughDefaultDialer(CallInfo callInfo, UserHandle userHandle) {
int count = mMissedCallCounts.get(userHandle).get();
Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle)
.setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count)
.putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER,
- call != null ? call.getPhoneNumber() : null);
+ callInfo == null ? null : callInfo.getPhoneNumber());
Log.w(this, "Showing missed calls through default dialer.");
mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE);
@@ -286,8 +279,8 @@
* @param call The missed call.
*/
@Override
- public void showMissedCallNotification(Call call) {
- final PhoneAccountHandle phoneAccountHandle = call.getTargetPhoneAccount();
+ public void showMissedCallNotification(@NonNull CallInfo callInfo) {
+ final PhoneAccountHandle phoneAccountHandle = callInfo.getPhoneAccountHandle();
final PhoneAccount phoneAccount =
mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle);
UserHandle userHandle;
@@ -297,19 +290,20 @@
} else {
userHandle = phoneAccountHandle.getUserHandle();
}
- showMissedCallNotification(call, userHandle);
+ showMissedCallNotification(callInfo, userHandle);
}
- private void showMissedCallNotification(Call call, UserHandle userHandle) {
+ private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle) {
+ Log.i(this, "showMissedCallNotification()");
mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0));
int missCallCounts = mMissedCallCounts.get(userHandle).incrementAndGet();
- if (sendNotificationCustomComponent(call, userHandle)) {
+ if (sendNotificationCustomComponent(callInfo, userHandle)) {
return;
}
if (shouldManageNotificationThroughDefaultDialer(userHandle)) {
- sendNotificationThroughDefaultDialer(call, userHandle);
+ sendNotificationThroughDefaultDialer(callInfo, userHandle);
return;
}
@@ -320,9 +314,9 @@
// 1 missed call: <caller name || handle>
// More than 1 missed call: <number of calls> + "missed calls"
if (missCallCounts == 1) {
- expandedText = getNameForCall(call);
+ expandedText = getNameForMissedCallNotification(callInfo);
- CallerInfo ci = call.getCallerInfo();
+ CallerInfo ci = callInfo.getCallerInfo();
if (ci != null && ci.userType == CallerInfo.USER_TYPE_WORK) {
titleResId = R.string.notification_missedWorkCallTitle;
} else {
@@ -341,7 +335,7 @@
Notification.Builder publicBuilder = mNotificationBuilderFactory.getBuilder(contextForUser);
publicBuilder.setSmallIcon(android.R.drawable.stat_notify_missed_call)
.setColor(mContext.getResources().getColor(R.color.theme_color))
- .setWhen(call.getCreationTimeMillis())
+ .setWhen(callInfo.getCreationTimeMillis())
// Show "Phone" for notification title.
.setContentTitle(mContext.getText(R.string.userCallActivityLabel))
// Notification details shows that there are missed call(s), but does not reveal
@@ -355,7 +349,7 @@
Notification.Builder builder = mNotificationBuilderFactory.getBuilder(contextForUser);
builder.setSmallIcon(android.R.drawable.stat_notify_missed_call)
.setColor(mContext.getResources().getColor(R.color.theme_color))
- .setWhen(call.getCreationTimeMillis())
+ .setWhen(callInfo.getCreationTimeMillis())
.setContentTitle(mContext.getText(titleResId))
.setContentText(expandedText)
.setContentIntent(createCallLogPendingIntent(userHandle))
@@ -366,8 +360,8 @@
// sensitive notification information.
.setPublicVersion(publicBuilder.build());
- Uri handleUri = call.getHandle();
- String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart();
+ Uri handleUri = callInfo.getHandle();
+ String handle = callInfo.getHandleSchemeSpecificPart();
// Add additional actions when there is only 1 missed call, like call-back and SMS.
if (missCallCounts == 1) {
@@ -379,18 +373,20 @@
mContext.getString(R.string.notification_missedCall_call_back),
createCallBackPendingIntent(handleUri, userHandle));
- if (canRespondViaSms(call)) {
+ if (canRespondViaSms(callInfo)) {
builder.addAction(R.drawable.ic_message_24dp,
mContext.getString(R.string.notification_missedCall_message),
createSendSmsFromNotificationPendingIntent(handleUri, userHandle));
}
}
- Bitmap photoIcon = call.getPhotoIcon();
+ Bitmap photoIcon = callInfo.getCallerInfo() == null ?
+ null : callInfo.getCallerInfo().cachedPhotoIcon;
if (photoIcon != null) {
builder.setLargeIcon(photoIcon);
} else {
- Drawable photo = call.getPhoto();
+ Drawable photo = callInfo.getCallerInfo() == null ?
+ null : callInfo.getCallerInfo().cachedPhoto;
if (photo != null && photo instanceof BitmapDrawable) {
builder.setLargeIcon(((BitmapDrawable) photo).getBitmap());
}
@@ -403,7 +399,7 @@
Notification notification = builder.build();
configureLedOnNotification(notification);
- Log.i(this, "Adding missed call notification for %s.", call);
+ Log.i(this, "Adding missed call notification for %s.", Log.pii(callInfo.getHandle()));
long token = Binder.clearCallingIdentity();
try {
mNotificationManager.notifyAsUser(
@@ -440,9 +436,9 @@
/**
* Returns the name to use in the missed call notification.
*/
- private String getNameForCall(Call call) {
- String handle = call.getHandle() == null ? null : call.getHandle().getSchemeSpecificPart();
- String name = call.getName();
+ private String getNameForMissedCallNotification(@NonNull CallInfo callInfo) {
+ String handle = callInfo.getHandleSchemeSpecificPart();
+ String name = callInfo.getName();
if (!TextUtils.isEmpty(handle)) {
String formattedNumber = PhoneNumberUtils.formatNumber(handle,
@@ -559,23 +555,34 @@
notification.defaults |= Notification.DEFAULT_LIGHTS;
}
- private boolean canRespondViaSms(Call call) {
+ private boolean canRespondViaSms(@NonNull CallInfo callInfo) {
// Only allow respond-via-sms for "tel:" calls.
- return call.getHandle() != null &&
- PhoneAccount.SCHEME_TEL.equals(call.getHandle().getScheme());
+ return callInfo.getHandle() != null &&
+ PhoneAccount.SCHEME_TEL.equals(callInfo.getHandle().getScheme());
}
+ @Override
+ public void reloadAfterBootComplete(final CallerInfoLookupHelper callerInfoLookupHelper,
+ CallInfoFactory callInfoFactory) {
+ if (userToLoadAfterBootComplete != null) {
+ reloadFromDatabase(callerInfoLookupHelper,
+ callInfoFactory, userToLoadAfterBootComplete);
+ userToLoadAfterBootComplete = null;
+ }
+ }
/**
* Adds the missed call notification on startup if there are unread missed calls.
*/
@Override
- public void reloadFromDatabase(
- final TelecomSystem.SyncRoot lock,
- final CallsManager callsManager,
- final ContactsAsyncHelper contactsAsyncHelper,
- final CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
- final UserHandle userHandle) {
+ public void reloadFromDatabase(final CallerInfoLookupHelper callerInfoLookupHelper,
+ CallInfoFactory callInfoFactory, final UserHandle userHandle) {
Log.d(this, "reloadFromDatabase()...");
+ if (TelecomSystem.getInstance() == null || !TelecomSystem.getInstance().isBootComplete()) {
+ Log.i(this, "Boot not yet complete -- call log db may not be available. Deferring " +
+ "loading until boot complete.");
+ userToLoadAfterBootComplete = userHandle;
+ return;
+ }
// instantiate query handler
AsyncQueryHandler queryHandler = new AsyncQueryHandler(mContext.getContentResolver()) {
@@ -602,35 +609,40 @@
handleString, null);
}
- synchronized (lock) {
+ callerInfoLookupHelper.startLookup(handle,
+ new CallerInfoLookupHelper.OnQueryCompleteListener() {
+ @Override
+ public void onCallerInfoQueryComplete(Uri queryHandle,
+ CallerInfo info) {
+ if (!Objects.equals(queryHandle, handle)) {
+ Log.w(MissedCallNotifierImpl.this,
+ "CallerInfo query returned with " +
+ "different handle.");
+ return;
+ }
+ if (info.contactDisplayPhotoUri == null) {
+ // If there is no photo, just show the notification.
+ CallInfo callInfo = callInfoFactory.makeCallInfo(
+ info, null, handle, date);
+ showMissedCallNotification(callInfo, userHandle);
+ }
+ }
- // Convert the data to a call object
- Call call = new Call(Call.CALL_ID_UNKNOWN, mContext, callsManager,
- lock, null, contactsAsyncHelper,
- callerInfoAsyncQueryFactory, mPhoneNumberUtilsAdapter, null,
- null, null, null, Call.CALL_DIRECTION_INCOMING, false,
- false);
- call.setDisconnectCause(
- new DisconnectCause(DisconnectCause.MISSED));
- call.setState(CallState.DISCONNECTED, "throw away call");
- call.setCreationTimeMillis(date);
-
- // Listen for the update to the caller information before posting
- // the notification so that we have the contact info and photo.
- call.addListener(new Call.ListenerBase() {
- @Override
- public void onCallerInfoChanged(Call call) {
- call.removeListener(
- this); // No longer need to listen to call
- // changes after the contact info
- // is retrieved.
- showMissedCallNotification(call, userHandle);
+ @Override
+ public void onContactPhotoQueryComplete(Uri queryHandle,
+ CallerInfo info) {
+ if (!Objects.equals(queryHandle, handle)) {
+ Log.w(MissedCallNotifierImpl.this,
+ "CallerInfo query for photo returned " +
+ "with different handle.");
+ return;
+ }
+ CallInfo callInfo = callInfoFactory.makeCallInfo(
+ info, null, handle, date);
+ showMissedCallNotification(callInfo, userHandle);
+ }
}
- });
- // Set the handle here because that is what triggers the contact
- // info query.
- call.setHandle(handle, presentation);
- }
+ );
}
} finally {
cursor.close();
@@ -640,16 +652,11 @@
};
// setup query spec, look for all Missed calls that are new.
- StringBuilder where = new StringBuilder("type=");
- where.append(Calls.MISSED_TYPE);
- where.append(" AND new=1");
- where.append(" AND is_read=0");
-
Uri callsUri =
ContentProvider.maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier());
// start the query
queryHandler.startQuery(0, null, callsUri, CALL_LOG_PROJECTION,
- where.toString(), null, Calls.DEFAULT_SORT_ORDER);
+ CALL_LOG_WHERE_CLAUSE, null, Calls.DEFAULT_SORT_ORDER);
}
@Override
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 6688ca0..1c096f9 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -595,7 +595,8 @@
// Attempt to pull the call and verify the API call makes it through
mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
- verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT).never())
+ Thread.sleep(TEST_TIMEOUT);
+ verify(mConnectionServiceFixtureA.getTestDouble(), never())
.pullExternalCall(ids.mCallId);
}
@@ -790,7 +791,8 @@
// Attempt to pull the call and verify the API call makes it through
mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
- verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT).never())
+ Thread.sleep(TEST_TIMEOUT);
+ verify(mConnectionServiceFixtureA.getTestDouble(), never())
.pullExternalCall(ids.mConnectionId);
}
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index e9db543..590304c 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -296,7 +296,7 @@
Integer.valueOf(CallLog.Calls.MISSED_TYPE));
// Timeout needed because showMissedCallNotification is called from onPostExecute.
verify(mMissedCallNotifier, timeout(TEST_TIMEOUT_MILLIS))
- .showMissedCallNotification(fakeMissedCall);
+ .showMissedCallNotification(any(MissedCallNotifier.CallInfo.class));
}
@MediumTest
diff --git a/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java b/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java
index 363d613..960a170 100644
--- a/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
@@ -87,14 +88,15 @@
}
@SmallTest
- public void testEmptyUri() {
+ public void testEmptyUri() throws Exception {
ContactsAsyncHelper cah = new ContactsAsyncHelper(mNullContentResolverAdapter);
try {
cah.startObtainPhotoAsync(TOKEN, mContext, null, mListener, COOKIE);
} catch (IllegalStateException e) {
// expected to fail
}
- verify(mListener, timeout(TEST_TIMEOUT).never()).onImageLoadComplete(anyInt(),
+ Thread.sleep(TEST_TIMEOUT);
+ verify(mListener, never()).onImageLoadComplete(anyInt(),
any(Drawable.class), any(Bitmap.class), anyObject());
}
diff --git a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
index 24c59ff..2663356 100644
--- a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
@@ -20,24 +20,32 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.Context;
+import android.content.IContentProvider;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.database.Cursor;
import android.net.Uri;
+import android.os.Handler;
+import android.os.ICancellationSignal;
+import android.os.Looper;
import android.os.UserHandle;
+import android.provider.CallLog;
import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccount.Builder;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.telecom.Call;
+import com.android.internal.telephony.CallerInfo;
+import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.Constants;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
import com.android.server.telecom.TelecomBroadcastIntentProcessor;
+import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.components.TelecomBroadcastReceiver;
import com.android.server.telecom.ui.MissedCallNotifierImpl;
import com.android.server.telecom.ui.MissedCallNotifierImpl.NotificationBuilderFactory;
@@ -48,20 +56,65 @@
import java.util.Arrays;
import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class MissedCallNotifierImplTest extends TelecomTestCase {
+ private static class MockMissedCallCursorBuilder {
+ private class CallLogRow {
+ String number;
+ int presentation;
+ long date;
+
+ public CallLogRow(String number, int presentation, long date) {
+ this.number = number;
+ this.presentation = presentation;
+ this.date = date;
+ }
+ }
+
+ private List<CallLogRow> mRows;
+
+ MockMissedCallCursorBuilder() {
+ mRows = new LinkedList<>();
+ mRows.add(null);
+ }
+
+ public MockMissedCallCursorBuilder addEntry(String number, int presentation, long date) {
+ mRows.add(new CallLogRow(number, presentation, date));
+ return this;
+ }
+
+ public Cursor build() {
+ Cursor c = mock(Cursor.class);
+ when(c.moveToNext()).thenAnswer(unused -> {
+ mRows.remove(0);
+ return mRows.size() > 0;
+ });
+ when(c.getString(MissedCallNotifierImpl.CALL_LOG_COLUMN_NUMBER))
+ .thenAnswer(unused -> mRows.get(0).number);
+ when(c.getInt(MissedCallNotifierImpl.CALL_LOG_COLUMN_NUMBER_PRESENTATION))
+ .thenAnswer(unused -> mRows.get(0).presentation);
+ when(c.getLong(MissedCallNotifierImpl.CALL_LOG_COLUMN_DATE))
+ .thenAnswer(unused -> mRows.get(0).date);
+ return c;
+ }
+ }
+
private static final Uri TEL_CALL_HANDLE = Uri.parse("tel:+11915552620");
private static final Uri SIP_CALL_HANDLE = Uri.parse("sip:testaddress@testdomain.com");
private static final String CALLER_NAME = "Fake Name";
@@ -79,6 +132,7 @@
private static final UserHandle PRIMARY_USER = UserHandle.of(0);
private static final UserHandle SECONARY_USER = UserHandle.of(12);
private static final int NO_CAPABILITY = 0;
+ private static final int TEST_TIMEOUT = 1000;
@Mock
private NotificationManager mNotificationManager;
@@ -89,6 +143,8 @@
@Mock
private TelecomManager mTelecomManager;
+ @Mock TelecomSystem mTelecomSystem;
+
@Override
public void setUp() throws Exception {
super.setUp();
@@ -114,6 +170,12 @@
mComponentContextFixture.setTelecomManager(mTelecomManager);
}
+ @Override
+ public void tearDown() throws Exception {
+ TelecomSystem.setInstance(null);
+ when(mTelecomSystem.isBootComplete()).thenReturn(false);
+ }
+
@SmallTest
public void testCancelNotificationInPrimaryUser() {
cancelNotificationTestInternal(PRIMARY_USER);
@@ -133,8 +195,8 @@
MissedCallNotifier missedCallNotifier = makeMissedCallNotifier(fakeBuilderFactory,
PRIMARY_USER);
PhoneAccount phoneAccount = makePhoneAccount(userHandle, NO_CAPABILITY);
- Call fakeCall = makeFakeCall(TEL_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
- phoneAccount.getAccountHandle());
+ MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
+ CALL_TIMESTAMP, phoneAccount.getAccountHandle());
missedCallNotifier.showMissedCallNotification(fakeCall);
missedCallNotifier.clearMissedCalls(userHandle);
@@ -160,14 +222,14 @@
}
PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
- Call fakeCall = makeFakeCall(TEL_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
- phoneAccount.getAccountHandle());
+ MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
+ CALL_TIMESTAMP, phoneAccount.getAccountHandle());
MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
makeNotificationBuilderFactory(builders);
MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
- mPhoneAccountRegistrar, new PhoneNumberUtilsAdapterImpl(), fakeBuilderFactory);
+ mPhoneAccountRegistrar, fakeBuilderFactory);
missedCallNotifier.showMissedCallNotification(fakeCall);
missedCallNotifier.showMissedCallNotification(fakeCall);
@@ -254,8 +316,8 @@
MissedCallNotifier missedCallNotifier = makeMissedCallNotifier(fakeBuilderFactory,
currentUser);
- Call fakeCall = makeFakeCall(TEL_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
- phoneAccount.getAccountHandle());
+ MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
+ CALL_TIMESTAMP, phoneAccount.getAccountHandle());
missedCallNotifier.showMissedCallNotification(fakeCall);
ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(
@@ -316,11 +378,11 @@
makeNotificationBuilderFactory(builder1);
MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
- mPhoneAccountRegistrar, new PhoneNumberUtilsAdapterImpl(), fakeBuilderFactory);
+ mPhoneAccountRegistrar, fakeBuilderFactory);
PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
- Call fakeCall =
- makeFakeCall(SIP_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
+ MissedCallNotifier.CallInfo fakeCall =
+ makeFakeCallInfo(SIP_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
phoneAccount.getAccountHandle());
missedCallNotifier.showMissedCallNotification(fakeCall);
@@ -344,6 +406,135 @@
smsIntent, PendingIntent.FLAG_NO_CREATE));
}
+ @SmallTest
+ public void testLoadOneCallFromDb() throws Exception {
+ CallerInfoLookupHelper mockCallerInfoLookupHelper = mock(CallerInfoLookupHelper.class);
+ MissedCallNotifier.CallInfoFactory mockCallInfoFactory =
+ mock(MissedCallNotifier.CallInfoFactory.class);
+
+ Uri queryUri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI,
+ PRIMARY_USER.getIdentifier());
+ IContentProvider cp = getContentProviderForUser(PRIMARY_USER.getIdentifier());
+
+ Cursor mockMissedCallsCursor = new MockMissedCallCursorBuilder()
+ .addEntry(TEL_CALL_HANDLE.getSchemeSpecificPart(),
+ CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
+ .build();
+
+ when(cp.query(anyString(), eq(queryUri), any(String[].class), anyString(), any
+ (String[].class), anyString(), any(ICancellationSignal.class)))
+ .thenReturn(mockMissedCallsCursor);
+
+ PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
+ MissedCallNotifier.CallInfo fakeCallInfo = makeFakeCallInfo(TEL_CALL_HANDLE,
+ CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle());
+ when(mockCallInfoFactory.makeCallInfo(any(CallerInfo.class),
+ any(PhoneAccountHandle.class), any(Uri.class), eq(CALL_TIMESTAMP)))
+ .thenReturn(fakeCallInfo);
+
+ Notification.Builder builder1 = makeNotificationBuilder("builder1");
+ MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
+ makeNotificationBuilderFactory(builder1);
+
+ MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
+ mPhoneAccountRegistrar, fakeBuilderFactory);
+
+ // AsyncQueryHandler used in reloadFromDatabase interacts poorly with the below
+ // timeout-verify, so run this in a new handler to mitigate that.
+ Handler h = new Handler(Looper.getMainLooper());
+ h.post(() -> missedCallNotifier.reloadFromDatabase(
+ mockCallerInfoLookupHelper, mockCallInfoFactory, PRIMARY_USER));
+ waitForHandlerAction(h, TEST_TIMEOUT);
+
+ // TelecomSystem.getInstance returns null in this test, so we expect that nothing will
+ // happen.
+ verify(mockCallerInfoLookupHelper, never()).startLookup(any(Uri.class),
+ any(CallerInfoLookupHelper.OnQueryCompleteListener.class));
+ // Simulate a boot-complete
+ TelecomSystem.setInstance(mTelecomSystem);
+ when(mTelecomSystem.isBootComplete()).thenReturn(true);
+ h.post(() -> missedCallNotifier.reloadAfterBootComplete(mockCallerInfoLookupHelper,
+ mockCallInfoFactory));
+ waitForHandlerAction(h, TEST_TIMEOUT);
+
+ Uri escapedHandle = Uri.fromParts(PhoneAccount.SCHEME_TEL,
+ TEL_CALL_HANDLE.getSchemeSpecificPart(), null);
+ ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> listenerCaptor =
+ ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
+ verify(mockCallerInfoLookupHelper, timeout(TEST_TIMEOUT)).startLookup(eq(escapedHandle),
+ listenerCaptor.capture());
+
+ CallerInfo ci = new CallerInfo();
+ listenerCaptor.getValue().onCallerInfoQueryComplete(escapedHandle, ci);
+ verify(mockCallInfoFactory).makeCallInfo(eq(ci), isNull(PhoneAccountHandle.class),
+ eq(escapedHandle), eq(CALL_TIMESTAMP));
+ }
+
+ @SmallTest
+ public void testLoadTwoCallsFromDb() throws Exception {
+ TelecomSystem.setInstance(mTelecomSystem);
+ when(mTelecomSystem.isBootComplete()).thenReturn(true);
+ CallerInfoLookupHelper mockCallerInfoLookupHelper = mock(CallerInfoLookupHelper.class);
+ MissedCallNotifier.CallInfoFactory mockCallInfoFactory =
+ mock(MissedCallNotifier.CallInfoFactory.class);
+
+ Cursor mockMissedCallsCursor = new MockMissedCallCursorBuilder()
+ .addEntry(TEL_CALL_HANDLE.getSchemeSpecificPart(),
+ CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
+ .addEntry(SIP_CALL_HANDLE.getSchemeSpecificPart(),
+ CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
+ .build();
+
+ Uri queryUri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI,
+ PRIMARY_USER.getIdentifier());
+ IContentProvider cp = getContentProviderForUser(PRIMARY_USER.getIdentifier());
+
+ when(cp.query(anyString(), eq(queryUri), any(String[].class), anyString(), any
+ (String[].class), anyString(), any(ICancellationSignal.class)))
+ .thenReturn(mockMissedCallsCursor);
+
+ PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
+ MissedCallNotifier.CallInfo fakeCallInfo = makeFakeCallInfo(TEL_CALL_HANDLE,
+ CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle());
+ when(mockCallInfoFactory.makeCallInfo(any(CallerInfo.class),
+ any(PhoneAccountHandle.class), any(Uri.class), eq(CALL_TIMESTAMP)))
+ .thenReturn(fakeCallInfo);
+
+ Notification.Builder builder1 = makeNotificationBuilder("builder1");
+ MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
+ makeNotificationBuilderFactory(builder1);
+
+ MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
+ mPhoneAccountRegistrar, fakeBuilderFactory);
+
+ // AsyncQueryHandler used in reloadFromDatabase interacts poorly with the below
+ // timeout-verify, so run this in a new handler to mitigate that.
+ Handler h = new Handler(Looper.getMainLooper());
+ h.post(() -> missedCallNotifier.reloadFromDatabase(
+ mockCallerInfoLookupHelper, mockCallInfoFactory, PRIMARY_USER));
+ waitForHandlerAction(h, TEST_TIMEOUT);
+
+ Uri escapedTelHandle = Uri.fromParts(PhoneAccount.SCHEME_TEL,
+ TEL_CALL_HANDLE.getSchemeSpecificPart(), null);
+ Uri escapedSipHandle = Uri.fromParts(PhoneAccount.SCHEME_SIP,
+ SIP_CALL_HANDLE.getSchemeSpecificPart(), null);
+
+ ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> listenerCaptor =
+ ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
+ verify(mockCallerInfoLookupHelper, timeout(TEST_TIMEOUT)).startLookup(eq(escapedTelHandle),
+ listenerCaptor.capture());
+ verify(mockCallerInfoLookupHelper, timeout(TEST_TIMEOUT)).startLookup(eq(escapedSipHandle),
+ listenerCaptor.capture());
+
+ CallerInfo ci = new CallerInfo();
+ listenerCaptor.getAllValues().get(0).onCallerInfoQueryComplete(escapedTelHandle, ci);
+ listenerCaptor.getAllValues().get(1).onCallerInfoQueryComplete(escapedSipHandle, ci);
+
+ // Verify that two notifications were generated, both with the same id.
+ verify(mNotificationManager, times(2)).notifyAsUser(isNull(String.class), eq(1),
+ any(Notification.class), eq(PRIMARY_USER));
+ }
+
private Notification.Builder makeNotificationBuilder(String label) {
Notification.Builder builder = spy(new Notification.Builder(mContext));
Notification notification = mock(Notification.class);
@@ -353,13 +544,14 @@
return builder;
}
- private Call makeFakeCall(Uri handle, String name, long timestamp,
+ private MissedCallNotifier.CallInfo makeFakeCallInfo(Uri handle, String name, long timestamp,
PhoneAccountHandle phoneAccountHandle) {
- Call fakeCall = mock(Call.class);
+ MissedCallNotifier.CallInfo fakeCall = mock(MissedCallNotifier.CallInfo.class);
when(fakeCall.getHandle()).thenReturn(handle);
+ when(fakeCall.getHandleSchemeSpecificPart()).thenReturn(handle.getSchemeSpecificPart());
when(fakeCall.getName()).thenReturn(name);
when(fakeCall.getCreationTimeMillis()).thenReturn(timestamp);
- when(fakeCall.getTargetPhoneAccount()).thenReturn(phoneAccountHandle);
+ when(fakeCall.getPhoneAccountHandle()).thenReturn(phoneAccountHandle);
return fakeCall;
}
@@ -375,7 +567,7 @@
private MissedCallNotifier makeMissedCallNotifier(
NotificationBuilderFactory fakeBuilderFactory, UserHandle currentUser) {
MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
- mPhoneAccountRegistrar, new PhoneNumberUtilsAdapterImpl(), fakeBuilderFactory);
+ mPhoneAccountRegistrar, fakeBuilderFactory);
missedCallNotifier.setCurrentUserHandle(currentUser);
return missedCallNotifier;
}
@@ -391,4 +583,9 @@
.thenReturn(phoneAccount);
return phoneAccount;
}
+
+ private IContentProvider getContentProviderForUser(int userId) {
+ return mContext.getContentResolver().acquireProvider(userId + "@call_log");
+ }
+
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 68eb0ed..d098eb9 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -64,6 +64,7 @@
import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.CallerInfoAsyncQueryFactory;
+import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.ContactsAsyncHelper;
@@ -129,7 +130,7 @@
public static class MissedCallNotifierFakeImpl extends CallsManagerListenerBase
implements MissedCallNotifier {
- List<com.android.server.telecom.Call> missedCallsNotified = new ArrayList<>();
+ List<CallInfo> missedCallsNotified = new ArrayList<>();
@Override
public void clearMissedCalls(UserHandle userHandle) {
@@ -137,16 +138,17 @@
}
@Override
- public void showMissedCallNotification(com.android.server.telecom.Call call) {
+ public void showMissedCallNotification(CallInfo call) {
missedCallsNotified.add(call);
}
@Override
- public void reloadFromDatabase(TelecomSystem.SyncRoot lock, CallsManager callsManager,
- ContactsAsyncHelper contactsAsyncHelper,
- CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory, UserHandle userHandle) {
+ public void reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper,
+ CallInfoFactory callInfoFactory) { }
- }
+ @Override
+ public void reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper,
+ CallInfoFactory callInfoFactory, UserHandle userHandle) { }
@Override
public void setCurrentUserHandle(UserHandle userHandle) {
@@ -376,8 +378,7 @@
new MissedCallNotifierImplFactory() {
@Override
public MissedCallNotifier makeMissedCallNotifierImpl(Context context,
- PhoneAccountRegistrar phoneAccountRegistrar,
- PhoneNumberUtilsAdapter phoneNumberUtilsAdapter) {
+ PhoneAccountRegistrar phoneAccountRegistrar) {
return mMissedCallNotifier;
}
},