Loading src/com/android/server/telecom/Call.java +1 −1 Original line number Diff line number Diff line Loading @@ -2968,7 +2968,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return mOriginalConnectionId; } ConnectionServiceFocusManager getConnectionServiceFocusManager() { public ConnectionServiceFocusManager getConnectionServiceFocusManager() { return mCallsManager.getConnectionServiceFocusManager(); } Loading src/com/android/server/telecom/TelecomServiceImpl.java +12 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.telecom; import static android.Manifest.permission.CALL_PHONE; import static android.Manifest.permission.CALL_PRIVILEGED; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.MODIFY_PHONE_STATE; import static android.Manifest.permission.READ_PHONE_STATE; Loading Loading @@ -1233,12 +1234,20 @@ public class TelecomServiceImpl { final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) == PackageManager.PERMISSION_GRANTED; // The Emergency Dialer has call privileged permission and uses this to place // emergency calls. We ensure permission checks in // NewOutgoingCallIntentBroadcaster#process pass by sending this to // Telecom as an ACTION_CALL_PRIVILEGED intent (which makes sense since the // com.android.phone process has that permission). final boolean hasCallPrivilegedPermission = mContext.checkCallingPermission( CALL_PRIVILEGED) == PackageManager.PERMISSION_GRANTED; synchronized (mLock) { final UserHandle userHandle = Binder.getCallingUserHandle(); long token = Binder.clearCallingIdentity(); try { final Intent intent = new Intent(Intent.ACTION_CALL, handle); final Intent intent = new Intent(hasCallPrivilegedPermission ? Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, handle); if (extras != null) { extras.setDefusable(true); intent.putExtras(extras); Loading @@ -1246,7 +1255,8 @@ public class TelecomServiceImpl { mUserCallIntentProcessorFactory.create(mContext, userHandle) .processIntent( intent, callingPackage, isSelfManaged || (hasCallAppOp && hasCallPermission)); (hasCallAppOp && hasCallPermission), true /* isLocalInvocation */); } finally { Binder.restoreCallingIdentity(token); } Loading src/com/android/server/telecom/components/UserCallActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ public class UserCallActivity extends Activity implements TelecomSystem.Componen // ActivityThread.ActivityClientRecord#intent directly. // Modifying directly may be a potential risk when relaunching this activity. new UserCallIntentProcessor(this, userHandle).processIntent(new Intent(intent), getCallingPackage(), true /* hasCallAppOp*/); getCallingPackage(), true /* hasCallAppOp*/, false /* isLocalInvocation */); } finally { Log.endSession(); wakelock.release(); Loading src/com/android/server/telecom/components/UserCallIntentProcessor.java +33 −11 Original line number Diff line number Diff line Loading @@ -18,15 +18,14 @@ package com.android.server.telecom.components; import com.android.server.telecom.CallIntentProcessor; import com.android.server.telecom.R; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.TelephonyUtil; import com.android.server.telecom.UserUtil; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.AppOpsManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; Loading @@ -37,7 +36,6 @@ import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.widget.Toast; // TODO: Needed for move to system service: import com.android.internal.R; Loading Loading @@ -72,9 +70,18 @@ public class UserCallIntentProcessor { * Processes intents sent to the activity. * * @param intent The intent. * @param callingPackageName The package name of the calling app. * @param canCallNonEmergency {@code true} if the caller is permitted to call non-emergency * numbers. * @param isLocalInvocation {@code true} if the caller is within the system service (i.e. the * caller is {@link com.android.server.telecom.TelecomServiceImpl}) * and we can skip the re-broadcast of the intent to Telecom. * When {@code false}, we need to re-broadcast the intent to Telcom * to trampoline it to the system service where the Telecom * service resides. */ public void processIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency) { boolean canCallNonEmergency, boolean isLocalInvocation) { // Ensure call intents are not processed on devices that are not capable of calling. if (!isVoiceCapable()) { return; Loading @@ -85,12 +92,13 @@ public class UserCallIntentProcessor { if (Intent.ACTION_CALL.equals(action) || Intent.ACTION_CALL_PRIVILEGED.equals(action) || Intent.ACTION_CALL_EMERGENCY.equals(action)) { processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency); processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency, isLocalInvocation); } } private void processOutgoingCallIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency) { boolean canCallNonEmergency, boolean isLocalInvocation) { Uri handle = intent.getData(); String scheme = handle.getScheme(); String uriString = handle.getSchemeSpecificPart(); Loading Loading @@ -144,7 +152,7 @@ public class UserCallIntentProcessor { // Save the user handle of current user before forwarding the intent to primary user. intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle); sendBroadcastToReceiver(intent); sendIntentToDestination(intent, isLocalInvocation); } private boolean isDefaultOrSystemDialer(String callingPackageName) { Loading Loading @@ -174,14 +182,28 @@ public class UserCallIntentProcessor { } /** * Trampolines the intent to the broadcast receiver that runs only as the primary user. * Potentially trampolines the intent to the broadcast receiver that runs only as the primary * user. If the caller is local to the Telecom service, we send the intent to Telecom without * rebroadcasting it. */ private boolean sendBroadcastToReceiver(Intent intent) { private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation) { intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false); intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.setClass(mContext, PrimaryCallReceiver.class); Log.d(this, "Sending broadcast as user to CallReceiver"); if (isLocalInvocation) { // We are invoking this from TelecomServiceImpl, so TelecomSystem is available. Don't // bother trampolining the intent, just sent it directly to the call intent processor. // TODO: We should not be using an intent here; this whole flows needs cleanup. Log.i(this, "sendIntentToDestination: send intent to Telecom directly."); synchronized (TelecomSystem.getInstance().getLock()) { TelecomSystem.getInstance().getCallIntentProcessor().processIntent(intent); } } else { // We're calling from the UserCallActivity, so the TelecomSystem is not in the same // process; we need to trampoline to TelecomSystem in the system server process. Log.i(this, "sendIntentToDestination: trampoline to Telecom."); mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM); } return true; } Loading tests/src/com/android/server/telecom/tests/BasicCallTests.java +25 −5 Original line number Diff line number Diff line Loading @@ -442,6 +442,7 @@ public class BasicCallTests extends TelecomSystemTest { @LargeTest @Test @FlakyTest public void testIncomingCallFromBlockedNumberIsRejected() throws Exception { String phoneNumber = "650-555-1212"; blockNumber(phoneNumber); Loading Loading @@ -986,19 +987,37 @@ public class BasicCallTests extends TelecomSystemTest { } /** * Basic test to ensure that when there are other calls, we do not permit outgoing calls by a * self managed CS. * Ensure if there is a holdable call ongoing we'll be able to place another call. * @throws Exception */ @LargeTest @Test public void testIsOutgoingCallPermittedOngoingHoldable() throws Exception { // Start a regular call; the self-managed CS can make a call now since ongoing call can be // held IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle())); } /** * Ensure if there is an unholdable call we can't place another call. * @throws Exception */ @LargeTest @Test public void testIsOutgoingCallPermittedOngoing() throws Exception { // Start a regular call; the self-managed CS can't make a call now. public void testIsOutgoingCallPermittedOngoingUnHoldable() throws Exception { // Start a regular call; the self-managed CS can't make a call now because the ongoing call // can't be held. mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 0; IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); assertFalse(mTelecomSystem.getTelecomServiceImpl().getBinder() assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle())); } Loading @@ -1009,6 +1028,7 @@ public class BasicCallTests extends TelecomSystemTest { */ @LargeTest @Test @FlakyTest public void testDisconnectSelfManaged() throws Exception { // Add a self-managed call. PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle(); Loading Loading
src/com/android/server/telecom/Call.java +1 −1 Original line number Diff line number Diff line Loading @@ -2968,7 +2968,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, return mOriginalConnectionId; } ConnectionServiceFocusManager getConnectionServiceFocusManager() { public ConnectionServiceFocusManager getConnectionServiceFocusManager() { return mCallsManager.getConnectionServiceFocusManager(); } Loading
src/com/android/server/telecom/TelecomServiceImpl.java +12 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.telecom; import static android.Manifest.permission.CALL_PHONE; import static android.Manifest.permission.CALL_PRIVILEGED; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.MODIFY_PHONE_STATE; import static android.Manifest.permission.READ_PHONE_STATE; Loading Loading @@ -1233,12 +1234,20 @@ public class TelecomServiceImpl { final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) == PackageManager.PERMISSION_GRANTED; // The Emergency Dialer has call privileged permission and uses this to place // emergency calls. We ensure permission checks in // NewOutgoingCallIntentBroadcaster#process pass by sending this to // Telecom as an ACTION_CALL_PRIVILEGED intent (which makes sense since the // com.android.phone process has that permission). final boolean hasCallPrivilegedPermission = mContext.checkCallingPermission( CALL_PRIVILEGED) == PackageManager.PERMISSION_GRANTED; synchronized (mLock) { final UserHandle userHandle = Binder.getCallingUserHandle(); long token = Binder.clearCallingIdentity(); try { final Intent intent = new Intent(Intent.ACTION_CALL, handle); final Intent intent = new Intent(hasCallPrivilegedPermission ? Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, handle); if (extras != null) { extras.setDefusable(true); intent.putExtras(extras); Loading @@ -1246,7 +1255,8 @@ public class TelecomServiceImpl { mUserCallIntentProcessorFactory.create(mContext, userHandle) .processIntent( intent, callingPackage, isSelfManaged || (hasCallAppOp && hasCallPermission)); (hasCallAppOp && hasCallPermission), true /* isLocalInvocation */); } finally { Binder.restoreCallingIdentity(token); } Loading
src/com/android/server/telecom/components/UserCallActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ public class UserCallActivity extends Activity implements TelecomSystem.Componen // ActivityThread.ActivityClientRecord#intent directly. // Modifying directly may be a potential risk when relaunching this activity. new UserCallIntentProcessor(this, userHandle).processIntent(new Intent(intent), getCallingPackage(), true /* hasCallAppOp*/); getCallingPackage(), true /* hasCallAppOp*/, false /* isLocalInvocation */); } finally { Log.endSession(); wakelock.release(); Loading
src/com/android/server/telecom/components/UserCallIntentProcessor.java +33 −11 Original line number Diff line number Diff line Loading @@ -18,15 +18,14 @@ package com.android.server.telecom.components; import com.android.server.telecom.CallIntentProcessor; import com.android.server.telecom.R; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.TelephonyUtil; import com.android.server.telecom.UserUtil; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.AppOpsManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; Loading @@ -37,7 +36,6 @@ import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.widget.Toast; // TODO: Needed for move to system service: import com.android.internal.R; Loading Loading @@ -72,9 +70,18 @@ public class UserCallIntentProcessor { * Processes intents sent to the activity. * * @param intent The intent. * @param callingPackageName The package name of the calling app. * @param canCallNonEmergency {@code true} if the caller is permitted to call non-emergency * numbers. * @param isLocalInvocation {@code true} if the caller is within the system service (i.e. the * caller is {@link com.android.server.telecom.TelecomServiceImpl}) * and we can skip the re-broadcast of the intent to Telecom. * When {@code false}, we need to re-broadcast the intent to Telcom * to trampoline it to the system service where the Telecom * service resides. */ public void processIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency) { boolean canCallNonEmergency, boolean isLocalInvocation) { // Ensure call intents are not processed on devices that are not capable of calling. if (!isVoiceCapable()) { return; Loading @@ -85,12 +92,13 @@ public class UserCallIntentProcessor { if (Intent.ACTION_CALL.equals(action) || Intent.ACTION_CALL_PRIVILEGED.equals(action) || Intent.ACTION_CALL_EMERGENCY.equals(action)) { processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency); processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency, isLocalInvocation); } } private void processOutgoingCallIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency) { boolean canCallNonEmergency, boolean isLocalInvocation) { Uri handle = intent.getData(); String scheme = handle.getScheme(); String uriString = handle.getSchemeSpecificPart(); Loading Loading @@ -144,7 +152,7 @@ public class UserCallIntentProcessor { // Save the user handle of current user before forwarding the intent to primary user. intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle); sendBroadcastToReceiver(intent); sendIntentToDestination(intent, isLocalInvocation); } private boolean isDefaultOrSystemDialer(String callingPackageName) { Loading Loading @@ -174,14 +182,28 @@ public class UserCallIntentProcessor { } /** * Trampolines the intent to the broadcast receiver that runs only as the primary user. * Potentially trampolines the intent to the broadcast receiver that runs only as the primary * user. If the caller is local to the Telecom service, we send the intent to Telecom without * rebroadcasting it. */ private boolean sendBroadcastToReceiver(Intent intent) { private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation) { intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false); intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.setClass(mContext, PrimaryCallReceiver.class); Log.d(this, "Sending broadcast as user to CallReceiver"); if (isLocalInvocation) { // We are invoking this from TelecomServiceImpl, so TelecomSystem is available. Don't // bother trampolining the intent, just sent it directly to the call intent processor. // TODO: We should not be using an intent here; this whole flows needs cleanup. Log.i(this, "sendIntentToDestination: send intent to Telecom directly."); synchronized (TelecomSystem.getInstance().getLock()) { TelecomSystem.getInstance().getCallIntentProcessor().processIntent(intent); } } else { // We're calling from the UserCallActivity, so the TelecomSystem is not in the same // process; we need to trampoline to TelecomSystem in the system server process. Log.i(this, "sendIntentToDestination: trampoline to Telecom."); mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM); } return true; } Loading
tests/src/com/android/server/telecom/tests/BasicCallTests.java +25 −5 Original line number Diff line number Diff line Loading @@ -442,6 +442,7 @@ public class BasicCallTests extends TelecomSystemTest { @LargeTest @Test @FlakyTest public void testIncomingCallFromBlockedNumberIsRejected() throws Exception { String phoneNumber = "650-555-1212"; blockNumber(phoneNumber); Loading Loading @@ -986,19 +987,37 @@ public class BasicCallTests extends TelecomSystemTest { } /** * Basic test to ensure that when there are other calls, we do not permit outgoing calls by a * self managed CS. * Ensure if there is a holdable call ongoing we'll be able to place another call. * @throws Exception */ @LargeTest @Test public void testIsOutgoingCallPermittedOngoingHoldable() throws Exception { // Start a regular call; the self-managed CS can make a call now since ongoing call can be // held IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle())); } /** * Ensure if there is an unholdable call we can't place another call. * @throws Exception */ @LargeTest @Test public void testIsOutgoingCallPermittedOngoing() throws Exception { // Start a regular call; the self-managed CS can't make a call now. public void testIsOutgoingCallPermittedOngoingUnHoldable() throws Exception { // Start a regular call; the self-managed CS can't make a call now because the ongoing call // can't be held. mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 0; IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); assertFalse(mTelecomSystem.getTelecomServiceImpl().getBinder() assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle())); } Loading @@ -1009,6 +1028,7 @@ public class BasicCallTests extends TelecomSystemTest { */ @LargeTest @Test @FlakyTest public void testDisconnectSelfManaged() throws Exception { // Add a self-managed call. PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle(); Loading