All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.server.gpu.GpuService Maven / Gradle / Ivy

/*
 * 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.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.DeviceConfig;
import android.provider.DeviceConfig.Properties;
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.
 *
 * 

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 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 final Object mDeviceConfigLock = new Object(); private ContentResolver mContentResolver; private long mGameDriverVersionCode; private SettingsObserver mSettingsObserver; private DeviceConfigListener mDeviceConfigListener; @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(); 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) { mContentResolver = mContext.getContentResolver(); if (mDriverPackageName == null || mDriverPackageName.isEmpty()) { return; } mSettingsObserver = new SettingsObserver(); mDeviceConfigListener = new DeviceConfigListener(); 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(); } } } private final class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { DeviceConfigListener() { super(); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_GAME_DRIVER, mContext.getMainExecutor(), this); } @Override public void onPropertiesChanged(Properties properties) { synchronized (mDeviceConfigLock) { if (properties.getKeyset().contains(Settings.Global.GAME_DRIVER_BLACKLISTS)) { parseBlacklists( properties.getString(Settings.Global.GAME_DRIVER_BLACKLISTS, "")); setBlacklist(); } } } } 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(); setBlacklist(); break; default: // do nothing break; } } } 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 { 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; } // 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); 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"); } } } private void processBlacklists() { String base64String = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_GAME_DRIVER, Settings.Global.GAME_DRIVER_BLACKLISTS); if (base64String == null) { base64String = Settings.Global.getString(mContentResolver, Settings.Global.GAME_DRIVER_BLACKLISTS); } parseBlacklists(base64String != null ? base64String : ""); } private void parseBlacklists(String base64String) { 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; } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy