diff options
4 files changed, 114 insertions, 34 deletions
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java index 31442297b1..1e184bb69a 100644 --- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java +++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java @@ -108,6 +108,10 @@ public class CarrierPrivilegesTracker extends Handler { private static final String SHA_1 = "SHA-1"; private static final String SHA_256 = "SHA-256"; + private static final int PACKAGE_NOT_PRIVILEGED = 0; + private static final int PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG = 1; + private static final int PACKAGE_PRIVILEGED_FROM_SIM = 2; + // TODO(b/232273884): Turn feature on when find solution to handle the inter-carriers switching /** * Time delay to clear UICC rules after UICC is gone. @@ -757,23 +761,35 @@ public class CarrierPrivilegesTracker extends Handler { @NonNull private PrivilegedPackageInfo getCurrentPrivilegedPackagesForAllUsers() { + Set<String> carrierServiceEligiblePackages = new ArraySet<>(); Set<String> privilegedPackageNames = new ArraySet<>(); Set<Integer> privilegedUids = new ArraySet<>(); for (Map.Entry<String, Set<String>> e : mInstalledPackageCerts.entrySet()) { - if (isPackagePrivileged(e.getKey(), e.getValue())) { - privilegedPackageNames.add(e.getKey()); - privilegedUids.addAll(getUidsForPackage(e.getKey(), /* invalidateCache= */ false)); + final int priv = getPackagePrivilegedStatus(e.getKey(), e.getValue()); + switch (priv) { + case PACKAGE_PRIVILEGED_FROM_SIM: + carrierServiceEligiblePackages.add(e.getKey()); + // fallthrough + case PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG: + privilegedPackageNames.add(e.getKey()); + privilegedUids.addAll( + getUidsForPackage(e.getKey(), /* invalidateCache= */ false)); } } - return new PrivilegedPackageInfo(privilegedPackageNames, privilegedUids, - getCarrierService(privilegedPackageNames)); + + return new PrivilegedPackageInfo( + privilegedPackageNames, + privilegedUids, + getCarrierService(carrierServiceEligiblePackages)); } /** - * Returns true iff there is an overlap between the provided certificate hashes and the - * certificate hashes stored in mTestOverrideRules, mCarrierConfigRules and mUiccRules. + * Returns the privilege status of the provided package. + * + * <p>Returned privilege status depends on whether a package matches the certificates from + * carrier config, from test overrides or from certificates stored on the SIM. */ - private boolean isPackagePrivileged(@NonNull String pkgName, @NonNull Set<String> certs) { + private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull Set<String> certs) { // Double-nested for loops, but each collection should contain at most 2 elements in nearly // every case. // TODO(b/184382310) find a way to speed this up @@ -782,23 +798,23 @@ public class CarrierPrivilegesTracker extends Handler { if (mTestOverrideRules != null) { for (UiccAccessRule rule : mTestOverrideRules) { if (rule.matches(cert, pkgName)) { - return true; + return PACKAGE_PRIVILEGED_FROM_SIM; } } } else { - for (UiccAccessRule rule : mCarrierConfigRules) { + for (UiccAccessRule rule : mUiccRules) { if (rule.matches(cert, pkgName)) { - return true; + return PACKAGE_PRIVILEGED_FROM_SIM; } } - for (UiccAccessRule rule : mUiccRules) { + for (UiccAccessRule rule : mCarrierConfigRules) { if (rule.matches(cert, pkgName)) { - return true; + return PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG; } } } } - return false; + return PACKAGE_NOT_PRIVILEGED; } @NonNull @@ -1067,13 +1083,13 @@ public class CarrierPrivilegesTracker extends Handler { } @NonNull - private Pair<String, Integer> getCarrierService(@NonNull Set<String> privilegedPackageNames) { + private Pair<String, Integer> getCarrierService(@NonNull Set<String> simPrivilegedPackages) { List<ResolveInfo> carrierServiceResolveInfos = mPackageManager.queryIntentServices( new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), /* flags= */ 0); String carrierServicePackageName = null; for (ResolveInfo resolveInfo : carrierServiceResolveInfos) { String packageName = getPackageName(resolveInfo); - if (privilegedPackageNames.contains(packageName)) { + if (simPrivilegedPackages.contains(packageName)) { carrierServicePackageName = packageName; break; } diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java index 891570b751..5b8aca5aa3 100644 --- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java @@ -23,6 +23,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIV import static com.android.internal.telephony.Phone.CS_FALLBACK; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.usage.NetworkStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.BroadcastReceiver; @@ -925,8 +926,10 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { * {@code ImsReasonInfo#CODE_*} value. * * See {@link CarrierConfigManager#KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY}. + * This ImsReasonInfoKeyPair with this key stating will consider getExtraMessage a match + * if the carrier config messages starts with getExtraMessage result. */ - private Map<Pair<Integer, String>, Integer> mImsReasonCodeMap = new ArrayMap<>(); + private Map<ImsReasonInfoKeyPair, Integer> mImsReasonCodeMap = new ArrayMap<>(); /** @@ -985,6 +988,54 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { // Used for important operational related events for logging. private final LocalLog mOperationLocalLog = new LocalLog(64); + /** + * Container to ease passing around a tuple of two objects. This object provides a sensible + * implementation of equals(), returning true/false using equals() for one object (Integer) + * and startsWith() for another object (String). Also the startsWith() in this equals() method + * will return true for A.startsWith(B) if B.second starts with A.second. + */ + private static class ImsReasonInfoKeyPair extends Pair<Integer, String> { + + /** + * Constructor for a ImsReasonInfoKeyPair. + * + * @param first Integer in the ImsReasonInfoKeyPair + * @param second String in the ImsReasonInfoKeyPair + */ + private ImsReasonInfoKeyPair(Integer first, String second) { + super(first, second); + } + + /** + * Checks the two objects for equality by delegating to their respective + * {@link Object#equals(Object)} methods. + * + * @param o the {@link com.android.internal.telephony.imsphone.ImsReasonInfoKeyPair} to + * which this one is to be checked for equality + * @return true if the underlying objects of the ImsReasonInfoKeyPair are + * considered equal and startsWith + */ + @Override + public boolean equals(@Nullable Object o) { + if (!(o instanceof ImsReasonInfoKeyPair)) { + return false; + } + ImsReasonInfoKeyPair p = (ImsReasonInfoKeyPair) o; + + return Objects.equals(p.first, first) + && Objects.toString(second).startsWith(Objects.toString(p.second)); + } + + /** + * Compute a hash code using the hash code of the Integer key + * + * @return a hashcode of the first + */ + @Override + public int hashCode() { + return (first == null ? 0 : first.hashCode()); + } + } //***** Events @@ -2824,7 +2875,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { if (message != null) { message = message.toLowerCase(); } - mImsReasonCodeMap.put(new Pair<>(fromCode, message), toCode); + mImsReasonCodeMap.put(new ImsReasonInfoKeyPair(fromCode, message), toCode); } /** @@ -2847,9 +2898,10 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } log("maybeRemapReasonCode : fromCode = " + reasonInfo.getCode() + " ; message = " + reason); - Pair<Integer, String> toCheck = new Pair<>(code, reason); - Pair<Integer, String> wildcardToCheck = new Pair<>(null, reason); - Pair<Integer, String> wildcardMessageToCheck = new Pair<>(code, null); + ImsReasonInfoKeyPair toCheck = new ImsReasonInfoKeyPair(code, reason); + ImsReasonInfoKeyPair wildcardToCheck = new ImsReasonInfoKeyPair(null, reason); + ImsReasonInfoKeyPair wildcardMessageToCheck = new ImsReasonInfoKeyPair(code, null); + if (mImsReasonCodeMap.containsKey(toCheck)) { int toCode = mImsReasonCodeMap.get(toCheck); diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java index 221b2b525e..07011a30e6 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java @@ -889,7 +889,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest { @Test public void testPackageDisabledAndThenEnabled() throws Exception { // Start with certs and packages installed - setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1))); + setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1))); setupInstalledPackages( new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1), new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2)); @@ -1032,9 +1032,12 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest { } @Test - public void testGetCarrierService_haveCarrierServiceWithCarrierPrivileges() throws Exception { - // Only packages with CERT_1 have carrier privileges - setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1))); + public void testGetCarrierService_haveCarrierServiceWithSimCarrierPrivileges() + throws Exception { + // Package 1 has SIM loaded rules, making it eligible for carrier service bindings + setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1))); + // Package 2 has only carrier-config based rules, which is insufficient for carrier services + setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_2))); // Setup all odd packages privileged, even packages not setupInstalledPackages( new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1), @@ -1061,7 +1064,6 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest { assertEquals(PACKAGE_1, carrierServicePackageName); assertEquals(UID_1, carrierServiceUid); - reset(mPackageManager); // Get CS again carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName(); @@ -1072,27 +1074,32 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest { verify(mPackageManager, never()).queryIntentServices(any(), anyInt()); assertEquals(PACKAGE_1, carrierServicePackageName); assertEquals(UID_1, carrierServiceUid); - } @Test - public void testGetCarrierService_haveCarrierServiceWithNoCarrierPrivileges() throws Exception { - // Only packages with CERT_1 have carrier privileges - setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1))); + public void testGetCarrierService_haveCarrierServiceWithoutSimCarrierPrivileges() + throws Exception { + // Package 1 has no carrier privileges, package 2 has carrier-config based privileges, but + // no matching certificate on the SIM. + setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_2))); // Setup all odd packages privileged, even packages not setupInstalledPackages( new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1), new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2), new PackageCertInfo(PACKAGE_3, CERT_1, USER_1, UID_1)); - // One declared CarrierService which has no carrier privileges - ResolveInfo noPrivilegeService = new ResolveInfoBuilder().setService(PACKAGE_2).build(); + // Two declared CarrierService, only PACKAGE_1 has carrier privileges + ResolveInfo service1 = new ResolveInfoBuilder().setService(PACKAGE_1).build(); + ResolveInfo service2 = new ResolveInfoBuilder().setService(PACKAGE_2).build(); // Use doReturn instead of when/thenReturn which has NPE with unknown reason - doReturn(List.of(noPrivilegeService)).when( - mPackageManager).queryIntentServices(any(), anyInt()); + doReturn(List.of(service1, service2)) + .when(mPackageManager) + .queryIntentServices(any(), anyInt()); when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1); when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2); when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1); + // Verify that neither carrier service (no privileges, or carrier-config based privileges) + // are accepted. mCarrierPrivilegesTracker = createCarrierPrivilegesTracker(); String carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName(); int carrierServiceUid = mCarrierPrivilegesTracker.getCarrierServicePackageUid(); diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java index 1428b254ed..ec2209db00 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java @@ -1006,7 +1006,9 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest { PersistableBundle bundle = new PersistableBundle(); String[] mappings = new String[]{ "1014|call completed elsewhere|1014", + "1014|Call Rejected By User|510", "1014|*|510", + "510|Call completed elsewhere|1014", }; bundle.putStringArray(CarrierConfigManager.KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, mappings); @@ -1024,6 +1026,9 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest { new ImsReasonInfo(1014, 200, "Call Rejected By User"))); // 1014 -> 510 assertEquals(ImsReasonInfo.CODE_ANSWERED_ELSEWHERE, mCTUT.maybeRemapReasonCode( new ImsReasonInfo(1014, 200, "Call completed elsewhere"))); // 1014 -> 1014 + assertEquals(ImsReasonInfo.CODE_ANSWERED_ELSEWHERE, mCTUT.maybeRemapReasonCode( + new ImsReasonInfo(510, 200, + "Call completed elsewhere by instance urn:gsma:imei:xxx"))); // 510 -> 1014 // Simulate that after SIM swap the new carrier config doesn't have the mapping for 1014 loadReasonCodeRemapCarrierConfig(); |