Skip to content

Commit 8d80f9b

Browse files
committedMay 1, 2023
Handle new shader directory on U / API 34
Fixes: 274314544 Test: MacrobenchmarkScopeTest (API 33 + 34) Relnote: "Fixes crash when dropping shaders on Android U (API 34), as well as on emulators." Android U moved the shader directory, which now needs to be handled in macrobench/profileinstaller. Also fixes access error to shellWrapper.sh after adb unroot (or disconnect/reconnect. Change-Id: I031ca38e15b9412e84a33eee4eb709cbf3014066
1 parent 9868b86 commit 8d80f9b

File tree

4 files changed

+63
-27
lines changed

4 files changed

+63
-27
lines changed
 

‎benchmark/benchmark-common/src/main/java/androidx/benchmark/Shell.kt

+12-3
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,16 @@ object Shell {
122122
val result = ShellImpl.executeCommandUnsafe("ls -l $path")
123123
if (result.isBlank()) "" else result.split(Regex("\\s+"))[3]
124124
}
125-
check(sum.isNotBlank()) {
126-
"Checksum for $path was blank"
125+
if (sum.isBlank()) {
126+
if (!ShellImpl.isSessionRooted) {
127+
val lsOutput = ShellImpl.executeCommandUnsafe("ls -l $path")
128+
throw IllegalStateException(
129+
"Checksum for $path was blank. Adb session is not rooted, if root owns file, " +
130+
"you may need to \"adb root\" and delete the file: $lsOutput"
131+
)
132+
} else {
133+
throw IllegalStateException("Checksum for $path was blank.")
134+
}
127135
}
128136
return sum
129137
}
@@ -690,7 +698,8 @@ class ShellScript internal constructor(
690698
* Usage args: ```path/to/shellWrapper.sh <scriptFile> <stderrFile> [inputFile]```
691699
*/
692700
private val scriptWrapperPath = Shell.createRunnableExecutable(
693-
"shellWrapper.sh",
701+
// use separate paths to prevent access errors after `adb unroot`
702+
if (ShellImpl.isSessionRooted) "shellWrapper_root.sh" else "shellWrapper.sh",
694703
"""
695704
### shell script which passes in stdin as needed, and captures stderr in a file
696705
# $1 == script content (not executable)

‎benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,16 @@ class MacrobenchmarkScopeTest {
225225

226226
private fun validateShaderCache(empty: Boolean, packageName: String) {
227227
val path = MacrobenchmarkScope.getShaderCachePath(packageName)
228+
228229
println("validating shader path $path")
229230
val fileCount = Shell.executeScriptCaptureStdout("find $path -type f | wc -l")
230231
.trim()
231232
.toInt()
232233
if (empty) {
233-
assertEquals(0, fileCount)
234+
val files = Shell.executeScriptCaptureStdout("find $path -type f")
235+
assertEquals(0, fileCount, "Expected 0 files in $path, saw $fileCount (files = $files)")
234236
} else {
235-
assertNotEquals(0, fileCount)
237+
assertNotEquals(0, fileCount, "Expected >0 files in $path, saw $fileCount")
236238
}
237239
}
238240

@@ -279,6 +281,11 @@ class MacrobenchmarkScopeTest {
279281
dropShaderCache()
280282
}
281283

284+
@Test
285+
fun dropShaderCacheRoot() = validateDropShaderCacheWithRoot {
286+
assertTrue(dropShaderCacheRoot())
287+
}
288+
282289
@Test
283290
fun dropKernelPageCache() {
284291
val scope = MacrobenchmarkScope(

‎benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt

+31-16
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ import android.util.Log
2323
import androidx.annotation.RequiresApi
2424
import androidx.benchmark.DeviceInfo
2525
import androidx.benchmark.Shell
26-
import androidx.benchmark.macro.MacrobenchmarkScope.Companion.Api24Helper.shaderDir
26+
import androidx.benchmark.macro.MacrobenchmarkScope.Companion.Api24ContextHelper.createDeviceProtectedStorageContextCompat
2727
import androidx.benchmark.macro.perfetto.forceTrace
2828
import androidx.test.platform.app.InstrumentationRegistry
2929
import androidx.test.uiautomator.UiDevice
3030
import androidx.tracing.trace
31-
import java.io.File
3231

3332
/**
3433
* Provides access to common operations in app automation, such as killing the app,
@@ -242,17 +241,30 @@ public class MacrobenchmarkScope(
242241
public fun dropShaderCache() {
243242
Log.d(TAG, "Dropping shader cache for $packageName")
244243
val dropError = ProfileInstallBroadcast.dropShaderCache(packageName)
245-
if (dropError != null) {
246-
if (Shell.isSessionRooted()) {
247-
// fall back to root approach
248-
val path = getShaderCachePath(packageName)
249-
Shell.executeScriptSilent("find $path -type f | xargs rm")
250-
} else {
244+
if (dropError != null && !DeviceInfo.isEmulator) {
245+
if (!dropShaderCacheRoot()) {
251246
throw IllegalStateException(dropError)
252247
}
253248
}
254249
}
255250

251+
/**
252+
* Returns true if rooted, and delete operation succeeded without error.
253+
*
254+
* Note that if no files are present in the shader dir, true will still be returned.
255+
*/
256+
internal fun dropShaderCacheRoot(): Boolean {
257+
if (Shell.isSessionRooted()) {
258+
// fall back to root approach
259+
val path = getShaderCachePath(packageName)
260+
261+
// Use -f to allow missing files, since app may not have generated shaders.
262+
Shell.executeScriptSilent("find $path -type f | xargs rm -f")
263+
return true
264+
}
265+
return false
266+
}
267+
256268
/**
257269
* Drop caches via setprop added in API 31
258270
*
@@ -312,21 +324,24 @@ public class MacrobenchmarkScope(
312324
val context = InstrumentationRegistry.getInstrumentation().context
313325

314326
// Shader paths sourced from ActivityThread.java
315-
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
316-
context.shaderDir
327+
val shaderDirectory = if (Build.VERSION.SDK_INT >= 34) {
328+
// U switched to cache dir, so it's not deleted on each app update
329+
context.createDeviceProtectedStorageContextCompat().cacheDir
330+
} else if (Build.VERSION.SDK_INT >= 24) {
331+
// shaders started using device protected storage context once it was added in N
332+
context.createDeviceProtectedStorageContextCompat().codeCacheDir
317333
} else {
318334
// getCodeCacheDir was added in L, but not used by platform for shaders until M
319335
// as M is minApi of this library, that's all we support here
320336
context.codeCacheDir
321-
}.absolutePath.replace(context.packageName, packageName)
337+
}
338+
return shaderDirectory.absolutePath.replace(context.packageName, packageName)
322339
}
323340

324341
@RequiresApi(Build.VERSION_CODES.N)
325-
internal object Api24Helper {
326-
val Context.shaderDir: File
327-
get() =
328-
// shaders started using device protected storage context once it was added in N
329-
createDeviceProtectedStorageContext().codeCacheDir
342+
internal object Api24ContextHelper {
343+
fun Context.createDeviceProtectedStorageContextCompat(): Context =
344+
createDeviceProtectedStorageContext()
330345
}
331346
}
332347
}

‎profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/BenchmarkOperation.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,15 @@ static void dropShaderCache(
3232
@NonNull ProfileInstallReceiver.ResultDiagnostics callback
3333
) {
3434
File shaderDirectory;
35-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
36-
// shaders started using code cache dir once it was added in N
37-
shaderDirectory = Api24ContextHelper.getDeviceProtectedCodeCacheDir(context);
38-
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
35+
if (Build.VERSION.SDK_INT >= 34) {
36+
// U switched to cache dir, so it's not deleted on each app update
37+
shaderDirectory = Api24ContextHelper.createDeviceProtectedStorageContext(context)
38+
.getCacheDir();
39+
} else if (Build.VERSION.SDK_INT >= 24) {
40+
// shaders started using device protected storage context once it was added in N
41+
shaderDirectory = Api21ContextHelper.getCodeCacheDir(
42+
Api24ContextHelper.createDeviceProtectedStorageContext(context));
43+
} else if (Build.VERSION.SDK_INT == 23) {
3944
// getCodeCacheDir was added in L, but not used by platform for shaders until M
4045
shaderDirectory = Api21ContextHelper.getCodeCacheDir(context);
4146
} else {
@@ -82,9 +87,9 @@ static File getCodeCacheDir(Context context) {
8287

8388
@RequiresApi(api = Build.VERSION_CODES.N)
8489
private static class Api24ContextHelper {
85-
static File getDeviceProtectedCodeCacheDir(Context context) {
90+
static Context createDeviceProtectedStorageContext(Context context) {
8691
// Code device protected storage added in 24
87-
return context.createDeviceProtectedStorageContext().getCodeCacheDir();
92+
return context.createDeviceProtectedStorageContext();
8893
}
8994
}
9095
}

0 commit comments

Comments
 (0)