Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION"/>
<protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT"/>

<uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>

<!-- Prevents the activity manager from delaying any activity-start
requests by this package, including requests immediately after
Expand Down
19 changes: 15 additions & 4 deletions src/com/android/server/telecom/CallsManager.java
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,16 @@ public void onCallRedirectionComplete(Call call, Uri handle,
boolean endEarly = false;
String disconnectReason = "";
String callRedirectionApp = mRoleManagerAdapter.getDefaultCallRedirectionApp();
PhoneAccount phoneAccount = mPhoneAccountRegistrar
.getPhoneAccountUnchecked(phoneAccountHandle);
if (phoneAccount != null
&& !phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
// Check if the phoneAccountHandle belongs to the current user
if (phoneAccountHandle != null &&
!phoneAccountHandle.getUserHandle().equals(mCurrentUserHandle)) {
phoneAccountHandle = null;
}
}

boolean isPotentialEmergencyNumber;
try {
Expand Down Expand Up @@ -2105,9 +2115,9 @@ public void onCallRedirectionComplete(Call call, Uri handle,
endEarly = true;
disconnectReason = "Null handle from Call Redirection Service";
} else if (phoneAccountHandle == null) {
Log.w(this, "onCallRedirectionComplete: phoneAccountHandle is null");
Log.w(this, "onCallRedirectionComplete: phoneAccountHandle is unavailable");
endEarly = true;
disconnectReason = "Null phoneAccountHandle from Call Redirection Service";
disconnectReason = "Unavailable phoneAccountHandle from Call Redirection Service";
} else if (isPotentialEmergencyNumber) {
Log.w(this, "onCallRedirectionComplete: emergency number %s is redirected from Call"
+ " Redirection Service", handle.getSchemeSpecificPart());
Expand All @@ -2128,6 +2138,7 @@ public void onCallRedirectionComplete(Call call, Uri handle,
return;
}

final PhoneAccountHandle finalPhoneAccountHandle = phoneAccountHandle;
if (uiAction.equals(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_ASK_FOR_CONFIRM)) {
Log.addEvent(call, LogUtils.Events.REDIRECTION_USER_CONFIRMATION);
mPendingRedirectedOutgoingCall = call;
Expand All @@ -2137,7 +2148,7 @@ public void onCallRedirectionComplete(Call call, Uri handle,
@Override
public void loggedRun() {
Log.addEvent(call, LogUtils.Events.REDIRECTION_USER_CONFIRMED);
call.setTargetPhoneAccount(phoneAccountHandle);
call.setTargetPhoneAccount(finalPhoneAccountHandle);
placeOutgoingCall(call, handle, gatewayInfo, speakerphoneOn,
videoState);
}
Expand All @@ -2147,7 +2158,7 @@ public void loggedRun() {
new Runnable("CM.oCRC", mLock) {
@Override
public void loggedRun() {
call.setTargetPhoneAccount(phoneAccountHandle);
call.setTargetPhoneAccount(finalPhoneAccountHandle);
placeOutgoingCall(call, handle, null, speakerphoneOn,
videoState);
}
Expand Down
15 changes: 15 additions & 0 deletions src/com/android/server/telecom/PhoneAccountRegistrar.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import android.text.TextUtils;
import android.util.AtomicFile;
import android.util.Base64;
import android.util.EventLog;
import android.util.Xml;

// TODO: Needed for move to system service: import com.android.internal.R;
Expand Down Expand Up @@ -818,6 +819,7 @@ private void addOrReplacePhoneAccount(PhoneAccount account) {

PhoneAccount oldAccount = getPhoneAccountUnchecked(account.getAccountHandle());
if (oldAccount != null) {
enforceSelfManagedAccountUnmodified(account, oldAccount);
mState.accounts.remove(oldAccount);
isEnabled = oldAccount.isEnabled();
Log.i(this, "Modify account: %s", getAccountDiffString(account, oldAccount));
Expand Down Expand Up @@ -878,6 +880,19 @@ public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
}
}

private void enforceSelfManagedAccountUnmodified(PhoneAccount newAccount,
PhoneAccount oldAccount) {
if (oldAccount.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) &&
(!newAccount.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED))) {
EventLog.writeEvent(0x534e4554, "246930197");
Log.w(this, "Self-managed phone account %s replaced by a non self-managed one",
newAccount.getAccountHandle());
throw new IllegalArgumentException("Error, cannot change a self-managed "
+ "phone account " + newAccount.getAccountHandle()
+ " to other kinds of phone account");
}
}

/**
* Un-registers all phone accounts associated with a specified package.
*
Expand Down
50 changes: 28 additions & 22 deletions src/com/android/server/telecom/TelecomServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
Expand Down Expand Up @@ -190,25 +191,26 @@ public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle
}

@Override
public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
public ParceledListSlice<PhoneAccountHandle> getCallCapablePhoneAccounts(
boolean includeDisabledAccounts, String callingPackage, String callingFeatureId) {
try {
Log.startSession("TSI.gCCPA");
if (includeDisabledAccounts &&
!canReadPrivilegedPhoneState(
callingPackage, "getCallCapablePhoneAccounts")) {
return Collections.emptyList();
return ParceledListSlice.emptyList();
}
if (!canReadPhoneState(callingPackage, callingFeatureId,
"getCallCapablePhoneAccounts")) {
return Collections.emptyList();
return ParceledListSlice.emptyList();
}
synchronized (mLock) {
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
return mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null,
includeDisabledAccounts, callingUserHandle);
return new ParceledListSlice<>(
mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null,
includeDisabledAccounts, callingUserHandle));
} catch (Exception e) {
Log.e(this, e, "getCallCapablePhoneAccounts");
throw e;
Expand All @@ -222,8 +224,8 @@ public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
}

@Override
public List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
String callingFeatureId) {
public ParceledListSlice<PhoneAccountHandle> getSelfManagedPhoneAccounts(
String callingPackage, String callingFeatureId) {
try {
Log.startSession("TSI.gSMPA");
if (!canReadPhoneState(callingPackage, callingFeatureId,
Expand All @@ -234,8 +236,8 @@ public List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackag
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
return mPhoneAccountRegistrar.getSelfManagedPhoneAccounts(
callingUserHandle);
return new ParceledListSlice<>(mPhoneAccountRegistrar
.getSelfManagedPhoneAccounts(callingUserHandle));
} catch (Exception e) {
Log.e(this, e, "getSelfManagedPhoneAccounts");
throw e;
Expand All @@ -249,8 +251,8 @@ public List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackag
}

@Override
public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme,
String callingPackage) {
public ParceledListSlice<PhoneAccountHandle> getPhoneAccountsSupportingScheme(
String uriScheme, String callingPackage) {
try {
Log.startSession("TSI.gPASS");
try {
Expand All @@ -259,15 +261,16 @@ public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriSchem
} catch (SecurityException e) {
EventLog.writeEvent(0x534e4554, "62347125", Binder.getCallingUid(),
"getPhoneAccountsSupportingScheme: " + callingPackage);
return Collections.emptyList();
return ParceledListSlice.emptyList();
}

synchronized (mLock) {
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
return mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme, false,
callingUserHandle);
return new ParceledListSlice<>(mPhoneAccountRegistrar
.getCallCapablePhoneAccounts(uriScheme, false,
callingUserHandle));
} catch (Exception e) {
Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
throw e;
Expand All @@ -281,7 +284,8 @@ public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriSchem
}

@Override
public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
public ParceledListSlice<PhoneAccountHandle> getPhoneAccountsForPackage(
String packageName) {
//TODO: Deprecate this in S
try {
enforceCallingPackage(packageName, "getPhoneAccountsForPackage");
Expand All @@ -304,8 +308,8 @@ public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSI.gPAFP");
return mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName,
callingUserHandle);
return new ParceledListSlice<>(mPhoneAccountRegistrar
.getPhoneAccountsForPackage(packageName, callingUserHandle));
} catch (Exception e) {
Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
throw e;
Expand Down Expand Up @@ -375,7 +379,7 @@ public int getAllPhoneAccountsCount() {
synchronized (mLock) {
try {
// This list is pre-filtered for the calling user.
return getAllPhoneAccounts().size();
return getAllPhoneAccounts().getList().size();
} catch (Exception e) {
Log.e(this, e, "getAllPhoneAccountsCount");
throw e;
Expand All @@ -388,7 +392,7 @@ public int getAllPhoneAccountsCount() {
}

@Override
public List<PhoneAccount> getAllPhoneAccounts() {
public ParceledListSlice<PhoneAccount> getAllPhoneAccounts() {
synchronized (mLock) {
try {
Log.startSession("TSI.gAPA");
Expand All @@ -404,7 +408,8 @@ public List<PhoneAccount> getAllPhoneAccounts() {
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
return mPhoneAccountRegistrar.getAllPhoneAccounts(callingUserHandle);
return new ParceledListSlice<>(mPhoneAccountRegistrar
.getAllPhoneAccounts(callingUserHandle));
} catch (Exception e) {
Log.e(this, e, "getAllPhoneAccounts");
throw e;
Expand All @@ -418,7 +423,7 @@ public List<PhoneAccount> getAllPhoneAccounts() {
}

@Override
public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
public ParceledListSlice<PhoneAccountHandle> getAllPhoneAccountHandles() {
try {
Log.startSession("TSI.gAPAH");
try {
Expand All @@ -434,7 +439,8 @@ public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
return mPhoneAccountRegistrar.getAllPhoneAccountHandles(callingUserHandle);
return new ParceledListSlice<>(mPhoneAccountRegistrar
.getAllPhoneAccountHandles(callingUserHandle));
} catch (Exception e) {
Log.e(this, e, "getAllPhoneAccounts");
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.view.MenuItem;
import android.view.WindowManager;

public class EnableAccountPreferenceActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addSystemFlags(
android.view.WindowManager.LayoutParams
.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);

getFragmentManager().beginTransaction()
.replace(android.R.id.content, new EnableAccountPreferenceFragment())
Expand Down
24 changes: 24 additions & 0 deletions tests/src/com/android/server/telecom/tests/CallsManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
import android.telecom.Connection;
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.Log;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
Expand Down Expand Up @@ -133,8 +136,12 @@
@RunWith(JUnit4.class)
public class CallsManagerTest extends TelecomTestCase {
private static final int TEST_TIMEOUT = 5000; // milliseconds
private static final int SECONDARY_USER_ID = 12;
private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle(
ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1");
private static final PhoneAccountHandle SIM_1_HANDLE_SECONDARY = new PhoneAccountHandle(
ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1",
new UserHandle(SECONDARY_USER_ID));
private static final PhoneAccountHandle SIM_2_HANDLE = new PhoneAccountHandle(
ComponentName.unflattenFromString("com.foo/.Blah"), "Sim2");
private static final PhoneAccountHandle CONNECTION_MGR_1_HANDLE = new PhoneAccountHandle(
Expand Down Expand Up @@ -1625,6 +1632,23 @@ public void testDisconnectDialingCall() throws Exception {
verify(callSpy, never()).setDisconnectCause(any(DisconnectCause.class));
}

@SmallTest
@Test
public void testCrossUserCallRedirectionEndEarlyForIncapablePhoneAccount() {
when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(eq(SIM_1_HANDLE_SECONDARY)))
.thenReturn(SIM_1_ACCOUNT);
mCallsManager.onUserSwitch(UserHandle.SYSTEM);

Call callSpy = addSpyCall(CallState.NEW);
mCallsManager.onCallRedirectionComplete(callSpy, TEST_ADDRESS, SIM_1_HANDLE_SECONDARY,
new GatewayInfo("foo", TEST_ADDRESS2, TEST_ADDRESS), true /* speakerphoneOn */,
VideoProfile.STATE_AUDIO_ONLY, false /* shouldCancelCall */, "" /* uiAction */);

ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
verify(callSpy).disconnect(argumentCaptor.capture());
assertTrue(argumentCaptor.getValue().contains("Unavailable phoneAccountHandle"));
}

private Call addSpyCall() {
return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,11 @@ public void testGetCallCapablePhoneAccounts() throws RemoteException {
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);

assertEquals(fullPHList,
mTSIBinder.getCallCapablePhoneAccounts(true, DEFAULT_DIALER_PACKAGE, null));
mTSIBinder.getCallCapablePhoneAccounts(
true, DEFAULT_DIALER_PACKAGE, null).getList());
assertEquals(smallPHList,
mTSIBinder.getCallCapablePhoneAccounts(false, DEFAULT_DIALER_PACKAGE, null));
mTSIBinder.getCallCapablePhoneAccounts(
false, DEFAULT_DIALER_PACKAGE, null).getList());
}

@SmallTest
Expand All @@ -412,7 +414,7 @@ public void testGetCallCapablePhoneAccountsFailure() throws RemoteException {

List<PhoneAccountHandle> result = null;
try {
result = mTSIBinder.getCallCapablePhoneAccounts(true, "", null);
result = mTSIBinder.getCallCapablePhoneAccounts(true, "", null).getList();
} catch (SecurityException e) {
// intended behavior
}
Expand Down Expand Up @@ -440,9 +442,11 @@ public void testGetPhoneAccountsSupportingScheme() throws RemoteException {
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);

assertEquals(telPHList,
mTSIBinder.getPhoneAccountsSupportingScheme("tel", DEFAULT_DIALER_PACKAGE));
mTSIBinder.getPhoneAccountsSupportingScheme(
"tel", DEFAULT_DIALER_PACKAGE).getList());
assertEquals(sipPHList,
mTSIBinder.getPhoneAccountsSupportingScheme("sip", DEFAULT_DIALER_PACKAGE));
mTSIBinder.getPhoneAccountsSupportingScheme(
"sip", DEFAULT_DIALER_PACKAGE).getList());
}

@SmallTest
Expand All @@ -458,7 +462,7 @@ public void testGetPhoneAccountsForPackage() throws RemoteException {
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
assertEquals(phoneAccountHandleList,
mTSIBinder.getPhoneAccountsForPackage(
TEL_PA_HANDLE_16.getComponentName().getPackageName()));
TEL_PA_HANDLE_16.getComponentName().getPackageName()).getList());
}

@SmallTest
Expand Down Expand Up @@ -487,7 +491,7 @@ public void testGetAllPhoneAccounts() throws RemoteException {
when(mFakePhoneAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class)))
.thenReturn(phoneAccountList);

assertEquals(2, mTSIBinder.getAllPhoneAccounts().size());
assertEquals(2, mTSIBinder.getAllPhoneAccounts().getList().size());
}

@SmallTest
Expand Down