Merge "RootlessGpuDebug: Change Activity to Service" into sc-v2-dev
diff --git a/hostsidetests/gputools/apps/AndroidManifest.xml b/hostsidetests/gputools/apps/AndroidManifest.xml
index 89ecaf8..3c8de1f 100755
--- a/hostsidetests/gputools/apps/AndroidManifest.xml
+++ b/hostsidetests/gputools/apps/AndroidManifest.xml
@@ -19,13 +19,13 @@
package="android.rootlessgpudebug.app">
<application android:extractNativeLibs="true">
- <activity android:name=".RootlessGpuDebugDeviceActivity"
+ <service android:name=".RootlessGpuDebugService"
+ android:process=":target_api_service"
android:exported="true">
<intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
+ <action android:name="android.service.action.TARGET_API_SERVICE"/>
</intent-filter>
- </activity>
+ </service>
</application>
</manifest>
diff --git a/hostsidetests/gputools/apps/inject/AndroidManifest.xml b/hostsidetests/gputools/apps/inject/AndroidManifest.xml
index 63bd9c1..743c2be 100644
--- a/hostsidetests/gputools/apps/inject/AndroidManifest.xml
+++ b/hostsidetests/gputools/apps/inject/AndroidManifest.xml
@@ -21,13 +21,12 @@
<application android:extractNativeLibs="true">
<meta-data android:name="com.android.graphics.injectLayers.enable"
android:value="true"/>
- <activity android:name=".RootlessGpuDebugDeviceActivity"
- android:exported="true">
+ <service android:name=".RootlessGpuDebugService"
+ android:process=":target_api_service"
+ android:exported="true">
<intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
+ <action android:name="android.service.action.TARGET_API_SERVICE"/>
</intent-filter>
- </activity>
+ </service>
</application>
-
</manifest>
diff --git a/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp b/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp
index f62a583..44317c5 100644
--- a/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp
+++ b/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp
@@ -17,9 +17,6 @@
#define LOG_TAG "RootlessGpuDebug"
-#include <string>
-#include <vector>
-
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <android/log.h>
@@ -27,6 +24,10 @@
#include <jni.h>
#include <vulkan/vulkan.h>
+#include <sstream>
+#include <string>
+#include <vector>
+
#define ALOGI(msg, ...) \
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
#define ALOGE(msg, ...) \
@@ -39,7 +40,7 @@
typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
std::string initVulkan() {
- std::string result = "";
+ std::stringstream result;
{
uint32_t count = 0;
@@ -78,13 +79,13 @@
};
VkInstance instance;
VkResult vkResult = vkCreateInstance(&instance_info, nullptr, &instance);
- if (vkResult == VK_ERROR_INITIALIZATION_FAILED) {
- result = "vkCreateInstance failed, meaning layers could not be chained.";
+ if (vkResult == VK_SUCCESS) {
+ result << "vkCreateInstance succeeded.";
} else {
- result = "vkCreateInstance succeeded.";
+ result << "vkCreateInstance failed with VkResult: " << vkResult;
}
- return result;
+ return result.str();
}
std::string initGLES() {
@@ -163,8 +164,7 @@
} // anonymous namespace
int register_android_gputools_cts_RootlessGpuDebug(JNIEnv* env) {
- jclass clazz = env->FindClass(
- "android/rootlessgpudebug/app/RootlessGpuDebugDeviceActivity");
+ jclass clazz = env->FindClass("android/rootlessgpudebug/app/RootlessGpuDebugService");
return env->RegisterNatives(clazz, gMethods,
sizeof(gMethods) / sizeof(JNINativeMethod));
}
diff --git a/hostsidetests/gputools/apps/src/android/rootlessgpudebug/app/RootlessGpuDebugDeviceActivity.java b/hostsidetests/gputools/apps/src/android/rootlessgpudebug/app/RootlessGpuDebugDeviceActivity.java
deleted file mode 100644
index a29a246..0000000
--- a/hostsidetests/gputools/apps/src/android/rootlessgpudebug/app/RootlessGpuDebugDeviceActivity.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.rootlessgpudebug.app;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-import java.lang.Override;
-
-public class RootlessGpuDebugDeviceActivity extends Activity {
-
- static {
- System.loadLibrary("ctsgputools_jni");
- }
-
- private static final String TAG = RootlessGpuDebugDeviceActivity.class.getSimpleName();
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- String result = nativeInitVulkan();
- Log.i(TAG, result);
-
- result = nativeInitGLES();
- Log.i(TAG, result);
-
- Log.i(TAG, "RootlessGpuDebug activity complete");
- }
-
- private static native String nativeInitVulkan();
- private static native String nativeInitGLES();
-
-}
-
diff --git a/hostsidetests/gputools/apps/src/android/rootlessgpudebug/app/RootlessGpuDebugService.java b/hostsidetests/gputools/apps/src/android/rootlessgpudebug/app/RootlessGpuDebugService.java
new file mode 100644
index 0000000..47b1ad6
--- /dev/null
+++ b/hostsidetests/gputools/apps/src/android/rootlessgpudebug/app/RootlessGpuDebugService.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 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.rootlessgpudebug.app;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.lang.Override;
+
+
+public class RootlessGpuDebugService extends Service {
+
+ private static final String TAG = RootlessGpuDebugService.class.getSimpleName();
+
+ static {
+ System.loadLibrary("ctsgputools_jni");
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // We don't provide binding, so return null
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+
+ // The target API is provided via Intent extras
+ String API = null;
+
+ if (intent == null) {
+ throw new AssertionError("No Intent provided to " + TAG);
+ }
+
+ Bundle bundle = intent.getExtras();
+
+ // Ensure the service was started with extras
+ if (bundle == null) {
+ throw new AssertionError("Failed to get Intent extras for " + TAG);
+ }
+
+ API = bundle.getString("API");
+
+ // Without an API to target, we're done
+ if (API == null) {
+ throw new AssertionError("No API provided for " + TAG);
+ }
+
+ // Only three combinations are expected
+ Boolean supportedApi = API.equals("Vulkan") ||
+ API.equals("GLES") ||
+ API.equals("Both");
+ if (!supportedApi) {
+ throw new AssertionError("Unsupported API " + API + " in " + TAG);
+ }
+
+ // For each choice, init the target API
+ if (API.equals("Vulkan") || API.equals("Both")) {
+ String result = nativeInitVulkan();
+ Log.i(TAG, result);
+ }
+
+ if (API.equals("GLES") || API.equals("Both")) {
+ String result = nativeInitGLES();
+ Log.i(TAG, result);
+ }
+
+ // Mark service completion
+ Log.i(TAG, "RootlessGpuDebugService complete");
+
+ // Don't try to restart when this is shut down
+ return START_NOT_STICKY;
+ }
+
+ private static native String nativeInitVulkan();
+ private static native String nativeInitGLES();
+}
+
diff --git a/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java b/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java
index 4ec4ef8..3f4c4c9 100644
--- a/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java
+++ b/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java
@@ -33,7 +33,7 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public class CtsRootlessGpuDebugHostTest extends BaseHostJUnit4Test {
- public static final String TAG = "RootlessGpuDebugDeviceActivity";
+ public static final String TAG = "RootlessGpuDebugService";
// 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
@@ -90,8 +90,9 @@
// Positive combined tests
// - Ensure we can load Vulkan and GLES layers at the same time, from multiple external apps (testMultipleExternalApps)
- private static final String CLASS = "RootlessGpuDebugDeviceActivity";
- private static final String ACTIVITY = "android.rootlessgpudebug.app.RootlessGpuDebugDeviceActivity";
+ private static final String API_VULKAN = "Vulkan";
+ private static final String API_GLES = "GLES";
+ private static final String API_BOTH = "Both";
private static final String VK_LAYER_LIB_PREFIX = "libVkLayer_nullLayer";
private static final String VK_LAYER_A_LIB = VK_LAYER_LIB_PREFIX + "A.so";
private static final String VK_LAYER_B_LIB = VK_LAYER_LIB_PREFIX + "B.so";
@@ -257,7 +258,7 @@
result.found = true;
result.lineNumber = lineNumber;
}
- if (line.contains("RootlessGpuDebug activity complete")) {
+ if (line.contains("RootlessGpuDebugService complete")) {
// Once we've got output from the app, we've collected what we need
scanComplete= true;
}
@@ -311,6 +312,20 @@
}
/**
+ * Launch our test as a background service, avoiding any platform rendering code
+ */
+ private void launchBackgroundService(String appName, String Api) throws Exception {
+
+ // Allow the app to be launched as a background service
+ getDevice().executeAdbCommand("shell", "cmd", "deviceidle", "tempwhitelist", appName);
+
+ // Start the service and tell it to init Vulkan/GLES/Both
+ getDevice().executeAdbCommand("shell", "am", "startservice", "-a", "android.service.action.TARGET_API_SERVICE",
+ "--es", "API", Api, appName);
+ }
+
+
+ /**
* This is the primary test of the feature. It pushes layers to our debuggable app and ensures they are
* loaded in the correct order.
*/
@@ -326,7 +341,6 @@
setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
setupLayer(VK_LAYER_B_LIB, LAYERS_APP);
-
// Copy them over to our DEBUG app
getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
@@ -335,10 +349,9 @@
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
"sh", "-c", "\'cat", ">", VK_LAYER_B_LIB, ";", "chmod", "700", VK_LAYER_B_LIB + "\'");
-
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_VULKAN);
// Check that both layers were loaded, in the correct order
String searchStringA = "nullCreateInstance called in " + VK_LAYER_A;
@@ -353,6 +366,7 @@
}
public void testLayerNotLoadedVulkan(final String APP_NAME) throws Exception {
+
// Set up a layers to be loaded for RELEASE or INJECT app
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", APP_NAME);
@@ -366,9 +380,9 @@
"run-as", APP_NAME, "--user", Integer.toString(getDevice().getCurrentUser()),
"sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'", "||", "echo", "run-as", "failed");
- // Kick off our RELEASE app
+ // Kick off our app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", APP_NAME + "/" + ACTIVITY);
+ launchBackgroundService(APP_NAME, API_VULKAN);
// Ensure we don't load the layer in base dir
assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
@@ -414,7 +428,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_VULKAN);
// Ensure we don't load the layer in base dir
assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
@@ -442,7 +456,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_VULKAN);
// Ensure we don't load the layer in base dir
assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
@@ -470,7 +484,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_VULKAN);
// Ensure layerA is not loaded
assertVkLayerLoading(appStartTime, VK_LAYER_A, false);
@@ -492,7 +506,7 @@
// Kick off our RELEASE app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
+ launchBackgroundService(RELEASE_APP, API_VULKAN);
// Check that only layerC was loaded
assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
@@ -527,7 +541,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_VULKAN);
// Ensure only layerA is loaded
assertVkLayerLoading(appStartTime, VK_LAYER_A, true);
@@ -548,9 +562,9 @@
// Specify the external app that hosts layers
applySetting("gpu_debug_layer_app", LAYERS_APP);
- // Kick off our DEBUG app
+ // Kick off our app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", APP_NAME + "/" + ACTIVITY);
+ launchBackgroundService(APP_NAME, API_VULKAN);
String[] layerNames = layers.split(":");
for (String layerName : layerNames) {
@@ -621,7 +635,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_GLES);
// Check that both layers were loaded, in the correct order
String searchStringA = "glesLayer_eglChooseConfig called in " + GLES_LAYER_A;
@@ -657,7 +671,7 @@
// Kick off our RELEASE app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
+ launchBackgroundService(RELEASE_APP, API_GLES);
// Ensure we don't load the layer in base dir
String searchStringA = GLES_LAYER_A + " loaded";
@@ -686,7 +700,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_GLES);
// Ensure we don't load the layer in base dir
String searchStringA = GLES_LAYER_A + " loaded";
@@ -715,7 +729,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_GLES);
// Ensure we don't load the layer in base dir
String searchStringA = GLES_LAYER_A + " loaded";
@@ -744,7 +758,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_GLES);
// Ensure layerA is not loaded
String searchStringA = "glesLayer_eglChooseConfig called in " + GLES_LAYER_A;
@@ -768,7 +782,7 @@
// Kick off our RELEASE app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
+ launchBackgroundService(RELEASE_APP, API_GLES);
// Check that both layers were loaded, in the correct order
String searchStringA = GLES_LAYER_A + "loaded";
@@ -808,7 +822,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_GLES);
// Ensure only layerA is loaded
String searchStringA = "glesLayer_eglChooseConfig called in " + GLES_LAYER_A;
@@ -829,9 +843,9 @@
// Specify the external app that hosts layers
applySetting("gpu_debug_layer_app", GLES_LAYERS_APP);
- // Kick off our DEBUG app
+ // Kick off our app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", APP_NAME + "/" + ACTIVITY);
+ launchBackgroundService(APP_NAME, API_GLES);
// Check that our external layer was loaded
String searchStringC = "glesLayer_eglChooseConfig called in " + GLES_LAYER_C;
@@ -872,7 +886,7 @@
// Kick off our DEBUG app
String appStartTime = getTime();
- getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
+ launchBackgroundService(DEBUG_APP, API_BOTH);
// Check that external layers were loaded from both apps
assertVkLayerLoading(appStartTime, VK_LAYER_C, true);