From c95354bc9c3490617d67c2248ae542797184a133 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 23 Jan 2019 15:29:59 -0800 Subject: [PATCH 1/7] [GPU Service] Implement GPU service. GPU Service is used to monitor all GPU and graphics driver related features. This patch implements GPU service into System Server, and implements functionality to extract the whitelist out of game driver package when the package is upgraded or removed. This will move the whitelist processing off critical path when app launches. BUG: 123290424 Test: Build, flash and boot. Verify by upgrading game driver apk. Change-Id: I563a138bfe0c4c1bb17ed28dab5d6a8df244021d Merged-In: I563a138bfe0c4c1bb17ed28dab5d6a8df244021d --- core/java/android/os/GraphicsEnvironment.java | 34 +--- .../com/android/server/gpu/GpuService.java | 163 ++++++++++++++++++ .../java/com/android/server/SystemServer.java | 6 + 3 files changed, 172 insertions(+), 31 deletions(-) create mode 100644 services/core/java/com/android/server/gpu/GpuService.java diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index d46cf3cb974ae..57bc026778bba 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -33,11 +33,8 @@ import com.android.framework.protobuf.InvalidProtocolBufferException; import dalvik.system.VMRuntime; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -57,7 +54,6 @@ public class GraphicsEnvironment { private static final boolean DEBUG = false; private static final String TAG = "GraphicsEnvironment"; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; - private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt"; private static final String GAME_DRIVER_BLACKLIST_FLAG = "blacklist"; private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; @@ -219,8 +215,9 @@ public class GraphicsEnvironment { boolean isOptIn = getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) .contains(ai.packageName); - - if (!isOptIn && !onWhitelist(context, driverPackageName, ai.packageName)) { + if (!isOptIn + && !getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_WHITELIST) + .contains(ai.packageName)) { if (DEBUG) { Log.w(TAG, ai.packageName + " is not on the whitelist."); } @@ -313,31 +310,6 @@ public class GraphicsEnvironment { return null; } - private static boolean onWhitelist(Context context, String driverPackageName, - String applicationPackageName) { - try { - Context driverContext = context.createPackageContext(driverPackageName, - Context.CONTEXT_RESTRICTED); - AssetManager assets = driverContext.getAssets(); - InputStream stream = assets.open(GAME_DRIVER_WHITELIST_FILENAME); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - for (String packageName; (packageName = reader.readLine()) != null; ) { - if (packageName.equals(applicationPackageName)) { - return true; - } - } - } catch (PackageManager.NameNotFoundException e) { - if (DEBUG) { - Log.w(TAG, "driver package '" + driverPackageName + "' not installed"); - } - } catch (IOException e) { - if (DEBUG) { - Log.w(TAG, "Failed to load whitelist driver package, abort."); - } - } - return false; - } - private static native void setLayerPaths(ClassLoader classLoader, String layerPaths); private static native void setDebugLayers(String layers); private static native void setDriverPath(String path); diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java new file mode 100644 index 0000000000000..a68ceed750ad4 --- /dev/null +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -0,0 +1,163 @@ +/* + * Copyright 2019 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 com.android.server.gpu; + +import static android.content.Intent.ACTION_PACKAGE_ADDED; +import static android.content.Intent.ACTION_PACKAGE_CHANGED; +import static android.content.Intent.ACTION_PACKAGE_REMOVED; + +import android.annotation.NonNull; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; + +import com.android.server.SystemService; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; + +/** + * Service to manage GPU related features. + * + *

GPU service is a core service that monitors, coordinates all GPU related features, + * as well as collect metrics about the GPU and GPU driver.

+ */ +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 WHITELIST_FILENAME = "whitelist.txt"; + + private final Context mContext; + private final String mDriverPackageName; + private final PackageManager mPackageManager; + + public GpuService(Context context) { + super(context); + + mContext = context; + mDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + mPackageManager = context.getPackageManager(); + if (mDriverPackageName != null && !mDriverPackageName.isEmpty()) { + final IntentFilter packageFilter = new IntentFilter(); + packageFilter.addAction(ACTION_PACKAGE_ADDED); + packageFilter.addAction(ACTION_PACKAGE_CHANGED); + packageFilter.addAction(ACTION_PACKAGE_REMOVED); + packageFilter.addDataScheme("package"); + getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, + packageFilter, null, null); + } + } + + @Override + public void onStart() { + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_BOOT_COMPLETED) { + if (mDriverPackageName == null || mDriverPackageName.isEmpty()) { + return; + } + fetchGameDriverPackageProperties(); + } + } + + private final class PackageReceiver extends BroadcastReceiver { + @Override + public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { + final Uri data = intent.getData(); + if (data == null && DEBUG) { + Slog.e(TAG, "Cannot handle package broadcast with null data"); + return; + } + final String packageName = data.getSchemeSpecificPart(); + if (!packageName.equals(mDriverPackageName)) { + 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(); + break; + default: + // do nothing + break; + } + } + } + + private void fetchGameDriverPackageProperties() { + final ApplicationInfo driverInfo; + try { + driverInfo = mPackageManager.getApplicationInfo(mDriverPackageName, + PackageManager.MATCH_SYSTEM_ONLY); + } catch (PackageManager.NameNotFoundException e) { + if (DEBUG) { + Slog.e(TAG, "driver package '" + mDriverPackageName + "' 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; + } + + try { + final Context driverContext = mContext.createPackageContext(mDriverPackageName, + Context.CONTEXT_RESTRICTED); + final BufferedReader reader = new BufferedReader( + new InputStreamReader(driverContext.getAssets().open(WHITELIST_FILENAME))); + final ArrayList whitelistedPackageNames = new ArrayList<>(); + for (String packageName; (packageName = reader.readLine()) != null; ) { + whitelistedPackageNames.add(packageName); + } + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.GAME_DRIVER_WHITELIST, + String.join(",", whitelistedPackageNames)); + } catch (PackageManager.NameNotFoundException e) { + if (DEBUG) { + Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed"); + } + } catch (IOException e) { + if (DEBUG) { + Slog.w(TAG, "Failed to load whitelist driver package, abort."); + } + } + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7be7ab2bfb23f..f0292aaded182 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -87,6 +87,7 @@ import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; import com.android.server.emergency.EmergencyAffordanceService; import com.android.server.fingerprint.FingerprintService; +import com.android.server.gpu.GpuService; import com.android.server.hdmi.HdmiControlService; import com.android.server.input.InputManagerService; import com.android.server.job.JobSchedulerService; @@ -747,6 +748,11 @@ public final class SystemServer { traceBeginAndSlog("StartBugreportManagerService"); mSystemServiceManager.startService(BugreportManagerService.class); traceEnd(); + + // Serivce for GPU and GPU driver. + traceBeginAndSlog("GpuService"); + mSystemServiceManager.startService(GpuService.class); + traceEnd(); } /** From b421e0c7966d975f35317ea0c7b4a7722e68ae41 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 4 Feb 2019 17:53:57 -0800 Subject: [PATCH 2/7] Game Driver: clean up GraphicsEnvironment Bug: 123529932 Test: Build, flash and boot. Verify by installing game driver apk Change-Id: Id73605125410a2b4054d9179227022e177d20af2 Merged-In: Id73605125410a2b4054d9179227022e177d20af2 --- core/java/android/os/GraphicsEnvironment.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 57bc026778bba..c49e8a7b1786a 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -104,15 +104,15 @@ public class GraphicsEnvironment { if (isDebuggable(context)) { - int enable = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); + final int enable = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); if (enable != 0) { - String gpuDebugApp = Settings.Global.getString(context.getContentResolver(), - Settings.Global.GPU_DEBUG_APP); + final String gpuDebugApp = Settings.Global.getString(context.getContentResolver(), + Settings.Global.GPU_DEBUG_APP); - String packageName = context.getPackageName(); + final String packageName = context.getPackageName(); if ((gpuDebugApp != null && packageName != null) && (!gpuDebugApp.isEmpty() && !packageName.isEmpty()) @@ -144,7 +144,7 @@ public class GraphicsEnvironment { private static List getGlobalSettingsString(Bundle bundle, String globalSetting) { List valueList = null; - String settingsValue = bundle.getString(globalSetting); + final String settingsValue = bundle.getString(globalSetting); if (settingsValue != null) { valueList = new ArrayList<>(Arrays.asList(settingsValue.split(","))); @@ -159,12 +159,12 @@ public class GraphicsEnvironment { * Choose whether the current process should use the builtin or an updated driver. */ private static void chooseDriver(Context context, Bundle coreSettings) { - String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + final String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); if (driverPackageName == null || driverPackageName.isEmpty()) { return; } - ApplicationInfo driverInfo; + final ApplicationInfo driverInfo; try { driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY); @@ -185,7 +185,7 @@ public class GraphicsEnvironment { // To minimize risk of driver updates crippling the device beyond user repair, never use an // updated driver for privileged or non-updated system apps. Presumably pre-installed apps // were tested thoroughly with the pre-installed driver. - ApplicationInfo ai = context.getApplicationInfo(); + final ApplicationInfo ai = context.getApplicationInfo(); if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) { if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app"); return; @@ -195,7 +195,7 @@ public class GraphicsEnvironment { // 0: Default (Invalid values fallback to default as well) // 1: All apps use Game Driver // 2: All apps use system graphics driver - int gameDriverAllApps = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); + final int gameDriverAllApps = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); if (gameDriverAllApps == 2) { if (DEBUG) { Log.w(TAG, "Game Driver is turned off on this device"); @@ -212,7 +212,7 @@ public class GraphicsEnvironment { } return; } - boolean isOptIn = + final boolean isOptIn = getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) .contains(ai.packageName); if (!isOptIn @@ -229,13 +229,13 @@ public class GraphicsEnvironment { // on the blacklist, terminate early when it's on the blacklist. try { // TODO(b/121350991) Switch to DeviceConfig with property listener. - String base64String = + final String base64String = coreSettings.getString(Settings.Global.GAME_DRIVER_BLACKLIST); if (base64String != null && !base64String.isEmpty()) { - Blacklists blacklistsProto = Blacklists.parseFrom( - Base64.decode(base64String, BASE64_FLAGS)); - List blacklists = blacklistsProto.getBlacklistsList(); - long driverVersionCode = driverInfo.longVersionCode; + final Blacklists blacklistsProto = + Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS)); + final List blacklists = blacklistsProto.getBlacklistsList(); + final long driverVersionCode = driverInfo.longVersionCode; for (Blacklist blacklist : blacklists) { if (blacklist.getVersionCode() == driverVersionCode) { for (String packageName : blacklist.getPackageNamesList()) { @@ -255,7 +255,7 @@ public class GraphicsEnvironment { } } - String abi = chooseAbi(driverInfo); + final String abi = chooseAbi(driverInfo); if (abi == null) { if (DEBUG) { // This is the normal case for the pre-installed empty driver package, don't spam @@ -266,13 +266,13 @@ public class GraphicsEnvironment { return; } - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(driverInfo.nativeLibraryDir) .append(File.pathSeparator); sb.append(driverInfo.sourceDir) .append("!/lib/") .append(abi); - String paths = sb.toString(); + final String paths = sb.toString(); if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths); setDriverPath(paths); @@ -289,7 +289,7 @@ public class GraphicsEnvironment { * Should only be called after chooseDriver(). */ public static void earlyInitEGL() { - Thread eglInitThread = new Thread( + final Thread eglInitThread = new Thread( () -> { EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); }, @@ -298,7 +298,7 @@ public class GraphicsEnvironment { } private static String chooseAbi(ApplicationInfo ai) { - String isa = VMRuntime.getCurrentInstructionSet(); + final String isa = VMRuntime.getCurrentInstructionSet(); if (ai.primaryCpuAbi != null && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) { return ai.primaryCpuAbi; From 8441bcbc6d79d49065d3bd0ff4ced72fe2a9c528 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 7 Feb 2019 15:52:38 -0800 Subject: [PATCH 3/7] Split blacklist from versioned blacklists. Previously we use blacklist to get all blacklists, to maintain the consistency between blacklist and whitelist, and to move blacklist processing to GPU service, we added blacklists to store all blacklists, and now blacklist will only represent one blacklist. BUG: 120869311 Test: Build, flash and boot. Verified in master patch ag/6288554 Change-Id: Ifac875177ad959705c8f80672341c4cbee7bbc93 Merged-In: Ifac875177ad959705c8f80672341c4cbee7bbc93 Exempt-From-Owner-Approval: Change in CoreSettingsObserver.java is too minor --- core/java/android/provider/Settings.java | 6 ++++++ core/proto/android/providers/settings/global.proto | 3 +++ .../coretests/src/android/provider/SettingsBackupTest.java | 1 + .../android/providers/settings/SettingsProtoDumpUtil.java | 3 +++ .../java/com/android/server/am/CoreSettingsObserver.java | 1 + 5 files changed, 14 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a0e4d0dcb90ec..2a257d22f0721 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11474,6 +11474,12 @@ public final class Settings { */ public static final String GAME_DRIVER_BLACKLIST = "game_driver_blacklist"; + /** + * List of blacklists, each blacklist is a blacklist for a specific version of Game Driver. + * @hide + */ + public static final String GAME_DRIVER_BLACKLISTS = "game_driver_blacklists"; + /** * Apps on the whitelist that are allowed to use Game Driver. * The string is a list of application package names, seperated by comma. diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 5aa3992d73f09..05c37ebd4e723 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -399,6 +399,9 @@ message GlobalSettingsProto { optional SettingProto game_driver_blacklist = 11; // Game Driver - List of Apps that are allowed to use Game Driver optional SettingProto game_driver_whitelist = 12; + // Game Driver - List of blacklists, each blacklist is a blacklist for + // a specific Game Driver version + optional SettingProto game_driver_blacklists = 14; } optional Gpu gpu = 59; diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index c1664087fb310..f513cd30b9948 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -447,6 +447,7 @@ public class SettingsBackupTest { Settings.Global.GAME_DRIVER_ALL_APPS, Settings.Global.GAME_DRIVER_OPT_IN_APPS, Settings.Global.GAME_DRIVER_OPT_OUT_APPS, + Settings.Global.GAME_DRIVER_BLACKLISTS, Settings.Global.GAME_DRIVER_BLACKLIST, Settings.Global.GAME_DRIVER_WHITELIST, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 43c1a267468e9..385736657ed28 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -662,6 +662,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.GAME_DRIVER_WHITELIST, GlobalSettingsProto.Gpu.GAME_DRIVER_WHITELIST); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_BLACKLISTS, + GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 75da9b54c6623..00fc4f9369cbb 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -60,6 +60,7 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class); // add other global settings here... } From 8287771adc3ed9971a56aea7acb1014d67eee47a Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 6 Feb 2019 19:37:04 -0800 Subject: [PATCH 4/7] [GPU Service] Move blacklists process to GPU service. Instead of re-process blacklists proto everytime, we move the processing to GPU Service, and add SettingsObserver to observe the change of Settings.Global.GAME_DRIVER_BLACKLISTS such that we only re-process the blacklists when needed. As a result, we will have GAME_DRIVER_BLACKLISTS which is used to accept a list of blacklist from the server, one for each game driver version that needs to have blacklist, and GAME_DRIVER_BLACKLIST will only contain a list of blacklisted application package names for the current version of game driver on the device, separated by comma. BUG: 120869311 Test: Build, flash and boot. Use adb shell settings put command to verify. Change-Id: Ic49800cd0b5b82ddbbdf9907d603243415d5bd3b Merged-In: Ic49800cd0b5b82ddbbdf9907d603243415d5bd3b --- core/java/android/os/GraphicsEnvironment.java | 41 ++----- .../com/android/server/gpu/GpuService.java | 101 +++++++++++++++++- 2 files changed, 104 insertions(+), 38 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index c49e8a7b1786a..da911dfa3da10 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -20,17 +20,12 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; -import android.gamedriver.GameDriverProto.Blacklist; -import android.gamedriver.GameDriverProto.Blacklists; import android.opengl.EGL14; import android.os.Build; import android.os.SystemProperties; import android.provider.Settings; -import android.util.Base64; import android.util.Log; -import com.android.framework.protobuf.InvalidProtocolBufferException; - import dalvik.system.VMRuntime; import java.io.File; @@ -54,8 +49,6 @@ public class GraphicsEnvironment { private static final boolean DEBUG = false; private static final String TAG = "GraphicsEnvironment"; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; - private static final String GAME_DRIVER_BLACKLIST_FLAG = "blacklist"; - private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; private ClassLoader mClassLoader; private String mLayerPath; @@ -224,34 +217,12 @@ public class GraphicsEnvironment { return; } - if (!isOptIn) { - // At this point, the application is on the whitelist only, check whether it's - // on the blacklist, terminate early when it's on the blacklist. - try { - // TODO(b/121350991) Switch to DeviceConfig with property listener. - final String base64String = - coreSettings.getString(Settings.Global.GAME_DRIVER_BLACKLIST); - if (base64String != null && !base64String.isEmpty()) { - final Blacklists blacklistsProto = - Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS)); - final List blacklists = blacklistsProto.getBlacklistsList(); - final long driverVersionCode = driverInfo.longVersionCode; - for (Blacklist blacklist : blacklists) { - if (blacklist.getVersionCode() == driverVersionCode) { - for (String packageName : blacklist.getPackageNamesList()) { - if (packageName == ai.packageName) { - return; - } - } - break; - } - } - } - } catch (InvalidProtocolBufferException e) { - if (DEBUG) { - Log.w(TAG, "Can't parse blacklist, skip and continue..."); - } - } + // If the application is not opted-in and check whether it's on the blacklist, + // terminate early if it's on the blacklist and fallback to system driver. + if (!isOptIn + && getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_BLACKLIST) + .contains(ai.packageName)) { + return; } } diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java index a68ceed750ad4..6899c3ffcbb14 100644 --- a/services/core/java/com/android/server/gpu/GpuService.java +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -22,24 +22,33 @@ import static android.content.Intent.ACTION_PACKAGE_REMOVED; import android.annotation.NonNull; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.database.ContentObserver; +import android.gamedriver.GameDriverProto.Blacklist; +import android.gamedriver.GameDriverProto.Blacklists; import android.net.Uri; import android.os.Build; +import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; +import android.util.Base64; import android.util.Slog; +import com.android.framework.protobuf.InvalidProtocolBufferException; +import com.android.internal.annotations.GuardedBy; import com.android.server.SystemService; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.List; /** * Service to manage GPU related features. @@ -52,17 +61,25 @@ public class GpuService extends SystemService { public static final boolean DEBUG = false; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; - private static final String WHITELIST_FILENAME = "whitelist.txt"; + 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 PackageManager mPackageManager; + private final Object mLock = new Object(); + private ContentResolver mContentResolver; + private long mGameDriverVersionCode; + private SettingsObserver mSettingsObserver; + @GuardedBy("mLock") + private Blacklists mBlacklists; public GpuService(Context context) { super(context); mContext = context; mDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + mGameDriverVersionCode = -1; mPackageManager = context.getPackageManager(); if (mDriverPackageName != null && !mDriverPackageName.isEmpty()) { final IntentFilter packageFilter = new IntentFilter(); @@ -82,10 +99,37 @@ public class GpuService extends SystemService { @Override public void onBootPhase(int phase) { if (phase == PHASE_BOOT_COMPLETED) { + mContentResolver = mContext.getContentResolver(); + mSettingsObserver = new SettingsObserver(); if (mDriverPackageName == null || mDriverPackageName.isEmpty()) { return; } fetchGameDriverPackageProperties(); + processBlacklists(); + setBlacklist(); + } + } + + private final class SettingsObserver extends ContentObserver { + private final Uri mGameDriverBlackUri = + Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_BLACKLISTS); + + SettingsObserver() { + super(new Handler()); + mContentResolver.registerContentObserver(mGameDriverBlackUri, false, this, + UserHandle.USER_ALL); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (uri == null) { + return; + } + + if (mGameDriverBlackUri.equals(uri)) { + processBlacklists(); + setBlacklist(); + } } } @@ -109,6 +153,7 @@ public class GpuService extends SystemService { case ACTION_PACKAGE_CHANGED: case ACTION_PACKAGE_REMOVED: fetchGameDriverPackageProperties(); + setBlacklist(); break; default: // do nothing @@ -138,16 +183,22 @@ public class GpuService extends SystemService { return; } + // Reset the whitelist. + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_WHITELIST, ""); + mGameDriverVersionCode = driverInfo.longVersionCode; + try { final Context driverContext = mContext.createPackageContext(mDriverPackageName, Context.CONTEXT_RESTRICTED); final BufferedReader reader = new BufferedReader( - new InputStreamReader(driverContext.getAssets().open(WHITELIST_FILENAME))); + new InputStreamReader(driverContext.getAssets() + .open(GAME_DRIVER_WHITELIST_FILENAME))); final ArrayList whitelistedPackageNames = new ArrayList<>(); for (String packageName; (packageName = reader.readLine()) != null; ) { whitelistedPackageNames.add(packageName); } - Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.putString(mContentResolver, Settings.Global.GAME_DRIVER_WHITELIST, String.join(",", whitelistedPackageNames)); } catch (PackageManager.NameNotFoundException e) { @@ -160,4 +211,48 @@ public class GpuService extends SystemService { } } } + + private void processBlacklists() { + // TODO(b/121350991) Switch to DeviceConfig with property listener. + String base64String = + Settings.Global.getString(mContentResolver, Settings.Global.GAME_DRIVER_BLACKLISTS); + if (base64String == null || base64String.isEmpty()) { + return; + } + + synchronized (mLock) { + // Reset all blacklists + mBlacklists = null; + try { + mBlacklists = Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS)); + } catch (IllegalArgumentException e) { + if (DEBUG) { + Slog.w(TAG, "Can't parse blacklist, skip and continue..."); + } + } catch (InvalidProtocolBufferException e) { + if (DEBUG) { + Slog.w(TAG, "Can't parse blacklist, skip and continue..."); + } + } + } + } + + private void setBlacklist() { + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_BLACKLIST, ""); + synchronized (mLock) { + if (mBlacklists == null) { + return; + } + List blacklists = mBlacklists.getBlacklistsList(); + for (Blacklist blacklist : blacklists) { + if (blacklist.getVersionCode() == mGameDriverVersionCode) { + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_BLACKLIST, + String.join(",", blacklist.getPackageNamesList())); + return; + } + } + } + } } From db98f35743c7e2a83c71d346220ff4c39e7e0463 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 13 Feb 2019 14:46:54 -0800 Subject: [PATCH 5/7] [Game Driver] Add global whitelist option. Allow a '*' at the beginning of the whitelist file to mean whitelist everything. BUG: 120869311 Test: Build, flash and boot. Verify with apk Change-Id: Ia1b772f545a04acb7f5b4ccbe5489e43ecddb9d2 Merged-In: Ia1b772f545a04acb7f5b4ccbe5489e43ecddb9d2 --- core/java/android/os/GraphicsEnvironment.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index da911dfa3da10..ab4d32c9b6724 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -49,6 +49,7 @@ public class GraphicsEnvironment { private static final boolean DEBUG = false; private static final String TAG = "GraphicsEnvironment"; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; + private static final String GAME_DRIVER_WHITELIST_ALL = "*"; private ClassLoader mClassLoader; private String mLayerPath; @@ -208,9 +209,10 @@ public class GraphicsEnvironment { final boolean isOptIn = getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) .contains(ai.packageName); - if (!isOptIn - && !getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_WHITELIST) - .contains(ai.packageName)) { + final List whitelist = getGlobalSettingsString(coreSettings, + Settings.Global.GAME_DRIVER_WHITELIST); + if (!isOptIn && whitelist.indexOf(GAME_DRIVER_WHITELIST_ALL) != 0 + && !whitelist.contains(ai.packageName)) { if (DEBUG) { Log.w(TAG, ai.packageName + " is not on the whitelist."); } From eb8d7cc3cdc1118c8c125b0d4eb5fa34bc2fc854 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 14 Feb 2019 10:43:42 -0800 Subject: [PATCH 6/7] Game Driver: Add a Settings.Global property for sphal libraries This change add the GAME_DRIVER_SPHAL_LIBRARIES property to save the list of sphal libraries assessible to Game Driver. Bug: 124448366 Test: Build, flash and boot. Change-Id: I7cb06df80f19d87f5fd13d7df3c991ceb5bdfb06 Merged-In: I7cb06df80f19d87f5fd13d7df3c991ceb5bdfb06 Exempt-From-Owner-Approval: Change in CoreSettingsObserver.java is too minor --- core/java/android/provider/Settings.java | 8 ++++++++ core/proto/android/providers/settings/global.proto | 2 ++ .../src/android/provider/SettingsBackupTest.java | 1 + .../android/providers/settings/SettingsProtoDumpUtil.java | 3 +++ .../java/com/android/server/am/CoreSettingsObserver.java | 1 + 5 files changed, 15 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2a257d22f0721..f98641d3ddc75 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11488,6 +11488,14 @@ public final class Settings { */ public static final String GAME_DRIVER_WHITELIST = "game_driver_whitelist"; + /** + * List of libraries in sphal accessible by Game Driver + * The string is a list of library names, separated by colon. + * i.e. ::...: + * @hide + */ + public static final String GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries"; + /** * Ordered GPU debug layer list * i.e. ::...: diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 05c37ebd4e723..a44ec9a911bed 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -402,6 +402,8 @@ message GlobalSettingsProto { // Game Driver - List of blacklists, each blacklist is a blacklist for // a specific Game Driver version optional SettingProto game_driver_blacklists = 14; + // Game Driver - List of libraries in sphal accessible by Game Driver + optional SettingProto game_driver_sphal_libraries = 16; } optional Gpu gpu = 59; diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index f513cd30b9948..76356ed572c76 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -450,6 +450,7 @@ public class SettingsBackupTest { Settings.Global.GAME_DRIVER_BLACKLISTS, Settings.Global.GAME_DRIVER_BLACKLIST, Settings.Global.GAME_DRIVER_WHITELIST, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 385736657ed28..c60e352e9960f 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -665,6 +665,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.GAME_DRIVER_BLACKLISTS, GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, + GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 00fc4f9369cbb..9ff47e0dc0b47 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -61,6 +61,7 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... } From b1eeb0cd9d8624a1b8a0e29b7fe97cb2e8f11fbd Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 14 Feb 2019 12:05:47 -0800 Subject: [PATCH 7/7] Game Driver: process sphal libraries in GPU service This change adds the sphal libraries text file parsing to the GPU service. As the result, when the Game Driver apk is updated, the sphal library list will be read out to the GAME_DRIVER_SPHAL_LIBRARIES settings global property to be used in the graphics environment to extend the current linker namespace. Bug: 124448366 Test: Build, flash and boot. Install the apk to verify settings global. Change-Id: Ifb4007a1fe7269e0a2857fe7badc8642342b1449 Merged-In: Ifb4007a1fe7269e0a2857fe7badc8642342b1449 --- core/java/android/os/GraphicsEnvironment.java | 13 ++++-- core/jni/android_os_GraphicsEnvironment.cpp | 9 ++-- .../com/android/server/gpu/GpuService.java | 44 +++++++++++++------ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index ab4d32c9b6724..1aaee18914a2c 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -247,8 +247,15 @@ public class GraphicsEnvironment { .append(abi); final String paths = sb.toString(); - if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths); - setDriverPath(paths); + final String sphalLibraries = + coreSettings.getString(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES); + + if (DEBUG) { + Log.v(TAG, + "gfx driver package search path: " + paths + + ", required sphal libraries: " + sphalLibraries); + } + setDriverPathAndSphalLibraries(paths, sphalLibraries); } /** @@ -285,5 +292,5 @@ public class GraphicsEnvironment { private static native void setLayerPaths(ClassLoader classLoader, String layerPaths); private static native void setDebugLayers(String layers); - private static native void setDriverPath(String path); + private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); } diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index dfa5de6b65c64..b95d500212d42 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -23,9 +23,12 @@ namespace { -void setDriverPath(JNIEnv* env, jobject clazz, jstring path) { +void setDriverPathAndSphalLibraries_native(JNIEnv* env, jobject clazz, jstring path, + jstring sphalLibraries) { ScopedUtfChars pathChars(env, path); - android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str()); + ScopedUtfChars sphalLibrariesChars(env, sphalLibraries); + android::GraphicsEnv::getInstance().setDriverPathAndSphalLibraries(pathChars.c_str(), + sphalLibrariesChars.c_str()); } void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) { @@ -43,7 +46,7 @@ void setDebugLayers_native(JNIEnv* env, jobject clazz, jstring layers) { } const JNINativeMethod g_methods[] = { - { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast(setDriverPath) }, + { "setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast(setDriverPathAndSphalLibraries_native) }, { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast(setLayerPaths_native) }, { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast(setDebugLayers_native) }, }; diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java index 6899c3ffcbb14..647727f795da6 100644 --- a/services/core/java/com/android/server/gpu/GpuService.java +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -62,6 +62,7 @@ public class GpuService extends SystemService { private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt"; + private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; private final Context mContext; @@ -162,6 +163,25 @@ public class GpuService extends SystemService { } } + private static void assetToSettingsGlobal(Context context, Context driverContext, + String fileName, String settingsGlobal, CharSequence delimiter) { + try { + final BufferedReader reader = new BufferedReader( + new InputStreamReader(driverContext.getAssets().open(fileName))); + final ArrayList assetStrings = new ArrayList<>(); + for (String assetString; (assetString = reader.readLine()) != null; ) { + assetStrings.add(assetString); + } + Settings.Global.putString(context.getContentResolver(), + settingsGlobal, + String.join(delimiter, assetStrings)); + } catch (IOException e) { + if (DEBUG) { + Slog.w(TAG, "Failed to load " + fileName + ", abort."); + } + } + } + private void fetchGameDriverPackageProperties() { final ApplicationInfo driverInfo; try { @@ -186,29 +206,25 @@ public class GpuService extends SystemService { // Reset the whitelist. Settings.Global.putString(mContentResolver, Settings.Global.GAME_DRIVER_WHITELIST, ""); + // Reset the sphal libraries + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ""); mGameDriverVersionCode = driverInfo.longVersionCode; try { final Context driverContext = mContext.createPackageContext(mDriverPackageName, Context.CONTEXT_RESTRICTED); - final BufferedReader reader = new BufferedReader( - new InputStreamReader(driverContext.getAssets() - .open(GAME_DRIVER_WHITELIST_FILENAME))); - final ArrayList whitelistedPackageNames = new ArrayList<>(); - for (String packageName; (packageName = reader.readLine()) != null; ) { - whitelistedPackageNames.add(packageName); - } - Settings.Global.putString(mContentResolver, - Settings.Global.GAME_DRIVER_WHITELIST, - String.join(",", whitelistedPackageNames)); + + assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME, + Settings.Global.GAME_DRIVER_WHITELIST, ","); + + assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_SPHAL_LIBRARIES_FILENAME, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ":"); + } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed"); } - } catch (IOException e) { - if (DEBUG) { - Slog.w(TAG, "Failed to load whitelist driver package, abort."); - } } }