Merge "fix security exception in VoipCallMonitor" into udc-dev
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 591ce72..6e5826b 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -39,6 +39,7 @@
 import android.provider.CallLog;
 import android.provider.ContactsContract.Contacts;
 import android.telecom.BluetoothCallQualityReport;
+import android.telecom.CallAttributes;
 import android.telecom.CallAudioState;
 import android.telecom.CallDiagnosticService;
 import android.telecom.CallDiagnostics;
@@ -556,7 +557,25 @@
     private boolean mIsSelfManaged = false;
 
     private boolean mIsTransactionalCall = false;
-    private int mOwnerPid = -1;
+    private CallingPackageIdentity mCallingPackageIdentity = new CallingPackageIdentity();
+
+    /**
+     * CallingPackageIdentity is responsible for storing properties about the calling package that
+     * initiated the call. For example, if MyVoipApp requests to add a call with Telecom, we can
+     * store their UID and PID when we are still bound to that package.
+     */
+    public static class CallingPackageIdentity {
+        public int mCallingPackageUid = -1;
+        public int mCallingPackagePid = -1;
+
+        public CallingPackageIdentity() {
+        }
+
+        CallingPackageIdentity(Bundle extras) {
+            mCallingPackageUid = extras.getInt(CallAttributes.CALLER_UID_KEY, -1);
+            mCallingPackagePid = extras.getInt(CallAttributes.CALLER_PID_KEY, -1);
+        }
+    }
 
     /**
      * Indicates whether this call is streaming.
@@ -1832,12 +1851,15 @@
         setConnectionProperties(getConnectionProperties());
     }
 
-    public void setOwnerPid(int pid) {
-        mOwnerPid = pid;
+    public void setCallingPackageIdentity(Bundle extras) {
+        mCallingPackageIdentity = new CallingPackageIdentity(extras);
+        // These extras should NOT be propagated to Dialer and should be removed.
+        extras.remove(CallAttributes.CALLER_PID_KEY);
+        extras.remove(CallAttributes.CALLER_UID_KEY);
     }
 
-    public int getOwnerPid() {
-        return mOwnerPid;
+    public CallingPackageIdentity getCallingPackageIdentity() {
+        return mCallingPackageIdentity;
     }
 
     public void setTransactionServiceWrapper(TransactionalServiceWrapper service) {
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 0dc37fa..9503c10 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -1405,8 +1405,7 @@
         // set properties for transactional call
         if (extras.containsKey(TelecomManager.TRANSACTION_CALL_ID_KEY)) {
             call.setIsTransactionalCall(true);
-            call.setOwnerPid(extras.getInt(CallAttributes.CALLER_PID, -1));
-            extras.remove(CallAttributes.CALLER_PID);
+            call.setCallingPackageIdentity(extras);
             call.setConnectionCapabilities(
                     extras.getInt(CallAttributes.CALL_CAPABILITIES_KEY,
                             CallAttributes.SUPPORTS_SET_INACTIVE), true);
@@ -1717,8 +1716,7 @@
 
             if (extras.containsKey(TelecomManager.TRANSACTION_CALL_ID_KEY)) {
                 call.setIsTransactionalCall(true);
-                call.setOwnerPid(extras.getInt(CallAttributes.CALLER_PID, -1));
-                extras.remove(CallAttributes.CALLER_PID);
+                call.setCallingPackageIdentity(extras);
                 call.setConnectionCapabilities(
                         extras.getInt(CallAttributes.CALL_CAPABILITIES_KEY,
                                 CallAttributes.SUPPORTS_SET_INACTIVE), true);
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 47c4acf..5f1b537 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -195,14 +195,15 @@
 
                 // add extras about info used for FGS delegation
                 Bundle extras = new Bundle();
-                extras.putInt(CallAttributes.CALLER_PID, Binder.getCallingPid());
+                extras.putInt(CallAttributes.CALLER_UID_KEY, Binder.getCallingUid());
+                extras.putInt(CallAttributes.CALLER_PID_KEY, Binder.getCallingPid());
 
                 VoipCallTransaction transaction = null;
                 // create transaction based on the call direction
                 switch (callAttributes.getDirection()) {
                     case DIRECTION_OUTGOING:
                         transaction = new OutgoingCallTransaction(callId, mContext, callAttributes,
-                                mCallsManager);
+                                mCallsManager, extras);
                         break;
                     case DIRECTION_INCOMING:
                         transaction = new IncomingCallTransaction(callId, callAttributes,
diff --git a/src/com/android/server/telecom/voip/VoipCallMonitor.java b/src/com/android/server/telecom/voip/VoipCallMonitor.java
index 04af98f..67af11d 100644
--- a/src/com/android/server/telecom/voip/VoipCallMonitor.java
+++ b/src/com/android/server/telecom/voip/VoipCallMonitor.java
@@ -143,8 +143,9 @@
                     k -> new HashSet<>());
             callList.add(call);
 
-            mHandler.post(() -> startFGSDelegation(call.getOwnerPid(),
-                    phoneAccountHandle.getUserHandle().getIdentifier(), call));
+            mHandler.post(
+                    () -> startFGSDelegation(call.getCallingPackageIdentity().mCallingPackagePid,
+                            call.getCallingPackageIdentity().mCallingPackageUid, call));
         }
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/CallTest.java b/tests/src/com/android/server/telecom/tests/CallTest.java
index 6b817d8..997e7dd 100644
--- a/tests/src/com/android/server/telecom/tests/CallTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallTest.java
@@ -26,16 +26,11 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.content.ComponentName;
 import android.content.Intent;
@@ -43,7 +38,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Parcel;
+import android.telecom.CallAttributes;
 import android.telecom.CallerInfo;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
@@ -56,12 +51,10 @@
 import android.telecom.VideoProfile;
 import android.telephony.CallQuality;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 import android.widget.Toast;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.internal.telecom.IVideoProvider;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallIdMapper;
 import com.android.server.telecom.CallState;
@@ -69,8 +62,6 @@
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.ClockProxy;
 import com.android.server.telecom.ConnectionServiceWrapper;
-import com.android.server.telecom.InCallController;
-import com.android.server.telecom.InCallController.InCallServiceInfo;
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.PhoneNumberUtilsAdapter;
 import com.android.server.telecom.TelecomSystem;
@@ -640,8 +631,40 @@
         verify(listener).onFailedUnknownCall(unknownCall);
     }
 
+    /**
+     * ensure a Call object does not throw an NPE when the CallingPackageIdentity is not set and
+     * the correct values are returned when set
+     */
     @Test
     @SmallTest
