diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java index 955f17781540f..8a3c963f48053 100644 --- a/services/core/java/com/android/server/gpu/GpuService.java +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -39,6 +39,7 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; import android.provider.Settings; +import android.text.TextUtils; import android.util.Base64; import android.util.Slog; @@ -62,15 +63,19 @@ public class GpuService extends SystemService { public static final String TAG = "GpuService"; public static final boolean DEBUG = false; - private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; + private static final String PROD_DRIVER_PROPERTY = "ro.gfx.driver.0"; + private static final String DEV_DRIVER_PROPERTY = "ro.gfx.driver.1"; private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt"; private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; private final Context mContext; - private final String mDriverPackageName; + private final String mProdDriverPackageName; + private final String mDevDriverPackageName; private final PackageManager mPackageManager; private final Object mLock = new Object(); private final Object mDeviceConfigLock = new Object(); + private final boolean mHasProdDriver; + private final boolean mHasDevDriver; private ContentResolver mContentResolver; private long mGameDriverVersionCode; private SettingsObserver mSettingsObserver; @@ -82,10 +87,13 @@ public class GpuService extends SystemService { super(context); mContext = context; - mDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + mProdDriverPackageName = SystemProperties.get(PROD_DRIVER_PROPERTY); mGameDriverVersionCode = -1; + mDevDriverPackageName = SystemProperties.get(DEV_DRIVER_PROPERTY); mPackageManager = context.getPackageManager(); - if (mDriverPackageName != null && !mDriverPackageName.isEmpty()) { + mHasProdDriver = !TextUtils.isEmpty(mProdDriverPackageName); + mHasDevDriver = !TextUtils.isEmpty(mDevDriverPackageName); + if (mHasDevDriver || mHasProdDriver) { final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(ACTION_PACKAGE_ADDED); packageFilter.addAction(ACTION_PACKAGE_CHANGED); @@ -104,7 +112,7 @@ public class GpuService extends SystemService { public void onBootPhase(int phase) { if (phase == PHASE_BOOT_COMPLETED) { mContentResolver = mContext.getContentResolver(); - if (mDriverPackageName == null || mDriverPackageName.isEmpty()) { + if (!mHasProdDriver && !mHasDevDriver) { return; } mSettingsObserver = new SettingsObserver(); @@ -112,6 +120,7 @@ public class GpuService extends SystemService { fetchGameDriverPackageProperties(); processBlacklists(); setBlacklist(); + fetchDeveloperDriverPackageProperties(); } } @@ -166,18 +175,22 @@ public class GpuService extends SystemService { return; } final String packageName = data.getSchemeSpecificPart(); - if (!packageName.equals(mDriverPackageName)) { + final boolean isProdDriver = packageName.equals(mProdDriverPackageName); + final boolean isDevDriver = packageName.equals(mDevDriverPackageName); + if (!isProdDriver && !isDevDriver) { return; } - final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); - switch (intent.getAction()) { case ACTION_PACKAGE_ADDED: case ACTION_PACKAGE_CHANGED: case ACTION_PACKAGE_REMOVED: - fetchGameDriverPackageProperties(); - setBlacklist(); + if (isProdDriver) { + fetchGameDriverPackageProperties(); + setBlacklist(); + } else if (isDevDriver) { + fetchDeveloperDriverPackageProperties(); + } break; default: // do nothing @@ -208,11 +221,11 @@ public class GpuService extends SystemService { private void fetchGameDriverPackageProperties() { final ApplicationInfo driverInfo; try { - driverInfo = mPackageManager.getApplicationInfo(mDriverPackageName, + driverInfo = mPackageManager.getApplicationInfo(mProdDriverPackageName, PackageManager.MATCH_SYSTEM_ONLY); } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { - Slog.e(TAG, "driver package '" + mDriverPackageName + "' not installed"); + Slog.e(TAG, "driver package '" + mProdDriverPackageName + "' not installed"); } return; } @@ -232,14 +245,14 @@ public class GpuService extends SystemService { mGameDriverVersionCode = driverInfo.longVersionCode; try { - final Context driverContext = mContext.createPackageContext(mDriverPackageName, + final Context driverContext = mContext.createPackageContext(mProdDriverPackageName, Context.CONTEXT_RESTRICTED); assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME, Settings.Global.GAME_DRIVER_WHITELIST, ","); } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { - Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed"); + Slog.w(TAG, "driver package '" + mProdDriverPackageName + "' not installed"); } } } @@ -291,4 +304,40 @@ public class GpuService extends SystemService { } } } + + private void fetchDeveloperDriverPackageProperties() { + final ApplicationInfo driverInfo; + try { + driverInfo = mPackageManager.getApplicationInfo(mDevDriverPackageName, + PackageManager.MATCH_SYSTEM_ONLY); + } catch (PackageManager.NameNotFoundException e) { + if (DEBUG) { + Slog.e(TAG, "driver package '" + mDevDriverPackageName + "' not installed"); + } + return; + } + + // O drivers are restricted to the sphal linker namespace, so don't try to use + // packages unless they declare they're compatible with that restriction. + if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) { + if (DEBUG) { + Slog.w(TAG, "Driver package is not known to be compatible with O"); + } + return; + } + + setUpdatableDriverPath(driverInfo); + } + + private void setUpdatableDriverPath(ApplicationInfo ai) { + if (ai.primaryCpuAbi == null) { + nSetUpdatableDriverPath(""); + return; + } + final StringBuilder sb = new StringBuilder(); + sb.append(ai.sourceDir).append("!/lib/"); + nSetUpdatableDriverPath(sb.toString()); + } + + private static native void nSetUpdatableDriverPath(String driverPath); } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 4c3f73d2d1292..925ad0f57f191 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -29,6 +29,7 @@ cc_library_static { "com_android_server_connectivity_Vpn.cpp", "com_android_server_ConsumerIrService.cpp", "com_android_server_devicepolicy_CryptoTestHelper.cpp", + "com_android_server_gpu_GpuService.cpp", "com_android_server_HardwarePropertiesManagerService.cpp", "com_android_server_hdmi_HdmiCecController.cpp", "com_android_server_input_InputManagerService.cpp", @@ -98,6 +99,7 @@ cc_defaults { "libcutils", "libcrypto", "liblog", + "libgraphicsenv", "libhardware", "libhardware_legacy", "libhidlbase", diff --git a/services/core/jni/com_android_server_gpu_GpuService.cpp b/services/core/jni/com_android_server_gpu_GpuService.cpp new file mode 100644 index 0000000000000..2359e808d6f66 --- /dev/null +++ b/services/core/jni/com_android_server_gpu_GpuService.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "GpuService-JNI" + +#include +#include +#include +#include + +namespace { + +static android::sp getGpuService() { + static const android::sp binder = + android::defaultServiceManager()->checkService(android::String16("gpu")); + if (!binder) { + ALOGE("Failed to get gpu service"); + return nullptr; + } + + return interface_cast(binder); +} + +void setUpdatableDriverPath_native(JNIEnv* env, jobject clazz, jstring jDriverPath) { + if (jDriverPath == nullptr) { + return; + } + const android::sp gpuService = getGpuService(); + if (!gpuService) { + return; + } + ScopedUtfChars driverPath(env, jDriverPath); + gpuService->setUpdatableDriverPath(driverPath.c_str()); +} + +static const JNINativeMethod gGpuServiceMethods[] = { + /* name, signature, funcPtr */ + {"nSetUpdatableDriverPath", "(Ljava/lang/String;)V", + reinterpret_cast(setUpdatableDriverPath_native)}, +}; + +const char* const kGpuServiceName = "com/android/server/gpu/GpuService"; + +} // anonymous namespace + +namespace android { + +int register_android_server_GpuService(JNIEnv* env) { + return jniRegisterNativeMethods(env, kGpuServiceName, gGpuServiceMethods, + NELEM(gGpuServiceMethods)); +} + +} /* namespace android */ diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index b988bd45d7864..e5d2a83479e0c 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -63,6 +63,7 @@ int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTrac int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env); int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env); int register_android_server_AdbDebuggingManager(JNIEnv* env); +int register_android_server_GpuService(JNIEnv* env); }; using namespace android; @@ -119,5 +120,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env); register_android_server_stats_pull_StatsPullAtomService(env); register_android_server_AdbDebuggingManager(env); + register_android_server_GpuService(env); return JNI_VERSION_1_4; }