Android 10에서는 모든 기기 식별자가 READ_PRIVILEGED_PHONE_STATE
권한으로 보호되도록 기기 식별자 권한이 변경됩니다. Android 10 이전에는 영구 기기 식별자(IMEI/MEID, IMSI, SIM 및 빌드 일련번호)가 READ_PHONE_STATE
런타임 권한 뒤에서 보호되었습니다.
READ_PRIVILEGED_PHONE_STATE
권한은 플랫폼 키로 서명된 앱과 권한이 있는 시스템 앱에만 부여됩니다.
새 권한 요구사항을 자세히 알아보려면 Javadoc 페이지의 TelephonyManager.java 및 Build.java 관련 정보를 참조하세요.
이 변경사항은 다음과 같은 API에 영향을 미칩니다.
- TelephonyManager#getDeviceId
- TelephonyManager#getImei
- TelephonyManager#getMeid
- TelephonyManager#getSimSerialNumber
- TelephonyManager#getSubscriberId
- Build#getSerial
READ_PRIVILEGED_PHONE_STATE 권한이 없는 이동통신사 앱의 액세스
READ_PRIVILEGED_PHONE_STATE
권한을 이용할 자격이 없는 미리 로드된 이동통신사 앱은 아래 표에 있는 옵션 중 하나를 구현하면 됩니다.
옵션 | 설명 | 제한사항 |
---|---|---|
UICC 이동통신사 권한 | Android 플랫폼은 UICC에 저장된 인증서를 로드하고 이러한 인증서로 서명된 앱에 권한을 부여하여 특수 메서드를 호출합니다. | 기존 이동통신사의 경우 SIM 이용 고객이 많아서 업데이트하기 쉽지 않습니다. 또한, 새로운 SIM에 작성할 권한이 없는 이동통신사(예: MNO에서 발행한 SIM이 있는 MVNO)는 SIM에 인증서를 추가하거나 업데이트할 수 없습니다. |
OEM 허용 목록 | OEM은 OP_READ_DEVICE_IDENTIFIER 를 사용하여 허용 목록에 있는 이동통신사 앱에 기기 식별자를 제공할 수 있습니다. |
이 해결 방법은 일부 이동통신사에만 적용됩니다. |
유형 할당 코드(TAC) | Android 10에 도입된 getTypeAllocationCode 메서드를 사용하여 제조업체 및 모델 정보를 반환하는 TAC를 노출합니다. |
TAC에 포함된 정보는 특정 기기를 식별하기에 부적절합니다. |
MSISDN | 이동통신사는 TelephonyManager 에서 PHONE 권한 그룹을 통해 가져올 수 있는 전화번호(MSISDN)를 사용하여 백엔드 시스템의 IMEI를 조회할 수 있습니다. |
이 작업은 이동통신사에 큰 부담이 됩니다. IMSI를 사용하여 네트워크 키를 매핑하는 이동통신사가 MSISDN으로 전환하려면 상당한 기술 리소스가 필요합니다. |
모든 이동통신사 앱은 CarrierConfig.xml
파일을 이동통신사 앱의 서명 인증서 해시로 업데이트하여 기기 식별자에 액세스할 수 있습니다. 이동통신사 앱에서 권한 정보를 읽는 메서드를 호출하면 플랫폼에서 CarrierConfig.xml
파일에 포함된 앱의 서명 인증서 해시(인증서의 SHA-1 또는 SHA-256 서명)와 일치하는 항목이 있는지 찾습니다. 일치하는 항목을 찾으면 요청한 정보가 반환됩니다. 일치하는 정보가 없다면 보안 예외가 반환됩니다.
이 해결 방법을 구현하려면 이동통신사는 반드시 다음 단계를 따라야 합니다.
CarrierConfig.xml
을 이동통신사 앱의 서명 인증서 해시로 업데이트하고 패치를 제출합니다.- QPR1+(권장) 또는 다음 필수 플랫폼 패치와 위의 1단계에서 업데이트된
CarrierConfig.xml
파일이 포함된 패치를 사용하여 빌드를 업데이트하도록 OEM에 요청합니다.
구현
독점 권한 허용 목록을 업데이트하여 기기 식별자에 액세스해야 하는 권한 있는 앱에 READ_PRIVILEGED_PHONE_STATE
권한을 부여하세요.
허용 목록에 관해 자세히 알아보려면 독점 권한 허용 목록을 참고하세요.
영향을 받은 API를 호출하려면 앱이 다음과 같은 요구사항 중 하나를 충족해야 합니다.
- 앱이 미리 로드된 권한 있는 애플리케이션인 경우 AndroidManifest.xml에
READ_PRIVILEGED_PHONE_STATE
권한을 선언해야 합니다. 또한 앱은 이 독점 권한을 허용 목록에 추가해야 합니다. - Google Play를 통해 제공되는 앱은 이동통신사 권한이 필요합니다. 이동통신사 권한 부여에 관한 자세한 내용은 UICC 이동통신사 권한 페이지를 참조하세요.
READ_PHONE_STATE
권한을 부여받은 기기 또는 프로필 소유자 앱이 필요합니다.
이러한 요구사항을 하나도 충족하지 않는 앱은 다음과 같이 작동합니다.
- 앱이 Q 이전 버전을 타겟팅하고
READ_PHONE_STATE
권한을 부여받지 않았다면SecurityException
이 트리거됩니다. 이는 현재의 Q 이전 버전의 동작이며, 이러한 API를 호출하려면 이 권한이 필요하기 때문입니다. - Q보다 낮은 버전을 타겟팅하고
READ_PHONE_STATE
권한을 부여받은 앱은 모든 TelephonyManager API에 관해 null 값을,Build#getSerial
메서드에 관해Build.UNKNOWN
을 수신합니다. - Android 10 이상을 타겟팅하고 새로운 요구사항을 하나도 충족하지 않는 앱은 SecurityException을 수신합니다.
유효성 검사 및 테스트
호환성 테스트 모음(CTS)에는 이동통신사 권한을 보유한 앱, 기기 및 프로필 소유자, 기기 식별자에 액세스할 수 없을 것으로 예상되는 앱의 예상 기기 식별자 액세스 동작을 검증하기 위한 테스트가 포함되어 있습니다.
다음 CTS 테스트는 이러한 기능과 관련이 있습니다.
cts-tradefed run cts -m CtsCarrierApiTestCases -t android.carrierapi.cts.CarrierApiTest
cts-tradefed run cts -m CtsTelephonyTestCases -t android.telephony.cts.TelephonyManagerTest
cts-tradefed run cts -m CtsTelephony3TestCases
cts-tradefed run cts -m CtsPermissionTestCases -t android.permission.cts.TelephonyManagerPermissionTest
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCanGetDeviceIdentifiers
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCanGetDeviceIdentifiers
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCannotGetDeviceIdentifiersWithoutPermission
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCannotGetDeviceIdentifiersWithoutPermission
FAQ
특정 (MCC, MNC)에 해당하도록 CarrierConfig.xml
의 허용 목록에 추가할 수 있는 앱은 몇 개인가요?
배열에 포함된 인증서 해시 수에는 제한이 없습니다.
앱을 허용 목록에 추가하려면 CarrierConfig.xml
에서 어떤 CarrierConfig 매개변수를 사용해야 하나요?
구성 중인 AOSP 옵션의 특정 CarrierConfig.xml
내에 다음 최상위 구성 항목을 사용합니다.
<string-array name="carrier_certificate_string_array" num="2"> <item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/> <item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/> </string-array>
사용할 수 있는 기본 CarrierConfig 템플릿이 있나요?
다음 템플릿을 사용하세요. 이 템플릿을 관련 애셋에 추가해야 합니다.
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <carrier_config> <string-array name="carrier_certificate_string_array" num="1"> <item value="CERTIFICATE_HASH_HERE"/> </string-array> </carrier_config>
기기 식별자에 액세스하려면 이동통신사 SIM이 기기에 있어야 하나요?
사용되는 CarrierConfig.xml
은 현재 삽입된 SIM을 기반으로 결정됩니다. 즉, 이동통신사 Y의 SIM이 삽입된 상태에서 이동통신사 X의 앱이 액세스 권한을 가져오려고 하면 기기에서 해시와 일치하는 항목을 찾지 못하고 보안 예외를 반환합니다.
멀티 SIM 기기에서 이동통신사 #1은 SIM #1의 액세스 권한만 보유하며 그 반대의 경우도 마찬가지입니다.
이동통신사에서 어떻게 앱의 서명 인증서를 해시로 변환하나요?
CarrierConfig.xml
에 추가하기 전에 서명 인증서를 해시로 변환하려면 다음과 같이 하세요.
toByteArray
를 사용하여 서명 인증서의 서명을 바이트 배열로 변환합니다.MessageDigest
를 사용하여 바이트 배열을 byte[] 유형의 해시로 변환합니다.-
byte[]의 해시를 16진수 문자열 형식으로 변환합니다.
IccUtils.java
예를 참고하세요.List<String> certHashes = new ArrayList<>(); PackageInfo pInfo; // Carrier app PackageInfo MessageDigest md = MessageDigest.getInstance("SHA-256"); for (Signature signature : pInfo.signatures) { certHashes.add(bytesToHexString(md.digest(signature.toByteArray())); }
certHashes
가12345
와54321
이라는 값이 있는 크기2
의 배열이라면 다음을 이동통신사 구성 파일에 추가합니다.<string-array name="carrier_certificate_string_array" num="2"> <item value="12345"/> <item value="54321"/> </string-array>