blob: ba9a49c31e9bc54abc7b7e3a5fa8b414e52c9f7c [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.gputools.cts;
import android.platform.test.annotations.Presubmit;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.ddmlib.Log;
import java.util.Scanner;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests that exercise Rootless GPU Debug functionality supported by the loader.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public class CtsRootlessGpuDebugHostTest implements IDeviceTest {
public static final String TAG = CtsRootlessGpuDebugHostTest.class.getSimpleName();
/**
* A reference to the device under test.
*/
private ITestDevice mDevice;
public void setDevice(ITestDevice device) {
mDevice = device;
}
@Override
public ITestDevice getDevice() {
return mDevice;
}
// This test ensures that the Vulkan and GLES loaders can use Settings to load layers
// from the base directory of debuggable applications. Is also tests several
// positive and negative scenarios we want to cover (listed below).
//
// There are three APKs; DEBUG and RELEASE are practically identical with one
// being flagged as debuggable. The LAYERS APK is mainly a conduit for getting
// layers onto the device without affecting the other APKs.
//
// The RELEASE APK does contain one layer to ensure using Settings to enable
// layers does not interfere with legacy methods using system properties.
//
// The layers themselves are practically null, only enough functionality to
// satisfy loader enumerating and loading. They don't actually chain together.
//
// Positive Vulkan tests
// - Ensure we can toggle the Enable Setting on and off (testDebugLayerLoadVulkan)
// - Ensure we can set the debuggable app (testDebugLayerLoadVulkan)
// - Ensure we can set the layer list (testDebugLayerLoadVulkan)
// - Ensure we can push a layer to debuggable app (testDebugLayerLoadVulkan)
// - Ensure we can specify the app to load layers (testDebugLayerLoadVulkan)
// - Ensure we can load a layer from app's data directory (testDebugLayerLoadVulkan)
// - Ensure we can load multiple layers, in order, from app's data directory (testDebugLayerLoadVulkan)
// - Ensure we can still use system properties if no layers loaded via Settings (testSystemPropertyEnableVulkan)
// - Ensure we can find layers in separate specified app (testDebugLayerLoadExternalVulkan)
// Negative Vulkan tests
// - Ensure we cannot push a layer to non-debuggable app (testReleaseLayerLoadVulkan)
// - Ensure non-debuggable app ignores the new Settings (testReleaseLayerLoadVulkan)
// - Ensure we cannot enumerate layers from debuggable app's data directory if Setting not specified (testDebugNoEnumerateVulkan)
// - Ensure we cannot enumerate layers without specifying the debuggable app (testDebugNoEnumerateVulkan)
// - Ensure we cannot use system properties when layer is found via Settings with debuggable app (testSystemPropertyIgnoreVulkan)
//
// Positive GLES tests
// - Ensure we can toggle the Enable Setting on and off (testDebugLayerLoadGLES)
// - Ensure we can set the debuggable app (testDebugLayerLoadGLES)
// - Ensure we can set the layer list (testDebugLayerLoadGLES)
// - Ensure we can push a layer to debuggable app (testDebugLayerLoadGLES)
// - Ensure we can specify the app to load layers (testDebugLayerLoadGLES)
// - Ensure we can load a layer from app's data directory (testDebugLayerLoadGLES)
// - Ensure we can load multiple layers, in order, from app's data directory (testDebugLayerLoadGLES)
// - Ensure we can find layers in separate specified app (testDebugLayerLoadExternalGLES)
// Negative GLES tests
// - Ensure we cannot push a layer to non-debuggable app (testReleaseLayerLoadGLES)
// - Ensure non-debuggable app ignores the new Settings (testReleaseLayerLoadGLES)
// - Ensure we cannot enumerate layers from debuggable app's data directory if Setting not specified (testDebugNoEnumerateGLES)
// - Ensure we cannot enumerate layers without specifying the debuggable app (testDebugNoEnumerateGLES)
private static final String CLASS = "RootlessGpuDebugDeviceActivity";
private static final String ACTIVITY = "android.rootlessgpudebug.app.RootlessGpuDebugDeviceActivity";
private static final String LAYER_A = "nullLayerA";
private static final String LAYER_B = "nullLayerB";
private static final String LAYER_C = "nullLayerC";
private static final String LAYER_A_LIB = "libVkLayer_" + LAYER_A + ".so";
private static final String LAYER_B_LIB = "libVkLayer_" + LAYER_B + ".so";
private static final String LAYER_C_LIB = "libVkLayer_" + LAYER_C + ".so";
private static final String LAYER_A_NAME = "VK_LAYER_ANDROID_" + LAYER_A;
private static final String LAYER_B_NAME = "VK_LAYER_ANDROID_" + LAYER_B;
private static final String LAYER_C_NAME = "VK_LAYER_ANDROID_" + LAYER_C;
private static final String DEBUG_APP = "android.rootlessgpudebug.DEBUG.app";
private static final String RELEASE_APP = "android.rootlessgpudebug.RELEASE.app";
private static final String LAYERS_APP = "android.rootlessgpudebug.LAYERS.app";
private static final String SHIM_A = "glesLayer1";
private static final String SHIM_B = "glesLayer2";
private static final String SHIM_C = "glesLayer3";
private static final String SHIM_A_LIB = "libGLES_" + SHIM_A + ".so";
private static final String SHIM_B_LIB = "libGLES_" + SHIM_B + ".so";
private static final String SHIM_C_LIB = "libGLES_" + SHIM_C + ".so";
// This is how long we'll scan the log for a result before giving up. This limit will only
// be reached if something has gone wrong
private static final long LOG_SEARCH_TIMEOUT_MS = 5000;
private String removeWhitespace(String input) {
return input.replaceAll(System.getProperty("line.separator"), "").trim();
}
/**
* Grab and format the process ID of requested app.
*/
private String getPID(String app) throws Exception {
String pid = mDevice.executeAdbCommand("shell", "pidof", app);
return removeWhitespace(pid);
}
/**
* Extract the requested layer from APK and copy to tmp
*/
private void setupLayer(String layer) throws Exception {
// We use the LAYERS apk to facilitate getting layers onto the device for mixing and matching
String libPath = mDevice.executeAdbCommand("shell", "pm", "path", LAYERS_APP);
libPath = libPath.replaceAll("package:", "");
libPath = libPath.replaceAll("base.apk", "");
libPath = removeWhitespace(libPath);
libPath += "lib/";
// Use find to get the .so so we can ignore ABI
String layerPath = mDevice.executeAdbCommand("shell", "find", libPath + " -name " + layer);
layerPath = removeWhitespace(layerPath);
mDevice.executeAdbCommand("shell", "cp", layerPath + " /data/local/tmp");
}
/**
* Simple helper class for returning multiple results
*/
public class LogScanResult {
public boolean found;
public int lineNumber;
}
private LogScanResult scanLog(String pid, String searchString) throws Exception {
return scanLog(pid, searchString, "");
}
/**
* Scan the logcat for requested process ID, returning if found and which line
*/
private LogScanResult scanLog(String pid, String searchString, String endString) throws Exception {
LogScanResult result = new LogScanResult();
result.found = false;
result.lineNumber = -1;
// Scan until output from app is found
boolean scanComplete= false;
// Let the test run a reasonable amount of time before moving on
long hostStartTime = System.currentTimeMillis();
while (!scanComplete && ((System.currentTimeMillis() - hostStartTime) < LOG_SEARCH_TIMEOUT_MS)) {
// Give our activity a chance to run and fill the log
Thread.sleep(1000);
// Pull the logcat for a single process
String logcat = mDevice.executeAdbCommand("logcat", "-v", "brief", "-d", "--pid=" + pid, "*:V");
int lineNumber = 0;
Scanner apkIn = new Scanner(logcat);
while (apkIn.hasNextLine()) {
lineNumber++;
String line = apkIn.nextLine();
if (line.contains(searchString) && line.endsWith(endString)) {
result.found = true;
result.lineNumber = lineNumber;
}
if (line.contains("RootlessGpuDebug activity complete")) {
// Once we've got output from the app, we've collected what we need
scanComplete= true;
}
}
apkIn.close();
}
return result;
}
/**
* Remove any temporary files on the device, clear any settings, kill the apps after each test
*/
@After
public void cleanup() throws Exception {
mDevice.executeAdbCommand("shell", "am", "force-stop", DEBUG_APP);
mDevice.executeAdbCommand("shell", "am", "force-stop", RELEASE_APP);
mDevice.executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + LAYER_A_LIB);
mDevice.executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + LAYER_B_LIB);
mDevice.executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + LAYER_C_LIB);
mDevice.executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + SHIM_A_LIB);
mDevice.executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + SHIM_B_LIB);
mDevice.executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + SHIM_C_LIB);
mDevice.executeAdbCommand("shell", "settings", "delete", "global", "enable_gpu_debug_layers");
mDevice.executeAdbCommand("shell", "settings", "delete", "global", "gpu_debug_app");
mDevice.executeAdbCommand("shell", "settings", "delete", "global", "gpu_debug_layers");
mDevice.executeAdbCommand("shell", "settings", "delete", "global", "gpu_debug_layer_app");
mDevice.executeAdbCommand("shell", "setprop", "debug.vulkan.layers", "\'\"\"\'");
mDevice.executeAdbCommand("shell", "setprop", "debug.gles.layers", "\'\"\"\'");
}
/**
* This is the primary test of the feature. It pushes layers to our debuggable app and ensures they are
* loaded in the correct order.
*/
@Test
public void testDebugLayerLoadVulkan() throws Exception {
// Set up layers to be loaded
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", LAYER_A_NAME + ":" + LAYER_B_NAME);
// Copy the layers from our LAYERS APK to tmp
setupLayer(LAYER_A_LIB);
setupLayer(LAYER_B_LIB);
// Copy them over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_B_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_B_LIB, ";", "chmod", "700", LAYER_B_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Check that both layers were loaded, in the correct order
String searchStringA = "nullCreateInstance called in " + LAYER_A;
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertTrue("LayerA was not loaded", resultA.found);
String searchStringB = "nullCreateInstance called in " + LAYER_B;
LogScanResult resultB = scanLog(pid, searchStringB);
Assert.assertTrue("LayerB was not loaded", resultB.found);
Assert.assertTrue("LayerA should be loaded before LayerB", resultA.lineNumber < resultB.lineNumber);
}
/**
* This test ensures that we cannot push a layer to a non-debuggable app
* It also ensures non-debuggable apps ignore Settings and don't enumerate layers in the base directory.
*/
@Test
public void testReleaseLayerLoadVulkan() throws Exception {
// Set up a layers to be loaded for RELEASE app
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", RELEASE_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", LAYER_A_NAME + ":" + LAYER_B_NAME);
// Copy a layer from our LAYERS APK to tmp
setupLayer(LAYER_A_LIB);
// Attempt to copy them over to our RELEASE app (this should fail)
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|", "run-as", RELEASE_APP,
"sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'", "||", "echo", "run-as", "failed");
// Kick off our RELEASE app
mDevice.executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(RELEASE_APP);
// Ensure we don't load the layer in base dir
String searchStringA = LAYER_A_NAME + "loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("LayerA was enumerated", resultA.found);
}
/**
* This test ensures debuggable apps do not enumerate layers in base
* directory if enable_gpu_debug_layers is not enabled.
*/
@Test
public void testDebugNotEnabledVulkan() throws Exception {
// Ensure the global layer enable settings is NOT enabled
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "0");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", LAYER_A_NAME);
// Copy a layer from our LAYERS APK to tmp
setupLayer(LAYER_A_LIB);
// Copy it over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure we don't load the layer in base dir
String searchStringA = LAYER_A_NAME + "loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("LayerA was enumerated", resultA.found);
}
/**
* This test ensures debuggable apps do not enumerate layers in base
* directory if gpu_debug_app does not match.
*/
@Test
public void testDebugWrongAppVulkan() throws Exception {
// Ensure the gpu_debug_app does not match what we launch
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", RELEASE_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", LAYER_A_NAME);
// Copy a layer from our LAYERS APK to tmp
setupLayer(LAYER_A_LIB);
// Copy it over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure we don't load the layer in base dir
String searchStringA = LAYER_A_NAME + "loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("LayerA was enumerated", resultA.found);
}
/**
* This test ensures debuggable apps do not enumerate layers in base
* directory if gpu_debug_layers are not set.
*/
@Test
public void testDebugNoLayersEnabledVulkan() throws Exception {
// Ensure the global layer enable settings is NOT enabled
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", "foo");
// Copy a layer from our LAYERS APK to tmp
setupLayer(LAYER_A_LIB);
// Copy it over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure layerA is not loaded
String searchStringA = "nullCreateInstance called in " + LAYER_A;
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("LayerA was loaded", resultA.found);
}
/**
* This test ensures we can still use properties if no layer specified via Settings
*/
@Test
public void testSystemPropertyEnableVulkan() throws Exception {
// Set up layerA to be loaded, but not layerB or layerC
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", RELEASE_APP);
// Switch back to delete once b/117555066 is fixed
//mDevice.executeAdbCommand("shell", "settings", "delete", "global", "gpu_debug_layers");
mDevice.executeShellCommand("settings put global gpu_debug_layers ''");
// Enable layerC (which is packaged with the RELEASE app) with system properties
mDevice.executeAdbCommand("shell", "setprop", "debug.vulkan.layers " + LAYER_C_NAME);
// Kick off our RELEASE app
mDevice.executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(RELEASE_APP);
// Check that both layers were loaded, in the correct order
String searchStringA = LAYER_A_NAME + "loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("LayerA was enumerated", resultA.found);
String searchStringC = "nullCreateInstance called in " + LAYER_C;
LogScanResult resultC = scanLog(pid, searchStringC);
Assert.assertTrue("LayerC was not loaded", resultC.found);
}
/**
* This test ensures system properties are ignored if Settings load a layer
*/
@Test
public void testSystemPropertyIgnoreVulkan() throws Exception {
// Set up layerA to be loaded, but not layerB
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", LAYER_A_NAME);
// Copy the layers from our LAYERS APK
setupLayer(LAYER_A_LIB);
setupLayer(LAYER_B_LIB);
// Copy them over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_B_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", LAYER_B_LIB, ";", "chmod", "700", LAYER_B_LIB + "\'");
// Enable layerB with system properties
mDevice.executeAdbCommand("shell", "setprop", "debug.vulkan.layers " + LAYER_B_NAME);
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure only layerA is loaded
String searchStringA = "nullCreateInstance called in " + LAYER_A;
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertTrue("LayerA was not loaded", resultA.found);
String searchStringB = "nullCreateInstance called in " + LAYER_B;
LogScanResult resultB = scanLog(pid, searchStringB);
Assert.assertFalse("LayerB was loaded", resultB.found);
}
/**
*
*/
@Test
public void testDebugLayerLoadExternalVulkan() throws Exception {
// Set up layers to be loaded
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", LAYER_C_NAME);
// Specify the external app that hosts layers
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layer_app", LAYERS_APP);
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Check that our external layer was loaded
String searchStringC = "nullCreateInstance called in " + LAYER_C;
LogScanResult resultC = scanLog(pid, searchStringC);
Assert.assertTrue("LayerC was not loaded", resultC.found);
}
/**
* This test pushes GLES layers to our debuggable app and ensures they are
* loaded in the correct order.
*/
@Test
public void testDebugLayerLoadGLES() throws Exception {
// Set up layers to be loaded
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", SHIM_A_LIB + ":" + SHIM_B_LIB);
// Copy the layers from our LAYERS APK to tmp
setupLayer(SHIM_A_LIB);
setupLayer(SHIM_B_LIB);
// Copy them over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_A_LIB, ";", "chmod", "700", SHIM_A_LIB + "\'");
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_B_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_B_LIB, ";", "chmod", "700", SHIM_B_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Check that both layers were loaded, in the correct order
String searchStringA = "glesLayer_eglChooseConfig called in " + SHIM_A;
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertTrue("glesLayer1 was not loaded", resultA.found);
String searchStringB = "glesLayer_eglChooseConfig called in " + SHIM_B;
LogScanResult resultB = scanLog(pid, searchStringB);
Assert.assertTrue("glesLayer2 was not loaded", resultB.found);
Assert.assertTrue("glesLayer1 should be loaded before glesLayer2", resultA.lineNumber < resultB.lineNumber);
}
/**
* This test ensures that we cannot push a layer to a non-debuggable GLES app
* It also ensures non-debuggable apps ignore Settings and don't enumerate layers in the base directory.
*/
@Test
public void testReleaseLayerLoadGLES() throws Exception {
// Set up a layers to be loaded for RELEASE app
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", RELEASE_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", SHIM_A_LIB + ":" + SHIM_B_LIB);
// Remove this once b/117555066 has been fixed
mDevice.executeShellCommand("settings put global gpu_debug_layer_app ''");
// Copy a layer from our LAYERS APK to tmp
setupLayer(SHIM_A_LIB);
// Attempt to copy them over to our RELEASE app (this should fail)
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_A_LIB, "|", "run-as", RELEASE_APP,
"sh", "-c", "\'cat", ">", SHIM_A_LIB, ";", "chmod", "700", SHIM_A_LIB + "\'", "||", "echo", "run-as", "failed");
// Kick off our RELEASE app
mDevice.executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(RELEASE_APP);
// Ensure we don't load the layer in base dir
String searchStringA = SHIM_A + " loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse(SHIM_A + " was enumerated", resultA.found);
}
/**
* This test ensures debuggable GLES apps do not enumerate layers in base
* directory if enable_gpu_debug_layers is not enabled.
*/
@Test
public void testDebugNotEnabledGLES() throws Exception {
// Ensure the global layer enable settings is NOT enabled
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "0");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", SHIM_A_LIB);
// Copy a layer from our LAYERS APK to tmp
setupLayer(SHIM_A_LIB);
// Copy it over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_A_LIB, ";", "chmod", "700", SHIM_A_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure we don't load the layer in base dir
String searchStringA = SHIM_A + " loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse(SHIM_A + " was enumerated", resultA.found);
}
/**
* This test ensures debuggable GLES apps do not enumerate layers in base
* directory if gpu_debug_app does not match.
*/
@Test
public void testDebugWrongAppGLES() throws Exception {
// Ensure the gpu_debug_app does not match what we launch
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", RELEASE_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", SHIM_A_LIB);
// Copy a layer from our LAYERS APK to tmp
setupLayer(SHIM_A_LIB);
// Copy it over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_A_LIB, ";", "chmod", "700", SHIM_A_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure we don't load the layer in base dir
String searchStringA = SHIM_A + " loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("ShimA was enumerated", resultA.found);
}
/**
* This test ensures debuggable GLES apps do not enumerate layers in base
* directory if gpu_debug_layers are not set.
*/
@Test
public void testDebugNoLayersEnabledGLES() throws Exception {
// Ensure the global layer enable settings is NOT enabled
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", "foo");
// Copy a layer from our LAYERS APK to tmp
setupLayer(SHIM_A_LIB);
// Copy it over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_A_LIB, ";", "chmod", "700", SHIM_A_LIB + "\'");
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure layerA is not loaded
String searchStringA = "glesLayer_eglChooseConfig called in " + SHIM_A;
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("ShimA was loaded", resultA.found);
}
/**
* This test ensures we can still use properties if no GLES layers are specified
*/
@Test
public void testSystemPropertyEnableGLES() throws Exception {
// Set up layerA to be loaded, but not layerB or layerC
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", RELEASE_APP);
// Switch back to delete once b/117555066 is fixed
//mDevice.executeAdbCommand("shell", "settings", "delete", "global", "gpu_debug_layers");
mDevice.executeShellCommand("settings put global gpu_debug_layers ''");
// Enable layerC (which is packaged with the RELEASE app) with system properties
mDevice.executeAdbCommand("shell", "setprop", "debug.gles.layers " + SHIM_C_LIB);
// Kick off our RELEASE app
mDevice.executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(RELEASE_APP);
// Check that both layers were loaded, in the correct order
String searchStringA = SHIM_A + "loaded";
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertFalse("ShimA was enumerated", resultA.found);
String searchStringC = "glesLayer_eglChooseConfig called in " + SHIM_C;
LogScanResult resultC = scanLog(pid, searchStringC);
Assert.assertTrue("ShimC was not loaded", resultC.found);
}
/**
* This test ensures system properties are ignored if Settings load a GLES layer
*/
@Test
public void testSystemPropertyIgnoreGLES() throws Exception {
// Set up layerA to be loaded, but not layerB
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", SHIM_A_LIB);
// Copy the layers from our LAYERS APK
setupLayer(SHIM_A_LIB);
setupLayer(SHIM_B_LIB);
// Copy them over to our DEBUG app
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_A_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_A_LIB, ";", "chmod", "700", SHIM_A_LIB + "\'");
mDevice.executeAdbCommand("shell", "cat", "/data/local/tmp/" + SHIM_B_LIB, "|", "run-as", DEBUG_APP,
"sh", "-c", "\'cat", ">", SHIM_B_LIB, ";", "chmod", "700", SHIM_B_LIB + "\'");
// Enable layerB with system properties
mDevice.executeAdbCommand("shell", "setprop", "debug.gles.layers " + SHIM_B_LIB);
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Ensure only layerA is loaded
String searchStringA = "glesLayer_eglChooseConfig called in " + SHIM_A;
LogScanResult resultA = scanLog(pid, searchStringA);
Assert.assertTrue("ShimA was not loaded", resultA.found);
String searchStringB = "glesLayer_eglChooseConfig called in " + SHIM_B;
LogScanResult resultB = scanLog(pid, searchStringB);
Assert.assertFalse("ShimB was loaded", resultB.found);
}
/**
*
*/
@Test
public void testDebugLayerLoadExternalGLES() throws Exception {
// Set up layers to be loaded
mDevice.executeAdbCommand("shell", "settings", "put", "global", "enable_gpu_debug_layers", "1");
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_app", DEBUG_APP);
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layers", SHIM_C_LIB);
// Specify the external app that hosts layers
mDevice.executeAdbCommand("shell", "settings", "put", "global", "gpu_debug_layer_app", LAYERS_APP);
// Kick off our DEBUG app
mDevice.executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Give it a chance to start, then grab process ID
Thread.sleep(1000);
String pid = getPID(DEBUG_APP);
// Check that our external layer was loaded
String searchStringC = "glesLayer_eglChooseConfig called in " + SHIM_C;
LogScanResult resultC = scanLog(pid, searchStringC);
Assert.assertTrue("ShimC was not loaded", resultC.found);
}
}