[GraphicsEnvironment] Add whitelist support.

This patch adds the ability to load whitelist from updatable graphcis driver
apk. Typically a whitelist is part of the graphics driver apk, and the name is
set by overwriting ro.gfx.driver.whitelist.0

BUG: 117241379
Test: Build, flash and boot, whitelist an app and verify.
Change-Id: Ie36ca0173a90a8e48acaca2979ab64bbf92eeaed
Merged-In: Ie36ca0173a90a8e48acaca2979ab64bbf92eeaed
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index f2e0bdd..b1408f4 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.res.AssetManager;
 import android.opengl.EGL14;
 import android.os.Build;
 import android.os.SystemProperties;
@@ -27,7 +28,13 @@
 
 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.HashSet;
+import java.util.Set;
 
 /** @hide */
 public class GraphicsEnvironment {
@@ -44,6 +51,7 @@
     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 PROPERTY_GFX_DRIVER_WHITELIST = "ro.gfx.driver.whitelist.0";
 
     private ClassLoader mClassLoader;
     private String mLayerPath;
@@ -146,6 +154,15 @@
             if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app");
             return;
         }
+        Set<String> whitelist = loadWhitelist(context, driverPackageName);
+
+        // Empty whitelist implies no updatable graphics driver. Typically, the pre-installed
+        // updatable graphics driver is supposed to be a place holder and contains no graphics
+        // driver and whitelist.
+        if (whitelist == null || whitelist.isEmpty()) {
+            return;
+        }
+
         ApplicationInfo driverInfo;
         try {
             driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName,
@@ -154,6 +171,22 @@
             Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
             return;
         }
+        if (!whitelist.contains(context.getPackageName())) {
+            if (DEBUG) {
+                Log.w(TAG, context.getPackageName() + " is not on the whitelist.");
+            }
+            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) {
+                Log.w(TAG, "updated driver package is not known to be compatible with O");
+            }
+            return;
+        }
+
         String abi = chooseAbi(driverInfo);
         if (abi == null) {
             if (DEBUG) {
@@ -164,12 +197,6 @@
             }
             return;
         }
-        if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
-            // 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.
-            Log.w(TAG, "updated driver package is not known to be compatible with O");
-            return;
-        }
 
         StringBuilder sb = new StringBuilder();
         sb.append(driverInfo.nativeLibraryDir)
@@ -215,6 +242,34 @@
         return null;
     }
 
+    private static Set<String> loadWhitelist(Context context, String driverPackageName) {
+        String whitelistName = SystemProperties.get(PROPERTY_GFX_DRIVER_WHITELIST);
+        if (whitelistName == null || whitelistName.isEmpty()) {
+            return null;
+        }
+        try {
+            Context driverContext = context.createPackageContext(driverPackageName,
+                                                                 Context.CONTEXT_RESTRICTED);
+            AssetManager assets = driverContext.getAssets();
+            InputStream stream = assets.open(whitelistName);
+            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+            Set<String> whitelist = new HashSet<>();
+            for (String line; (line = reader.readLine()) != null; ) {
+                whitelist.add(line);
+            }
+            return whitelist;
+        } 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 null;
+    }
+
     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/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index 8bf3772..973fa5a 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -460,7 +460,9 @@
         optional int32  vts_coverage = 43;
         optional string zygote = 44;
 
-        // Next Tag: 45
+        optional string gfx_driver_whitelist_0 = 45;
+
+        // Next Tag: 46
     }
     optional Ro ro = 21;