Limit Carrier Privileges to relevant CTS test app

The Android framework queries the SIM card to identify apps that should
have carrier privileges. Currently the emulator's virtual SIM card does
this by providing a certificate hash and any app signed by the matching
certificate will receive carrier privileges. Unfortunately CTS test apps
that have test requiring that they do NOT have carrier privileges are
signed by the same certificate and will fail because they DO have
access. Luckily the framework also supports using package names in
addition to certificate hashes to specify which apps should have
permission. This change adds support for providing such package names
and limits the carrier privileges to the carrier privileges CTS test
app. This revokes privileges from the other test apps and allows those
tests to succeed.

BUG: 33052562
Change-Id: Ie147a1a81d0cc4fd93213022aff7ec83b84d4493
diff --git a/android/android-emu/android/telephony/SimAccessRules.cpp b/android/android-emu/android/telephony/SimAccessRules.cpp
index b470043..37a96a0 100644
--- a/android/android-emu/android/telephony/SimAccessRules.cpp
+++ b/android/android-emu/android/telephony/SimAccessRules.cpp
@@ -27,8 +27,8 @@
 static AllRefArDo kCtsAppCertificateHash {
     RefArDo {
         RefDo {
-            AidRefDo {},
-            DeviceAppIdRefDo { "61ed377e85d386a8dfee6b864bd85b0bfaa5af81" }
+            DeviceAppIdRefDo { "61ed377e85d386a8dfee6b864bd85b0bfaa5af81" },
+            PkgRefDo { "android.carrierapi.cts" }
         },
         ArDo {
             PermArDo { "0000000000000000" }
diff --git a/android/android-emu/android/telephony/TagLengthValue.cpp b/android/android-emu/android/telephony/TagLengthValue.cpp
index 17fd34b..3a38d88 100644
--- a/android/android-emu/android/telephony/TagLengthValue.cpp
+++ b/android/android-emu/android/telephony/TagLengthValue.cpp
@@ -11,6 +11,8 @@
 */
 #include "TagLengthValue.h"
 
+#include "android/utils/misc.h"
+
 #include <assert.h>
 #include <vector>
 #include <stdint.h>
@@ -30,6 +32,17 @@
 // Size: 0x12345, String: "83012345" -- 83 indicates 3 bytes needed, zero padded
 static const uint32_t kMaxSingleByteSize = 0x80;
 
+// Convert a plain string to a string of hexadecimal values representing the
+// value of each character of the plain string. For example the string "FOO"
+// will be converted to "464F4F".
+static std::string stringToHexString(const std::string& str) {
+    std::string result(str.size() * 2, '0');
+    for (size_t i = 0; i < str.size(); ++i) {
+        int2hex(reinterpret_cast<uint8_t*>(&result[i * 2]), 2, str[i]);
+    }
+    return result;
+}
+
 void TagLengthValue::populateData(const char* tag,
         std::initializer_list<const TagLengthValue*> data) {
     populateData(tag, data.begin(), data.end());
@@ -89,6 +102,7 @@
 }
 
 const char AidRefDo::kTag[] = "4F";
+const char PkgRefDo::kTag[] = "CA";
 const char DeviceAppIdRefDo::kTag[] = "C1";
 const char RefDo::kTag[] = "E1";
 const char ApduArDo::kTag[] = "D0";
@@ -98,15 +112,29 @@
 const char RefArDo::kTag[] = "E2";
 const char AllRefArDo::kTag[] = "FF40";
 
+PkgRefDo::PkgRefDo(const std::string& packageName) {
+    std::string hexPackageName = stringToHexString(packageName);
+    populateData(kTag, { &hexPackageName });
+}
+
 DeviceAppIdRefDo::DeviceAppIdRefDo(const std::string& stringData) {
     populateData(kTag, { &stringData });
 }
 
+RefDo::RefDo(const DeviceAppIdRefDo& deviceAppIdRefDo) {
+    populateData(kTag, { &deviceAppIdRefDo });
+}
+
 RefDo::RefDo(const AidRefDo& aidRefDo,
              const DeviceAppIdRefDo& deviceAppIdRefDo) {
     populateData(kTag, { &aidRefDo, &deviceAppIdRefDo });
 }
 
+RefDo::RefDo(const DeviceAppIdRefDo& deviceAppIdRefDo,
+             const PkgRefDo& pkgRefDo) {
+    populateData(kTag, { &deviceAppIdRefDo, &pkgRefDo });
+}
+
 ApduArDo::ApduArDo(Allow rule) {
     // Allocate enough space for the data plus NULL, then resize down to 2 to
     // avoid modifying the terminating NULL (which is undefined behavior)
diff --git a/android/android-emu/android/telephony/TagLengthValue.h b/android/android-emu/android/telephony/TagLengthValue.h
index 7f5e625..93bc789 100644
--- a/android/android-emu/android/telephony/TagLengthValue.h
+++ b/android/android-emu/android/telephony/TagLengthValue.h
@@ -60,6 +60,15 @@
     static const char kTag[];
 };
 
+// PKG-REF-DO, contains a package name string identifying a particular
+// application. If a package name is present the access rule only applies to the
+// package matching this name
+class PkgRefDo : public TagLengthValue {
+    static const char kTag[];
+public:
+    explicit PkgRefDo(const std::string& packageName);
+};
+
 // DeviceAppID-REF-DO, contains a unique app ID or hash of a certificate used
 // to sign an app.
 class DeviceAppIdRefDo : public TagLengthValue {
@@ -69,12 +78,17 @@
     explicit DeviceAppIdRefDo(const std::string& stringData);
 };
 
-// REF-DO, Reference Data Object, contains an AID reference and DeviceAppID
-// reference that together uniquely identify an application
+// REF-DO, Reference Data Object, contains a DeviceAppID reference and
+// optionally either an AidRefDo or a PkgRefDo. This uniquely identifies an
+// application.
 class RefDo : public TagLengthValue {
     static const char kTag[];
 public:
-    RefDo(const AidRefDo& aidRefDo, const DeviceAppIdRefDo& deviceAppIdRefDo);
+    explicit RefDo(const DeviceAppIdRefDo& deviceAppIdRefDo);
+    RefDo(const AidRefDo& aidRefDo,
+          const DeviceAppIdRefDo& deviceAppIdRefDo);
+    RefDo(const DeviceAppIdRefDo& deviceAppIdRefDo,
+          const PkgRefDo& pkgRefDo);
 };
 
 // APDU-AR-DO, used to set access rules regarding APDU commands, can be used to
diff --git a/android/android-emu/android/telephony/TagLengthValue_unittest.cpp b/android/android-emu/android/telephony/TagLengthValue_unittest.cpp
index 480ec4d..d9d7aa6 100644
--- a/android/android-emu/android/telephony/TagLengthValue_unittest.cpp
+++ b/android/android-emu/android/telephony/TagLengthValue_unittest.cpp
@@ -24,8 +24,23 @@
                  deviceAppIdRefDo.c_str());
 }
 
+TEST(TagLengthValue, ConstructPkgRefDo) {
+    PkgRefDo pkgRefDo("com.android.foo");
+
+    ASSERT_STREQ(/*tag*/ "CA" /*length*/ "0f"
+                 /*payload*/ "636f6d2e616e64726f69642e666f6f",
+                 pkgRefDo.c_str());
+}
+
 TEST(TagLengthValue, ConstructRefDo) {
-    RefDo refDo(AidRefDo(), DeviceAppIdRefDo("C0FFEE"));
+    RefDo refDo{DeviceAppIdRefDo("C0FFEE")};
+
+    ASSERT_STREQ(/*tag*/ "E1" /*length*/ "05" /*payload*/ "C103C0FFEE",
+                 refDo.c_str());
+}
+
+TEST(TagLengthValue, ConstructRefDoWithAidRefDo) {
+    RefDo refDo{AidRefDo(), DeviceAppIdRefDo("C0FFEE")};
 
     // Note that the AID-REF-DO does not end up in the payload because we
     // construct an empty object.
@@ -33,6 +48,14 @@
                  refDo.c_str());
 }
 
