SmsSenderCallback: Run the callback with the phone UID.

The SmsSenderCallback needs to run as the phone UID because of checks that
ensure only the messaging app or phone process can run that code.

Also modifies SmsUsageMonitor to allow phone process to make calls.

Bug: 19302541
Change-Id: Ic6b8141fbf15f42696e9b86d3c599ef2ec4ebd1c
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index fad63cb..6db5cac 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -35,8 +35,10 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms;
@@ -431,8 +433,14 @@
          */
         @Override
         public void onSendSmsComplete(int result, int messageRef) {
-            mSmsSender.disposeConnection(mContext);
-            processSendSmsResponse(mSmsSender.mTracker, result, messageRef);
+            checkCallerIsPhoneOrCarrierApp();
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                mSmsSender.disposeConnection(mContext);
+                processSendSmsResponse(mSmsSender.mTracker, result, messageRef);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
         }
 
         @Override
@@ -558,12 +566,18 @@
                 return;
             }
 
-            for (int i = 0; i < mSmsSender.mTrackers.length; i++) {
-                int messageRef = 0;
-                if (messageRefs != null && messageRefs.length > i) {
-                    messageRef = messageRefs[i];
+            checkCallerIsPhoneOrCarrierApp();
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                for (int i = 0; i < mSmsSender.mTrackers.length; i++) {
+                    int messageRef = 0;
+                    if (messageRefs != null && messageRefs.length > i) {
+                        messageRef = messageRefs[i];
+                    }
+                    processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef);
                 }
-                processSendSmsResponse(mSmsSender.mTrackers[i], result, messageRef);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
@@ -1696,4 +1710,21 @@
     protected int getSubId() {
         return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhone.mPhoneId);
     }
+
+    private void checkCallerIsPhoneOrCarrierApp() {
+        int uid = Binder.getCallingUid();
+        int appId = UserHandle.getAppId(uid);
+        if (appId == Process.PHONE_UID || uid == 0) {
+            return;
+        }
+        try {
+            PackageManager pm = mContext.getPackageManager();
+            ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0);
+            if (!UserHandle.isSameApp(ai.uid, Binder.getCallingUid())) {
+                throw new SecurityException("Caller is not phone or carrier app!");
+            }
+        } catch (PackageManager.NameNotFoundException re) {
+            throw new SecurityException("Caller is not phone or carrier app!");
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/SmsUsageMonitor.java b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
index aa9f4e5..b9a0af1 100644
--- a/src/java/com/android/internal/telephony/SmsUsageMonitor.java
+++ b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
@@ -540,7 +540,7 @@
      * @throws SecurityException if the caller is not a system process
      */
     public int getPremiumSmsPermission(String packageName) {
-        checkCallerIsSystemOrSameApp(packageName);
+        checkCallerIsSystemOrPhoneOrSameApp(packageName);
         synchronized (mPremiumSmsPolicy) {
             Integer policy = mPremiumSmsPolicy.get(packageName);
             if (policy == null) {
@@ -578,9 +578,10 @@
         }).start();
     }
 
-    private static void checkCallerIsSystemOrSameApp(String pkg) {
+    private static void checkCallerIsSystemOrPhoneOrSameApp(String pkg) {
         int uid = Binder.getCallingUid();
-        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+        int appId = UserHandle.getAppId(uid);
+        if (appId == Process.SYSTEM_UID || appId == Process.PHONE_UID || uid == 0) {
             return;
         }
         try {