diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 93360a5fa377a..ddec688931cbf 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -34,14 +34,11 @@ import com.android.framework.protobuf.InvalidProtocolBufferException; import dalvik.system.VMRuntime; -import java.io.BufferedReader; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -63,7 +60,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 ANGLE_RULES_FILE = "a4a_rules.json"; private static final String ANGLE_TEMP_RULES = "debug.angle.rules"; private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID"; @@ -553,8 +549,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."); } @@ -647,31 +644,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 int getCanLoadSystemLibraries(); private static native void setLayerPaths(ClassLoader classLoader, String layerPaths); private static native void setDebugLayers(String layers); 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 5861368026197..d25aa8cffb017 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -90,6 +90,7 @@ import com.android.server.display.ColorDisplayService; import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; import com.android.server.emergency.EmergencyAffordanceService; +import com.android.server.gpu.GpuService; import com.android.server.hdmi.HdmiControlService; import com.android.server.input.InputManagerService; import com.android.server.inputmethod.InputMethodManagerService; @@ -811,6 +812,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(); } /**