Merge "Add *AsUser() calls where appropriate for multi-user support." into nyc-dev
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index fc124a4..2a56422 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1331,7 +1331,8 @@
}
}
- Bundle getIntentExtras() {
+ @VisibleForTesting
+ public Bundle getIntentExtras() {
return mIntentExtras;
}
diff --git a/src/com/android/server/telecom/CallScreening.java b/src/com/android/server/telecom/CallScreening.java
index f0ef5a6..22201a3 100644
--- a/src/com/android/server/telecom/CallScreening.java
+++ b/src/com/android/server/telecom/CallScreening.java
@@ -55,6 +55,7 @@
private final Listener mListener;
private final TelecomSystem.SyncRoot mLock;
private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+ private final CallsManager mCallsManager;
private final Handler mHandler = new Handler();
private Call mCall;
private ICallScreeningService mService;
@@ -62,12 +63,13 @@
public CallScreening(
Context context,
- Listener listener,
+ CallsManager callsManager,
TelecomSystem.SyncRoot lock,
PhoneAccountRegistrar phoneAccountRegistrar,
Call call) {
mContext = context;
- mListener = listener;
+ mCallsManager = callsManager;
+ mListener = callsManager;
mLock = lock;
mPhoneAccountRegistrar = phoneAccountRegistrar;
mCall = call;
@@ -113,7 +115,8 @@
Intent intent = new Intent(CallScreeningService.SERVICE_INTERFACE)
.setPackage(dialerPackage);
- List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServices(intent, 0);
+ List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
+ intent, 0, mCallsManager.getCurrentUserHandle().getIdentifier());
if (entries.isEmpty()) {
return false;
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 8379ddf..2634ab3 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -16,6 +16,7 @@
package com.android.server.telecom;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.Intent;
@@ -109,7 +110,8 @@
{CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING};
private static final int[] LIVE_CALL_STATES =
- {CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING, CallState.ACTIVE};
+ {CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING,
+ CallState.ACTIVE};
public static final String TELECOM_CALL_ID_PREFIX = "TC@";
// Maps call technologies in PhoneConstants to those in Analytics.
@@ -142,6 +144,11 @@
*/
private int mCallId = 0;
+ /**
+ * Stores the current foreground user.
+ */
+ private UserHandle mCurrentUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
+
private final ConnectionServiceRepository mConnectionServiceRepository;
private final DtmfLocalTonePlayer mDtmfLocalTonePlayer;
private final InCallController mInCallController;
@@ -230,8 +237,9 @@
RingtoneFactory ringtoneFactory = new RingtoneFactory(context);
SystemVibrator systemVibrator = new SystemVibrator(context);
AsyncRingtonePlayer asyncRingtonePlayer = new AsyncRingtonePlayer();
+ mInCallController = new InCallController(context, mLock, this, systemStateProvider);
mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
- ringtoneFactory, systemVibrator);
+ ringtoneFactory, systemVibrator, mInCallController);
mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
this,new CallAudioModeStateMachine((AudioManager)
@@ -243,7 +251,6 @@
mProximitySensorManager = proximitySensorManagerFactory.create(context, this);
mPhoneStateBroadcaster = new PhoneStateBroadcaster(this);
mCallLogManager = new CallLogManager(context, phoneAccountRegistrar);
- mInCallController = new InCallController(context, mLock, this, systemStateProvider);
mConnectionServiceRepository =
new ConnectionServiceRepository(mPhoneAccountRegistrar, mContext, mLock, this);
mInCallWakeLockController = inCallWakeLockControllerFactory.create(context, this);
@@ -553,6 +560,10 @@
return mCallAudioManager.getForegroundCall();
}
+ public UserHandle getCurrentUserHandle() {
+ return mCurrentUserHandle;
+ }
+
CallAudioManager getCallAudioManager() {
return mCallAudioManager;
}
@@ -561,7 +572,8 @@
return mInCallController;
}
- boolean hasEmergencyCall() {
+ @VisibleForTesting
+ public boolean hasEmergencyCall() {
for (Call call : mCalls) {
if (call.isEmergencyCall()) {
return true;
@@ -1848,6 +1860,7 @@
* including the user itself. There may be chances that profiles are not started yet.
*/
void onUserSwitch(UserHandle userHandle) {
+ mCurrentUserHandle = userHandle;
mMissedCallNotifier.setCurrentUserHandle(userHandle);
final UserManager userManager = UserManager.get(mContext);
List<UserInfo> profiles = userManager.getEnabledProfiles(userHandle.getIdentifier());
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 41c99db..150879d 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -39,6 +39,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
+import com.android.internal.annotations.VisibleForTesting;
// TODO: Needed for move to system service: import com.android.internal.R;
import com.android.internal.telecom.IInCallService;
import com.android.internal.util.IndentingPrintWriter;
@@ -345,7 +346,8 @@
*
* @param call The newly added call that triggered the binding to the in-call services.
*/
- private void bindToServices(Call call) {
+ @VisibleForTesting
+ public void bindToServices(Call call) {
ComponentName inCallUIService = null;
ComponentName carModeInCallUIService = null;
List<ComponentName> nonUIInCallServices = new LinkedList<>();
@@ -353,12 +355,16 @@
// Loop through all the InCallService implementations that exist in the devices;
PackageManager packageManager = mContext.getPackageManager();
Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE);
- for (ResolveInfo entry :
- packageManager.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA)) {
+ for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
+ serviceIntent,
+ PackageManager.GET_META_DATA,
+ mCallsManager.getCurrentUserHandle().getIdentifier())) {
ServiceInfo serviceInfo = entry.serviceInfo;
+
if (serviceInfo != null) {
ComponentName componentName =
new ComponentName(serviceInfo.packageName, serviceInfo.name);
+ Log.v(this, "ICS: " + componentName + ", user: " + entry.targetUserId);
switch (getInCallServiceType(entry.serviceInfo, packageManager)) {
case IN_CALL_SERVICE_TYPE_DIALER_UI:
@@ -500,7 +506,8 @@
// Check to see that it is the default dialer package
boolean isDefaultDialerPackage = Objects.equals(serviceInfo.packageName,
- DefaultDialerManager.getDefaultDialerApplication(mContext));
+ DefaultDialerManager.getDefaultDialerApplication(
+ mContext, mCallsManager.getCurrentUserHandle().getIdentifier()));
boolean isUIService = serviceInfo.metaData != null &&
serviceInfo.metaData.getBoolean(
TelecomManager.METADATA_IN_CALL_SERVICE_UI, false);
@@ -706,17 +713,26 @@
pw.decreaseIndent();
}
- static boolean doesDefaultDialerSupportRinging(Context context) {
- String dialerPackage = DefaultDialerManager
- .getDefaultDialerApplication(context, UserHandle.USER_CURRENT);
- if (TextUtils.isEmpty(dialerPackage)) {
+ public boolean doesConnectedDialerSupportRinging() {
+ String ringingPackage = null;
+ if (mInCallUIComponentName != null) {
+ ringingPackage = mInCallUIComponentName.getPackageName().trim();
+ }
+
+ if (TextUtils.isEmpty(ringingPackage)) {
+ // The current in-call UI returned nothing, so lets use the default dialer.
+ ringingPackage = DefaultDialerManager.getDefaultDialerApplication(
+ mContext, UserHandle.USER_CURRENT);
+ }
+ if (TextUtils.isEmpty(ringingPackage)) {
return false;
}
Intent intent = new Intent(InCallService.SERVICE_INTERFACE)
- .setPackage(dialerPackage);
- List<ResolveInfo> entries = context.getPackageManager()
- .queryIntentServices(intent, PackageManager.GET_META_DATA);
+ .setPackage(ringingPackage);
+ List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
+ intent, PackageManager.GET_META_DATA,
+ mCallsManager.getCurrentUserHandle().getIdentifier());
if (entries.isEmpty()) {
return false;
}
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index b9d6e0d..ddd2e93 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -56,6 +56,7 @@
private final AsyncRingtonePlayer mRingtonePlayer;
private final Context mContext;
private final Vibrator mVibrator;
+ private final InCallController mInCallController;
private InCallTonePlayer mCallWaitingPlayer;
private RingtoneFactory mRingtoneFactory;
@@ -79,7 +80,8 @@
SystemSettingsUtil systemSettingsUtil,
AsyncRingtonePlayer asyncRingtonePlayer,
RingtoneFactory ringtoneFactory,
- Vibrator vibrator) {
+ Vibrator vibrator,
+ InCallController inCallController) {
mSystemSettingsUtil = systemSettingsUtil;
mPlayerFactory = playerFactory;
@@ -89,6 +91,7 @@
mVibrator = vibrator;
mRingtonePlayer = asyncRingtonePlayer;
mRingtoneFactory = ringtoneFactory;
+ mInCallController = inCallController;
}
public void startRinging(Call foregroundCall) {
@@ -101,7 +104,7 @@
return;
}
- if (InCallController.doesDefaultDialerSupportRinging(mContext)) {
+ if (mInCallController.doesConnectedDialerSupportRinging()) {
Log.event(foregroundCall, Log.Events.SKIP_RINGING);
return;
}
@@ -138,7 +141,7 @@
return;
}
- if (InCallController.doesDefaultDialerSupportRinging(mContext)) {
+ if (mInCallController.doesConnectedDialerSupportRinging()) {
Log.event(call, Log.Events.SKIP_RINGING);
return;
}
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index e645123..3e8fe5b 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -54,7 +54,7 @@
<service android:name="com.android.server.telecom.testapps.TestInCallServiceImpl"
android:process="com.android.server.telecom.testapps.TestInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE" >
- <meta-data android:name="android.telecom.IN_CALL_SERVICE_CAR_MODE_UI" android:value="true" />
+ <meta-data android:name="android.telecom.IN_CALL_SERVICE_CAR_MODE_UI" android:value="true"/>
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
new file mode 100644
index 0000000..ee3f691
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 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.server.telecom.tests;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.telecom.ConnectionService;
+import android.telecom.InCallService;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.test.mock.MockContext;
+
+import com.android.server.telecom.BluetoothHeadsetProxy;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.InCallController;
+import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.R;
+import com.android.server.telecom.SystemStateProvider;
+import com.android.server.telecom.TelecomSystem;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.LinkedList;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyChar;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+public class InCallControllerTests extends TelecomTestCase {
+ @Mock CallsManager mMockCallsManager;
+ @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
+ @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;
+ @Mock SystemStateProvider mMockSystemStateProvider;
+ @Mock PackageManager mMockPackageManager;
+ @Mock Call mMockCall;
+ @Mock Resources mMockResources;
+ @Mock MockContext mMockContext;
+
+ private static final int CURRENT_USER_ID = 900973;
+ private static final String DEF_PKG = "defpkg";
+ private static final String DEF_CLASS = "defcls";
+ private static final PhoneAccountHandle PA_HANDLE =
+ new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"), "pa_id");
+
+ private UserHandle mUserHandle = UserHandle.of(CURRENT_USER_ID);
+ private InCallController mInCallController;
+ private TelecomSystem.SyncRoot mLock;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ doReturn(mMockResources).when(mMockContext).getResources();
+ doReturn(DEF_PKG).when(mMockResources).getString(R.string.ui_default_package);
+ doReturn(DEF_CLASS).when(mMockResources).getString(R.string.incall_default_class);
+ mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
+ mMockSystemStateProvider);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testBindToService_NoServicesFound_IncomingCall() throws Exception {
+ when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
+ when(mMockCall.isIncoming()).thenReturn(true);
+
+ Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
+ when(mMockPackageManager.queryIntentServicesAsUser(
+ queryIntent, PackageManager.GET_META_DATA, CURRENT_USER_ID))
+ .thenReturn(new LinkedList<ResolveInfo>());
+ mInCallController.bindToServices(mMockCall);
+
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.CURRENT));
+
+ Intent bindIntent = bindIntentCaptor.getValue();
+ assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+ assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
+ assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
+ assertNull(bindIntent.getExtras());
+ }
+
+ public void testBindToService_NoServicesFound_OutgoingCall() throws Exception {
+ Bundle callExtras = new Bundle();
+ callExtras.putBoolean("whatever", true);
+
+ when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
+ when(mMockCall.isIncoming()).thenReturn(false);
+ when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
+ when(mMockCall.getIntentExtras()).thenReturn(callExtras);
+
+ Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
+ when(mMockPackageManager.queryIntentServicesAsUser(
+ queryIntent, PackageManager.GET_META_DATA, CURRENT_USER_ID))
+ .thenReturn(new LinkedList<ResolveInfo>());
+ mInCallController.bindToServices(mMockCall);
+
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.CURRENT));
+
+ Intent bindIntent = bindIntentCaptor.getValue();
+ assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+ assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
+ assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
+ assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
+ TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
+ assertEquals(callExtras, bindIntent.getExtras().getParcelable(
+ TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
+ }
+}