+TEST(TagLengthValue, ConstructRefDoWithPkgRefDo) {
+    RefDo refDo{DeviceAppIdRefDo("C0FFEE"), PkgRefDo("foo")};
+
+    ASSERT_STREQ(/*tag*/ "E1" /*length*/ "0a"
+                 /*payload*/ "C103C0FFEECA03666f6f",
+                 refDo.c_str());
+}
+
 TEST(TagLengthValue, ConstructApduArDo) {
     ApduArDo globalDenyRule(ApduArDo::Allow::Never);
     ASSERT_STREQ(/*tag*/ "D0" /*length*/ "01" /*payload*/ "00",
diff --git a/android/android-emu/android/telephony/modem_unittest.cpp b/android/android-emu/android/telephony/modem_unittest.cpp
index 7d69d63..12cad11 100644
--- a/android/android-emu/android/telephony/modem_unittest.cpp
+++ b/android/android-emu/android/telephony/modem_unittest.cpp
@@ -101,7 +101,7 @@
     ASSERT_FALSE(closeLogicalChannel(channel));
 }
 
-static const char* kValidReply = "+CGLA: 144,0,FF4026E224E116C11461ed377e85d386a8dfee6b864bd85b0bfaa5af81E30aDB080000000000000000\rOK";
+static const char* kValidReply = "+CGLA: 144,0,FF403eE23cE12eC11461ed377e85d386a8dfee6b864bd85b0bfaa5af81CA16616e64726f69642e636172726965726170692e637473E30aDB080000000000000000\rOK";
 static const char* kCmeError = "+CME ERROR: ";
 
 TEST_F(ModemTest, TransmitLogicalChannel) {