Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.content.Context;
     20 import android.content.pm.ApplicationInfo;
     21 import android.content.pm.PackageManager;
     22 import android.opengl.EGL14;
     23 import android.os.Build;
     24 import android.os.SystemProperties;
     25 import android.util.Log;
     26 
     27 import dalvik.system.VMRuntime;
     28 
     29 import java.io.File;
     30 
     31 /** @hide */
     32 public final class GraphicsEnvironment {
     33 
     34     private static final boolean DEBUG = false;
     35     private static final String TAG = "GraphicsEnvironment";
     36     private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
     37 
     38     public static void setupGraphicsEnvironment(Context context) {
     39         chooseDriver(context);
     40 
     41         // Now that we've figured out which driver to use for this process, load and initialize it.
     42         // This can take multiple frame periods, and it would otherwise happen as part of the first
     43         // frame, increasing first-frame latency. Starting it here, as a low-priority background
     44         // thread, means that it's usually done long before we start drawing the first frame,
     45         // without significantly disrupting other activity launch work.
     46         Thread eglInitThread = new Thread(
     47                 () -> {
     48                     EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
     49                 },
     50                 "EGL Init");
     51         eglInitThread.start();
     52     }
     53 
     54     private static void chooseDriver(Context context) {
     55         String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
     56         if (driverPackageName == null || driverPackageName.isEmpty()) {
     57             return;
     58         }
     59         // To minimize risk of driver updates crippling the device beyond user repair, never use an
     60         // updated driver for privileged or non-updated system apps. Presumably pre-installed apps
     61         // were tested thoroughly with the pre-installed driver.
     62         ApplicationInfo ai = context.getApplicationInfo();
     63         if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
     64             if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app");
     65             return;
     66         }
     67         ApplicationInfo driverInfo;
     68         try {
     69             driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName,
     70                     PackageManager.MATCH_SYSTEM_ONLY);
     71         } catch (PackageManager.NameNotFoundException e) {
     72             Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
     73             return;
     74         }
     75         String abi = chooseAbi(driverInfo);
     76         if (abi == null) {
     77             if (DEBUG) {
     78                 // This is the normal case for the pre-installed empty driver package, don't spam
     79                 if (driverInfo.isUpdatedSystemApp()) {
     80                     Log.w(TAG, "updated driver package has no compatible native libraries");
     81                 }
     82             }
     83             return;
     84         }
     85         if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
     86             // O drivers are restricted to the sphal linker namespace, so don't try to use
     87             // packages unless they declare they're compatible with that restriction.
     88             Log.w(TAG, "updated driver package is not known to be compatible with O");
     89             return;
     90         }
     91 
     92         StringBuilder sb = new StringBuilder();
     93         sb.append(driverInfo.nativeLibraryDir)
     94           .append(File.pathSeparator);
     95         sb.append(driverInfo.sourceDir)
     96           .append("!/lib/")
     97           .append(abi);
     98         String paths = sb.toString();
     99 
    100         if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
    101         setDriverPath(paths);
    102     }
    103 
    104     private static String chooseAbi(ApplicationInfo ai) {
    105         String isa = VMRuntime.getCurrentInstructionSet();
    106         if (ai.primaryCpuAbi != null &&
    107                 isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) {
    108             return ai.primaryCpuAbi;
    109         }
    110         if (ai.secondaryCpuAbi != null &&
    111                 isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) {
    112             return ai.secondaryCpuAbi;
    113         }
    114         return null;
    115     }
    116 
    117     private static native void setDriverPath(String path);
    118 
    119 }
    120