Refactor CarrierConfigRule carrier privilege
Addressing leftover comments in ag/33040619 regarding carrier privilege acquisition in CarrierConfigRule with the following changes: 1) Refactored CarrierPrivilegeCallback to match records using a lambda. 2) Added various helper methods to handle calls with permissions. 3) Moved wait for carrier privlege to overrideConfigAndWait. 4) Fixed acquireCarrierPrivilege to append to current cert strings instead of overwriting them. 5) Fixed dropCarrierPrivilege to remove from current cert strings instead of cleaning up all configs. Flag: EXEMPT test only change Bug: 409710349 Test: atest TetheringManagerTest Change-Id: I1165d95775e809f1aa8905af029fb13df0d3a1a8
This commit is contained in:
parent
96cc8b4f79
commit
b4f1e46e6d
1 changed files with 130 additions and 106 deletions
|
|
@ -62,13 +62,25 @@ class CarrierConfigRule : TestRule {
|
|||
private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
|
||||
private val uiAutomation by lazy { InstrumentationRegistry.getInstrumentation().uiAutomation }
|
||||
private val ccm by lazy { context.getSystemService(CarrierConfigManager::class.java) }
|
||||
private val tm by lazy { context.getSystemService(TelephonyManager::class.java) }
|
||||
private val certHash by lazy {
|
||||
val signatures = context.packageManager.getPackageInfo(
|
||||
context.opPackageName,
|
||||
PackageManager.GET_SIGNATURES
|
||||
).signatures
|
||||
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
val result = signatures?.get(0)?.toByteArray()?.let {
|
||||
bytesToHexString(digest.digest(it))
|
||||
}
|
||||
|
||||
if (result == null) Log.e(TAG, "Can't get cert!")
|
||||
result
|
||||
}
|
||||
|
||||
// Map of (subId) -> (original values of overridden settings)
|
||||
private val originalConfigs = mutableMapOf<Int, PersistableBundle>()
|
||||
|
||||
// Map of (subId) -> (original values of carrier privilege)
|
||||
private val originalCarrierPrivileges = mutableMapOf<Int, Boolean>()
|
||||
|
||||
// Map of (subId) -> (original values of carrier service package)
|
||||
private val originalCarrierServicePackages = mutableMapOf<Int, String?>()
|
||||
|
||||
|
|
@ -106,14 +118,30 @@ class CarrierConfigRule : TestRule {
|
|||
}
|
||||
|
||||
private fun overrideConfigAndWait(subId: Int, config: PersistableBundle) {
|
||||
val changeReceiver = ConfigChangeReceiver(subId)
|
||||
context.registerReceiver(changeReceiver, IntentFilter(ACTION_CARRIER_CONFIG_CHANGED))
|
||||
ccm.overrideConfig(subId, config)
|
||||
assertTrue(
|
||||
changeReceiver.cv.block(CARRIER_CONFIG_CHANGE_TIMEOUT_MS),
|
||||
"Timed out waiting for config change for subId $subId"
|
||||
)
|
||||
context.unregisterReceiver(changeReceiver)
|
||||
runAsShell(MODIFY_PHONE_STATE) {
|
||||
val changeReceiver = ConfigChangeReceiver(subId)
|
||||
context.registerReceiver(changeReceiver, IntentFilter(ACTION_CARRIER_CONFIG_CHANGED))
|
||||
ccm.overrideConfig(subId, config)
|
||||
assertTrue(
|
||||
changeReceiver.cv.block(CARRIER_CONFIG_CHANGE_TIMEOUT_MS),
|
||||
"Timed out waiting for config change for subId $subId"
|
||||
)
|
||||
context.unregisterReceiver(changeReceiver)
|
||||
}
|
||||
|
||||
// Carrier privilege status may not be reset yet even after receiving
|
||||
// ACTION_CARRIER_CONFIG_CHANGED, so make sure to also wait for
|
||||
// CarrierPrivilegesCallback before proceeding.
|
||||
if (SdkLevel.isAtLeastT()) {
|
||||
config.getStringArray(
|
||||
CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY
|
||||
)?.let {
|
||||
eventuallyExpectCarrierPrivilegesChangedOnSubId(
|
||||
subId,
|
||||
it.contains(certHash)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,15 +161,12 @@ class CarrierConfigRule : TestRule {
|
|||
}
|
||||
originalConfig.putAll(previousValues)
|
||||
|
||||
runAsShell(MODIFY_PHONE_STATE) {
|
||||
overrideConfigAndWait(subId, config)
|
||||
}
|
||||
overrideConfigAndWait(subId, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte array into a String of hexadecimal characters.
|
||||
*
|
||||
* @param bytes an array of bytes
|
||||
* @return hex string representation of bytes array
|
||||
*/
|
||||
private fun bytesToHexString(bytes: ByteArray?): String? {
|
||||
|
|
@ -167,50 +192,34 @@ class CarrierConfigRule : TestRule {
|
|||
)
|
||||
}
|
||||
|
||||
fun getCertHash(): String {
|
||||
val pkgInfo = context.packageManager.getPackageInfo(
|
||||
context.opPackageName,
|
||||
PackageManager.GET_SIGNATURES
|
||||
val hasPrivilege = getCarrierPrivilegesOnSubId(subId).uids.contains(Process.myUid())
|
||||
if (hasPrivilege == hold) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Package ${context.opPackageName} is already ${if (hold) "" else "not "}privileged"
|
||||
)
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
val certHash = digest.digest(pkgInfo.signatures!![0]!!.toByteArray())
|
||||
return bytesToHexString(certHash)!!
|
||||
return
|
||||
}
|
||||
|
||||
val tm = context.getSystemService(TelephonyManager::class.java)!!
|
||||
val currentCertStrings = runAsShell(READ_PHONE_STATE) {
|
||||
ccm.getConfigForSubIdCompat(
|
||||
subId,
|
||||
setOf(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY)
|
||||
)
|
||||
}.getStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY) ?: arrayOf()
|
||||
|
||||
val cpb = PrivilegeWaiterCallback()
|
||||
tryTest {
|
||||
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
|
||||
}
|
||||
val currentPrivilege = cpb.expectCarrierPrivilegesChanged()
|
||||
if (currentPrivilege == hold) {
|
||||
if (hold) {
|
||||
Log.w(TAG, "Package ${context.opPackageName} already is privileged")
|
||||
} else {
|
||||
Log.w(TAG, "Package ${context.opPackageName} already isn't privileged")
|
||||
}
|
||||
return@tryTest
|
||||
}
|
||||
if (!originalCarrierPrivileges.contains(subId)) {
|
||||
originalCarrierPrivileges.put(subId, currentPrivilege)
|
||||
}
|
||||
if (hold) {
|
||||
addConfigOverrides(subId, PersistableBundle().also {
|
||||
it.putStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
|
||||
arrayOf(getCertHash()))
|
||||
})
|
||||
} else {
|
||||
cleanUpNow()
|
||||
}
|
||||
cpb.eventuallyExpectCarrierPrivilegesChanged(hold)
|
||||
} cleanup {
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.unregisterCarrierPrivilegesCallback(cpb)
|
||||
}
|
||||
val hashes = if (hold) {
|
||||
currentCertStrings + certHash
|
||||
} else {
|
||||
currentCertStrings.subtract(setOf(certHash)).toTypedArray()
|
||||
}
|
||||
|
||||
addConfigOverrides(subId, PersistableBundle().apply {
|
||||
putStringArray(
|
||||
CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
|
||||
hashes
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -249,15 +258,10 @@ class CarrierConfigRule : TestRule {
|
|||
)
|
||||
}
|
||||
|
||||
val tm = context.getSystemService(TelephonyManager::class.java)!!
|
||||
|
||||
val cv = ConditionVariable()
|
||||
val cpb = CarrierServiceChangedWaiterCallback(cv)
|
||||
tryTest {
|
||||
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
|
||||
}
|
||||
tm.registerCarrierPrivilegesCallbackWithPermission(subId, cpb)
|
||||
// Wait for the callback to be registered
|
||||
assertTrue(cv.block(CARRIER_CONFIG_CHANGE_TIMEOUT_MS),
|
||||
"Can't register CarrierPrivilegesCallback")
|
||||
|
|
@ -283,31 +287,77 @@ class CarrierConfigRule : TestRule {
|
|||
assertTrue(cv.block(CARRIER_CONFIG_CHANGE_TIMEOUT_MS),
|
||||
"Can't modify carrier service package")
|
||||
} cleanup {
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.unregisterCarrierPrivilegesCallback(cpb)
|
||||
}
|
||||
tm.unregisterCarrierPrivilegesCallbackWithPermission(cpb)
|
||||
}
|
||||
}
|
||||
|
||||
private class PrivilegeWaiterCallback() :
|
||||
CarrierPrivilegesCallback {
|
||||
private val history = ArrayTrackRecord<Boolean>().ReadHead()
|
||||
override fun onCarrierPrivilegesChanged(p: MutableSet<String>, uids: MutableSet<Int>) {
|
||||
history.add(uids.contains(Process.myUid()))
|
||||
private fun TelephonyManager.registerCarrierPrivilegesCallbackWithPermission(
|
||||
subId: Int,
|
||||
cpb: CarrierPrivilegesCallback
|
||||
) =
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
registerCarrierPrivilegesCallback(
|
||||
SubscriptionManager.getSlotIndex(subId)!!,
|
||||
{ it.run() },
|
||||
cpb
|
||||
)
|
||||
}
|
||||
|
||||
fun expectCarrierPrivilegesChanged(): Boolean {
|
||||
val result = history.poll(CARRIER_CONFIG_CHANGE_TIMEOUT_MS)
|
||||
private fun TelephonyManager.unregisterCarrierPrivilegesCallbackWithPermission(
|
||||
cpb: CarrierPrivilegesCallback
|
||||
) =
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
unregisterCarrierPrivilegesCallback(cpb)
|
||||
}
|
||||
|
||||
private class PrivilegeWaiterCallback() : CarrierPrivilegesCallback {
|
||||
data class CarrierPrivileges(val packages: Set<String>, val uids: Set<Int>)
|
||||
private val history = ArrayTrackRecord<CarrierPrivileges>().ReadHead()
|
||||
|
||||
override fun onCarrierPrivilegesChanged(p: MutableSet<String>, uids: MutableSet<Int>) {
|
||||
history.add(CarrierPrivileges(p, uids))
|
||||
}
|
||||
|
||||
fun expectCarrierPrivilegesChanged(): CarrierPrivileges {
|
||||
return eventuallyExpectCarrierPrivilegesChanged { true }
|
||||
}
|
||||
|
||||
fun eventuallyExpectCarrierPrivilegesChanged(
|
||||
predicate: (CarrierPrivileges) -> Boolean
|
||||
): CarrierPrivileges {
|
||||
val result = history.poll(
|
||||
CARRIER_CONFIG_CHANGE_TIMEOUT_MS,
|
||||
predicate
|
||||
)
|
||||
assertNotNull(result, "onCarrierPrivilegesChanged not received!")
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun eventuallyExpectCarrierPrivilegesChanged(privileged: Boolean) {
|
||||
val result = history.poll(
|
||||
CARRIER_CONFIG_CHANGE_TIMEOUT_MS,
|
||||
{ it == privileged }
|
||||
)
|
||||
assertNotNull(result, "Carrier privilege did not change to $privileged!")
|
||||
private fun getCarrierPrivilegesOnSubId(
|
||||
subId: Int
|
||||
): PrivilegeWaiterCallback.CarrierPrivileges {
|
||||
val cpb = PrivilegeWaiterCallback()
|
||||
return tryTest {
|
||||
tm.registerCarrierPrivilegesCallbackWithPermission(subId, cpb)
|
||||
cpb.expectCarrierPrivilegesChanged()
|
||||
} cleanup {
|
||||
tm.unregisterCarrierPrivilegesCallbackWithPermission(cpb)
|
||||
}
|
||||
}
|
||||
|
||||
private fun eventuallyExpectCarrierPrivilegesChangedOnSubId(
|
||||
subId: Int,
|
||||
expectedPrivilege: Boolean
|
||||
): PrivilegeWaiterCallback.CarrierPrivileges {
|
||||
val cpb = PrivilegeWaiterCallback()
|
||||
return tryTest {
|
||||
tm.registerCarrierPrivilegesCallbackWithPermission(subId, cpb)
|
||||
cpb.eventuallyExpectCarrierPrivilegesChanged {
|
||||
it.uids.contains(Process.myUid()) == expectedPrivilege
|
||||
}
|
||||
} cleanup {
|
||||
tm.unregisterCarrierPrivilegesCallbackWithPermission(cpb)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,40 +378,14 @@ class CarrierConfigRule : TestRule {
|
|||
* test case unless cleaning up earlier is required.
|
||||
*/
|
||||
fun cleanUpNow() {
|
||||
runAsShell(MODIFY_PHONE_STATE) {
|
||||
originalConfigs.forEach { (subId, config) ->
|
||||
try {
|
||||
// Do not use null as the config to reset, as it would reset configs that may
|
||||
// have been set by target preparers such as
|
||||
// ConnectivityTestTargetPreparer / CarrierConfigSetupTest.
|
||||
overrideConfigAndWait(subId, config)
|
||||
} catch (e: Throwable) {
|
||||
Log.e(TAG, "Error resetting carrier config for subId $subId")
|
||||
}
|
||||
originalConfigs.forEach { (subId, config) ->
|
||||
try {
|
||||
overrideConfigAndWait(subId, config)
|
||||
} catch (e: Throwable) {
|
||||
Log.e(TAG, "Error resetting carrier config for subId $subId: $e", e)
|
||||
}
|
||||
originalConfigs.clear()
|
||||
}
|
||||
|
||||
// Carrier privilege status may not be reset yet even after receiving
|
||||
// ACTION_CARRIER_CONFIG_CHANGED, so make sure to also wait for
|
||||
// CarrierPrivilegesCallback before proceeding.
|
||||
val tm = context.getSystemService(TelephonyManager::class.java)!!
|
||||
originalCarrierPrivileges.forEach { (subId, privileged) ->
|
||||
val cpb = PrivilegeWaiterCallback()
|
||||
tryTest {
|
||||
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
|
||||
}
|
||||
cpb.eventuallyExpectCarrierPrivilegesChanged(privileged)
|
||||
} cleanup {
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.unregisterCarrierPrivilegesCallback(cpb)
|
||||
}
|
||||
}
|
||||
originalCarrierPrivileges.clear()
|
||||
}
|
||||
|
||||
originalConfigs.clear()
|
||||
originalCarrierServicePackages.forEach { (subId, pkg) ->
|
||||
setCarrierServicePackageOverride(subId, pkg)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue