use SharedPreferences to save verify results

If an app declares too much hosts for App Link, Statementservice will crash since
it uses Data class of WorkManager to save verify result for all hosts while Data throws
IllegalStateException if it occupies more than 10240 bytes when serialized.
This fix uses SharedPreferences to save verify results instead of Data class of WorkManager.

Test:Disable GMS core and reboot device, then install Google Map; Statementservice does not crash
and framework receives host verify results from Statementservice

Signed-off-by: Bin Wang <bin.wang@oppo.corp-partner.google.com>
Change-Id: I6d1b19fd8ed3158a621a2fb0089d92430482fd61
This commit is contained in:
Bin Wang 2022-05-30 16:09:42 +08:00
parent 6db478c840
commit 4978d1ad10
3 changed files with 42 additions and 15 deletions

View File

@ -67,6 +67,10 @@ class DomainVerificationReceiverV1 : BaseDomainVerificationReceiver() {
}
}
//clear sp before enqueue unique work since policy is REPLACE
val deContext = context.createDeviceProtectedStorageContext()
val editor = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)?.edit()
editor?.clear()?.apply()
WorkManager.getInstance(context)
.beginUniqueWork(
"$PACKAGE_WORK_PREFIX_V1$packageName",

View File

@ -41,9 +41,7 @@ class CollectV1Worker(appContext: Context, params: WorkerParameters) :
Data.Builder()
.putInt(VERIFICATION_ID_KEY, verificationId)
.apply {
if (DEBUG) {
putString(PACKAGE_NAME_KEY, packageName)
}
putString(PACKAGE_NAME_KEY, packageName)
}
.build()
)
@ -52,6 +50,18 @@ class CollectV1Worker(appContext: Context, params: WorkerParameters) :
override suspend fun doWork() = coroutineScope {
if (!AndroidUtils.isReceiverV1Enabled(appContext)) {
//clear sp and commit here
val inputData = params.inputData
val packageName = inputData.getString(PACKAGE_NAME_KEY)
val deContext = appContext.createDeviceProtectedStorageContext()
val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
val editor = sp?.edit()
editor?.clear()?.commit()
//delete sp file
val retOfDel = deContext?.deleteSharedPreferences(packageName)
if (DEBUG) {
Log.d(TAG, "delete sp for $packageName return $retOfDel")
}
return@coroutineScope Result.success()
}
@ -59,7 +69,10 @@ class CollectV1Worker(appContext: Context, params: WorkerParameters) :
val verificationId = inputData.getInt(VERIFICATION_ID_KEY, -1)
val successfulHosts = mutableListOf<String>()
val failedHosts = mutableListOf<String>()
inputData.keyValueMap.entries.forEach { (key, _) ->
val packageName = inputData.getString(PACKAGE_NAME_KEY)
val deContext = appContext.createDeviceProtectedStorageContext()
val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
sp?.all?.entries?.forEach { (key, _) ->
when {
key.startsWith(SingleV1RequestWorker.HOST_SUCCESS_PREFIX) ->
successfulHosts += key.removePrefix(SingleV1RequestWorker.HOST_SUCCESS_PREFIX)
@ -69,7 +82,6 @@ class CollectV1Worker(appContext: Context, params: WorkerParameters) :
}
if (DEBUG) {
val packageName = inputData.getString(PACKAGE_NAME_KEY)
Log.d(
TAG, "Domain verification v1 request for $packageName: " +
"success = $successfulHosts, failed = $failedHosts"
@ -84,6 +96,15 @@ class CollectV1Worker(appContext: Context, params: WorkerParameters) :
appContext.packageManager.verifyIntentFilter(verificationId, resultCode, failedHosts)
//clear sp and commit here
val editor = sp?.edit()
editor?.clear()?.commit()
//delete sp file
val retOfDel = deContext?.deleteSharedPreferences(packageName)
if (DEBUG) {
Log.d(TAG, "delete sp for $packageName return $retOfDel")
}
Result.success()
}
}

View File

@ -71,16 +71,18 @@ class SingleV1RequestWorker(appContext: Context, params: WorkerParameters) :
// Coerce failure results into success so that final collection task gets a chance to run
when (result) {
is Result.Success -> Result.success(
Data.Builder()
.putInt("$HOST_SUCCESS_PREFIX$host", status.value)
.build()
)
is Result.Failure -> Result.success(
Data.Builder()
.putInt("$HOST_FAILURE_PREFIX$host", status.value)
.build()
)
is Result.Success -> {
val deContext = appContext.createDeviceProtectedStorageContext()
val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
sp?.edit()?.putInt("$HOST_SUCCESS_PREFIX$host", status.value)?.apply()
Result.success()
}
is Result.Failure -> {
val deContext = appContext.createDeviceProtectedStorageContext()
val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
sp?.edit()?.putInt("$HOST_FAILURE_PREFIX$host", status.value)?.apply()
Result.success()
}
else -> result
}
}