+    public void testCallingPackageIdentity() {
+        final int packageUid = 123;
+        final int packagePid = 1;
+
+        Call call = createCall("1");
+
+        // assert default values for a Calls CallingPackageIdentity are -1 unless set via the setter
+        assertEquals(-1, call.getCallingPackageIdentity().mCallingPackageUid);
+        assertEquals(-1, call.getCallingPackageIdentity().mCallingPackagePid);
+
+        // set the Call objects CallingPackageIdentity via the setter and a bundle
+        Bundle extras = new Bundle();
+        extras.putInt(CallAttributes.CALLER_UID_KEY, packageUid);
+        extras.putInt(CallAttributes.CALLER_PID_KEY, packagePid);
+        // assert that the setter removed the extras
+        assertEquals(packageUid, extras.getInt(CallAttributes.CALLER_UID_KEY));
+        assertEquals(packagePid, extras.getInt(CallAttributes.CALLER_PID_KEY));
+        call.setCallingPackageIdentity(extras);
+        // assert that the setter removed the extras
+        assertEquals(0, extras.getInt(CallAttributes.CALLER_UID_KEY));
+        assertEquals(0, extras.getInt(CallAttributes.CALLER_PID_KEY));
+        // assert the properties are fetched correctly
+        assertEquals(packageUid, call.getCallingPackageIdentity().mCallingPackageUid);
+        assertEquals(packagePid, call.getCallingPackageIdentity().mCallingPackagePid);
+    }
+
+        @Test
+    @SmallTest
     public void testOnConnectionEventNotifiesListener() {
         Call.Listener listener = mock(Call.Listener.class);
         Call call = createCall("1");
diff --git a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
index 7b6bd3e..346b3d8 100644
--- a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
+++ b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
@@ -212,6 +212,7 @@
         when(call.isTransactionalCall()).thenReturn(true);
         when(call.getExtras()).thenReturn(new Bundle());
         when(call.getId()).thenReturn(id);
+        when(call.getCallingPackageIdentity()).thenReturn( new Call.CallingPackageIdentity() );
         return call;
     }
 }