• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // feature_support_util.cpp: Helps client APIs make decisions based on rules
8 // data files.  For example, the Android EGL loader uses this library to
9 // determine whether to use ANGLE or a native GLES driver.
10 
11 #include "feature_support_util.h"
12 #include <json/json.h>
13 #include <string.h>
14 #include "common/platform.h"
15 #if defined(ANGLE_PLATFORM_ANDROID)
16 #    include <android/log.h>
17 #    include <unistd.h>
18 #endif
19 #include <fstream>
20 #include <list>
21 #include "../gpu_info_util/SystemInfo.h"
22 
23 namespace angle
24 {
25 
26 #if defined(ANGLE_PLATFORM_ANDROID)
27 // Define ANGLE_FEATURE_UTIL_LOG_VERBOSE if you want VERBOSE to output
28 // ANGLE_FEATURE_UTIL_LOG_VERBOSE is automatically defined when is_debug = true
29 
30 #    define ERR(...) __android_log_print(ANDROID_LOG_ERROR, "ANGLE", __VA_ARGS__)
31 #    define WARN(...) __android_log_print(ANDROID_LOG_WARN, "ANGLE", __VA_ARGS__)
32 #    define INFO(...) __android_log_print(ANDROID_LOG_INFO, "ANGLE", __VA_ARGS__)
33 #    define DEBUG(...) __android_log_print(ANDROID_LOG_DEBUG, "ANGLE", __VA_ARGS__)
34 #    ifdef ANGLE_FEATURE_UTIL_LOG_VERBOSE
35 #        define VERBOSE(...) __android_log_print(ANDROID_LOG_VERBOSE, "ANGLE", __VA_ARGS__)
36 #    else
37 #        define VERBOSE(...) ((void)0)
38 #    endif
39 #else  // defined(ANDROID)
40 #    define ERR(...) printf(__VA_ARGS__)
41 #    define WARN(...) printf(__VA_ARGS__)
42 #    define INFO(...) printf(__VA_ARGS__)
43 #    define DEBUG(...) printf(__VA_ARGS__)
44 #    define VERBOSE(...) printf(__VA_ARGS__)
45 #endif  // defined(ANDROID)
46 
47 // JSON values are generally composed of either:
48 //  - Objects, which are a set of comma-separated string:value pairs (note the recursive nature)
49 //  - Arrays, which are a set of comma-separated values.
50 // We'll call the string in a string:value pair the "identifier".  These identifiers are defined
51 // below, as follows:
52 
53 // The JSON identifier for the top-level set of rules.  This is an object, the value of which is an
54 // array of rules.  The rules will be processed in order.  If a rule matches, the rule's version of
55 // the answer (true or false) becomes the new answer.  After all rules are processed, the
56 // most-recent answer is the final answer.
57 constexpr char kJsonRules[] = "Rules";
58 // The JSON identifier for a given rule.  A rule is an object, the first string:value pair is this
59 // identifier (i.e. "Rule") as the string and the value is a user-firendly description of the rule:
60 constexpr char kJsonRule[] = "Rule";
61 // Within a rule, the JSON identifier for the answer--whether or not to use ANGLE.  The value is a
62 // boolean (i.e. true or false).
63 constexpr char kJsonUseANGLE[] = "UseANGLE";
64 
65 // Within a rule, the JSON identifier for describing one or more applications.  The value is an
66 // array of objects, each object of which can specify attributes of an application.
67 constexpr char kJsonApplications[] = "Applications";
68 // Within an object that describes the attributes of an application, the JSON identifier for the
69 // name of the application (e.g. "com.google.maps").  The value is a string.  If any other
70 // attributes will be specified, this must be the first attribute specified in the object.
71 constexpr char kJsonAppName[] = "AppName";
72 
73 // Within a rule, the JSON identifier for describing one or more devices.  The value is an
74 // array of objects, each object of which can specify attributes of a device.
75 constexpr char kJsonDevices[] = "Devices";
76 // Within an object that describes the attributes of a device, the JSON identifier for the
77 // manufacturer of the device.  The value is a string.  If any other non-GPU attributes will be
78 // specified, this must be the first attribute specified in the object.
79 constexpr char kJsonManufacturer[] = "Manufacturer";
80 // Within an object that describes the attributes of a device, the JSON identifier for the
81 // model of the device.  The value is a string.
82 constexpr char kJsonModel[] = "Model";
83 
84 // Within an object that describes the attributes of a device, the JSON identifier for describing
85 // one or more GPUs/drivers used in the device.  The value is an
86 // array of objects, each object of which can specify attributes of a GPU and its driver.
87 constexpr char kJsonGPUs[] = "GPUs";
88 // Within an object that describes the attributes of a GPU and driver, the JSON identifier for the
89 // vendor of the device/driver.  The value is a string.  If any other attributes will be specified,
90 // this must be the first attribute specified in the object.
91 constexpr char kJsonVendor[] = "Vendor";
92 // Within an object that describes the attributes of a GPU and driver, the JSON identifier for the
93 // deviceId of the device.  The value is an unsigned integer.  If the driver version will be
94 // specified, this must preceded the version attributes specified in the object.
95 constexpr char kJsonDeviceId[] = "DeviceId";
96 
97 // Within an object that describes the attributes of either an application or a GPU, the JSON
98 // identifier for the major version of that application or GPU driver.  The value is a positive
99 // integer number.  Not specifying a major version implies a wildcard for all values of a version.
100 constexpr char kJsonVerMajor[] = "VerMajor";
101 // Within an object that describes the attributes of either an application or a GPU, the JSON
102 // identifier for the minor version of that application or GPU driver.  The value is a positive
103 // integer number.  In order to specify a minor version, it must be specified immediately after the
104 // major number associated with it.  Not specifying a minor version implies a wildcard for the
105 // minor, subminor, and patch values of a version.
106 constexpr char kJsonVerMinor[] = "VerMinor";
107 // Within an object that describes the attributes of either an application or a GPU, the JSON
108 // identifier for the subminor version of that application or GPU driver.  The value is a positive
109 // integer number.  In order to specify a subminor version, it must be specified immediately after
110 // the minor number associated with it.  Not specifying a subminor version implies a wildcard for
111 // the subminor and patch values of a version.
112 constexpr char kJsonVerSubMinor[] = "VerSubMinor";
113 // Within an object that describes the attributes of either an application or a GPU, the JSON
114 // identifier for the patch version of that application or GPU driver.  The value is a positive
115 // integer number.  In order to specify a patch version, it must be specified immediately after the
116 // subminor number associated with it.  Not specifying a patch version implies a wildcard for the
117 // patch value of a version.
118 constexpr char kJsonVerPatch[] = "VerPatch";
119 
120 // This encapsulates a std::string.  The default constructor (not given a string) assumes that this
121 // is a wildcard (i.e. will match all other StringPart objects).
122 class StringPart
123 {
124   public:
StringPart()125     StringPart() : mPart(""), mWildcard(true) {}
StringPart(const std::string part)126     StringPart(const std::string part) : mPart(part), mWildcard(false) {}
~StringPart()127     ~StringPart() {}
match(const StringPart & toCheck) const128     bool match(const StringPart &toCheck) const
129     {
130         return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart));
131     }
132 
133   public:
134     std::string mPart;
135     bool mWildcard;
136 };
137 
138 // This encapsulates a 32-bit unsigned integer.  The default constructor (not given a number)
139 // assumes that this is a wildcard (i.e. will match all other IntegerPart objects).
140 class IntegerPart
141 {
142   public:
IntegerPart()143     IntegerPart() : mPart(0), mWildcard(true) {}
IntegerPart(uint32_t part)144     IntegerPart(uint32_t part) : mPart(part), mWildcard(false) {}
~IntegerPart()145     ~IntegerPart() {}
match(const IntegerPart & toCheck) const146     bool match(const IntegerPart &toCheck) const
147     {
148         return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart));
149     }
150 
151   public:
152     uint32_t mPart;
153     bool mWildcard;
154 };
155 
156 // This encapsulates a list of other classes, each of which will have a match() and logItem()
157 // method.  The common constructor (given a type, but not any list items) assumes that this is
158 // a wildcard (i.e. will match all other ListOf<t> objects).
159 template <class T>
160 class ListOf
161 {
162   public:
ListOf(const std::string listType)163     ListOf(const std::string listType) : mWildcard(true), mListType(listType) {}
~ListOf()164     ~ListOf() { mList.clear(); }
addItem(const T & toAdd)165     void addItem(const T &toAdd)
166     {
167         mList.push_back(toAdd);
168         mWildcard = false;
169     }
match(const T & toCheck) const170     bool match(const T &toCheck) const
171     {
172         VERBOSE("\t\t Within ListOf<%s> match: wildcards are %s and %s,\n", mListType.c_str(),
173                 mWildcard ? "true" : "false", toCheck.mWildcard ? "true" : "false");
174         if (mWildcard || toCheck.mWildcard)
175         {
176             return true;
177         }
178         for (const T &it : mList)
179         {
180             VERBOSE("\t\t   Within ListOf<%s> match: calling match on sub-item is %s,\n",
181                     mListType.c_str(), it.match(toCheck) ? "true" : "false");
182             if (it.match(toCheck))
183             {
184                 return true;
185             }
186         }
187         return false;
188     }
match(const ListOf<T> & toCheck) const189     bool match(const ListOf<T> &toCheck) const
190     {
191         VERBOSE("\t\t Within ListOf<%s> match: wildcards are %s and %s,\n", mListType.c_str(),
192                 mWildcard ? "true" : "false", toCheck.mWildcard ? "true" : "false");
193         if (mWildcard || toCheck.mWildcard)
194         {
195             return true;
196         }
197         // If we make it to here, both this and toCheck have at least one item in their mList
198         for (const T &it : toCheck.mList)
199         {
200             if (match(it))
201             {
202                 return true;
203             }
204         }
205         return false;
206     }
logListOf(const std::string prefix,const std::string name) const207     void logListOf(const std::string prefix, const std::string name) const
208     {
209         if (mWildcard)
210         {
211             VERBOSE("%sListOf%s is wildcarded to always match", prefix.c_str(), name.c_str());
212         }
213         else
214         {
215             VERBOSE("%sListOf%s has %d item(s):", prefix.c_str(), name.c_str(),
216                     static_cast<int>(mList.size()));
217             for (auto &it : mList)
218             {
219                 it.logItem();
220             }
221         }
222     }
223 
224     bool mWildcard;
225 
226   private:
227     std::string mListType;
228     std::vector<T> mList;
229 };
230 
231 // This encapsulates up-to four 32-bit unsigned integers, that represent a potentially-complex
232 // version number.  The default constructor (not given any numbers) assumes that this is a wildcard
233 // (i.e. will match all other Version objects).  Each part of a Version is stored in an IntegerPart
234 // class, and so may be wildcarded as well.
235 class Version
236 {
237   public:
Version(uint32_t major,uint32_t minor,uint32_t subminor,uint32_t patch)238     Version(uint32_t major, uint32_t minor, uint32_t subminor, uint32_t patch)
239         : mMajor(major), mMinor(minor), mSubminor(subminor), mPatch(patch), mWildcard(false)
240     {}
Version(uint32_t major,uint32_t minor,uint32_t subminor)241     Version(uint32_t major, uint32_t minor, uint32_t subminor)
242         : mMajor(major), mMinor(minor), mSubminor(subminor), mWildcard(false)
243     {}
Version(uint32_t major,uint32_t minor)244     Version(uint32_t major, uint32_t minor) : mMajor(major), mMinor(minor), mWildcard(false) {}
Version(uint32_t major)245     Version(uint32_t major) : mMajor(major), mWildcard(false) {}
Version()246     Version() : mWildcard(true) {}
Version(const Version & toCopy)247     Version(const Version &toCopy)
248         : mMajor(toCopy.mMajor),
249           mMinor(toCopy.mMinor),
250           mSubminor(toCopy.mSubminor),
251           mPatch(toCopy.mPatch),
252           mWildcard(toCopy.mWildcard)
253     {}
~Version()254     ~Version() {}
255 
CreateVersionFromJson(const Json::Value & jObject)256     static Version *CreateVersionFromJson(const Json::Value &jObject)
257     {
258         Version *version = nullptr;
259         // A major version must be provided before a minor, and so on:
260         if (jObject.isMember(kJsonVerMajor) && jObject[kJsonVerMajor].isInt())
261         {
262             int major = jObject[kJsonVerMajor].asInt();
263             if (jObject.isMember(kJsonVerMinor) && jObject[kJsonVerMinor].isInt())
264             {
265                 int minor = jObject[kJsonVerMinor].asInt();
266                 if (jObject.isMember(kJsonVerSubMinor) && jObject[kJsonVerSubMinor].isInt())
267                 {
268                     int subMinor = jObject[kJsonVerSubMinor].asInt();
269                     if (jObject.isMember(kJsonVerPatch) && jObject[kJsonVerPatch].isInt())
270                     {
271                         int patch = jObject[kJsonVerPatch].asInt();
272                         version   = new Version(major, minor, subMinor, patch);
273                     }
274                     else
275                     {
276                         version = new Version(major, minor, subMinor);
277                     }
278                 }
279                 else
280                 {
281                     version = new Version(major, minor);
282                 }
283             }
284             else
285             {
286                 version = new Version(major);
287             }
288         }
289         return version;
290     }
291 
match(const Version & toCheck) const292     bool match(const Version &toCheck) const
293     {
294         VERBOSE("\t\t\t Within Version %d,%d,%d,%d match(%d,%d,%d,%d): wildcards are %s and %s,\n",
295                 mMajor.mPart, mMinor.mPart, mSubminor.mPart, mPatch.mPart, toCheck.mMajor.mPart,
296                 toCheck.mMinor.mPart, toCheck.mSubminor.mPart, toCheck.mPatch.mPart,
297                 mWildcard ? "true" : "false", toCheck.mWildcard ? "true" : "false");
298         if (!(mWildcard || toCheck.mWildcard))
299         {
300             VERBOSE("\t\t\t   mMajor match is %s, mMinor is %s, mSubminor is %s, mPatch is %s\n",
301                     mMajor.match(toCheck.mMajor) ? "true" : "false",
302                     mMinor.match(toCheck.mMinor) ? "true" : "false",
303                     mSubminor.match(toCheck.mSubminor) ? "true" : "false",
304                     mPatch.match(toCheck.mPatch) ? "true" : "false");
305         }
306         return (mWildcard || toCheck.mWildcard ||
307                 (mMajor.match(toCheck.mMajor) && mMinor.match(toCheck.mMinor) &&
308                  mSubminor.match(toCheck.mSubminor) && mPatch.match(toCheck.mPatch)));
309     }
getString() const310     std::string getString() const
311     {
312         if (mWildcard)
313         {
314             return "*";
315         }
316         else
317         {
318             char ret[100];
319             // Must at least have a major version:
320             if (!mMinor.mWildcard)
321             {
322                 if (!mSubminor.mWildcard)
323                 {
324                     if (!mPatch.mWildcard)
325                     {
326                         snprintf(ret, 100, "%d.%d.%d.%d", mMajor.mPart, mMinor.mPart,
327                                  mSubminor.mPart, mPatch.mPart);
328                     }
329                     else
330                     {
331                         snprintf(ret, 100, "%d.%d.%d.*", mMajor.mPart, mMinor.mPart,
332                                  mSubminor.mPart);
333                     }
334                 }
335                 else
336                 {
337                     snprintf(ret, 100, "%d.%d.*", mMajor.mPart, mMinor.mPart);
338                 }
339             }
340             else
341             {
342                 snprintf(ret, 100, "%d.*", mMajor.mPart);
343             }
344             std::string retString = ret;
345             return retString;
346         }
347     }
348 
349   public:
350     IntegerPart mMajor;
351     IntegerPart mMinor;
352     IntegerPart mSubminor;
353     IntegerPart mPatch;
354     bool mWildcard;
355 };
356 
357 // This encapsulates an application, and potentially the application's Version.  The default
358 // constructor (not given any values) assumes that this is a wildcard (i.e. will match all
359 // other Application objects).  Each part of an Application is stored in a class that may
360 // also be wildcarded.
361 class Application
362 {
363   public:
Application(const std::string name,const Version & version)364     Application(const std::string name, const Version &version)
365         : mName(name), mVersion(version), mWildcard(false)
366     {}
Application(const std::string name)367     Application(const std::string name) : mName(name), mVersion(), mWildcard(false) {}
Application()368     Application() : mName(), mVersion(), mWildcard(true) {}
~Application()369     ~Application() {}
370 
CreateApplicationFromJson(const Json::Value & jObject)371     static Application *CreateApplicationFromJson(const Json::Value &jObject)
372     {
373         Application *application = nullptr;
374 
375         // If an application is listed, the application's name is required:
376         std::string appName = jObject[kJsonAppName].asString();
377 
378         // The application's version is optional:
379         Version *version = Version::CreateVersionFromJson(jObject);
380         if (version)
381         {
382             application = new Application(appName, *version);
383             delete version;
384         }
385         else
386         {
387             application = new Application(appName);
388         }
389         return application;
390     }
391 
match(const Application & toCheck) const392     bool match(const Application &toCheck) const
393     {
394         return (mWildcard || toCheck.mWildcard ||
395                 (toCheck.mName.match(mName) && toCheck.mVersion.match(mVersion)));
396     }
logItem() const397     void logItem() const
398     {
399         if (mWildcard)
400         {
401             VERBOSE("      Wildcard (i.e. will match all applications)");
402         }
403         else if (!mVersion.mWildcard)
404         {
405             VERBOSE("      Application \"%s\" (version: %s)", mName.mPart.c_str(),
406                     mVersion.getString().c_str());
407         }
408         else
409         {
410             VERBOSE("      Application \"%s\"", mName.mPart.c_str());
411         }
412     }
413 
414   public:
415     StringPart mName;
416     Version mVersion;
417     bool mWildcard;
418 };
419 
420 // This encapsulates a GPU and its driver.  The default constructor (not given any values) assumes
421 // that this is a wildcard (i.e. will match all other GPU objects).  Each part of a GPU is stored
422 // in a class that may also be wildcarded.
423 class GPU
424 {
425   public:
GPU(const std::string vendor,uint32_t deviceId,const Version & version)426     GPU(const std::string vendor, uint32_t deviceId, const Version &version)
427         : mVendor(vendor), mDeviceId(IntegerPart(deviceId)), mVersion(version), mWildcard(false)
428     {}
GPU(const std::string vendor,uint32_t deviceId)429     GPU(const std::string vendor, uint32_t deviceId)
430         : mVendor(vendor), mDeviceId(IntegerPart(deviceId)), mVersion(), mWildcard(false)
431     {}
GPU(const std::string vendor)432     GPU(const std::string vendor) : mVendor(vendor), mDeviceId(), mVersion(), mWildcard(false) {}
GPU()433     GPU() : mVendor(), mDeviceId(), mVersion(), mWildcard(true) {}
match(const GPU & toCheck) const434     bool match(const GPU &toCheck) const
435     {
436         VERBOSE("\t\t Within GPU match: wildcards are %s and %s,\n", mWildcard ? "true" : "false",
437                 toCheck.mWildcard ? "true" : "false");
438         VERBOSE("\t\t   mVendor = \"%s\" and toCheck.mVendor = \"%s\"\n", mVendor.mPart.c_str(),
439                 toCheck.mVendor.mPart.c_str());
440         VERBOSE("\t\t   mDeviceId = %d and toCheck.mDeviceId = %d\n", mDeviceId.mPart,
441                 toCheck.mDeviceId.mPart);
442         VERBOSE("\t\t   mVendor match is %s, mDeviceId is %s, mVersion is %s\n",
443                 toCheck.mVendor.match(mVendor) ? "true" : "false",
444                 toCheck.mDeviceId.match(mDeviceId) ? "true" : "false",
445                 toCheck.mVersion.match(mVersion) ? "true" : "false");
446         return (mWildcard || toCheck.mWildcard ||
447                 (toCheck.mVendor.match(mVendor) && toCheck.mDeviceId.match(mDeviceId) &&
448                  toCheck.mVersion.match(mVersion)));
449     }
~GPU()450     ~GPU() {}
451 
CreateGpuFromJson(const Json::Value & jObject)452     static GPU *CreateGpuFromJson(const Json::Value &jObject)
453     {
454         GPU *gpu = nullptr;
455 
456         // If a GPU is listed, the vendor name is required:
457         if (jObject.isMember(kJsonVendor) && jObject[kJsonVendor].isString())
458         {
459             std::string vendor = jObject[kJsonVendor].asString();
460             // If a version is given, the deviceId is required:
461             if (jObject.isMember(kJsonDeviceId) && jObject[kJsonDeviceId].isUInt())
462             {
463                 uint32_t deviceId = jObject[kJsonDeviceId].asUInt();
464                 Version *version  = Version::CreateVersionFromJson(jObject);
465                 if (version)
466                 {
467                     gpu = new GPU(vendor, deviceId, *version);
468                     delete version;
469                 }
470                 else
471                 {
472                     gpu = new GPU(vendor, deviceId);
473                 }
474             }
475             else
476             {
477                 gpu = new GPU(vendor);
478             }
479         }
480         else
481         {
482             WARN("Asked to parse a GPU, but no vendor found");
483         }
484 
485         return gpu;
486     }
487 
logItem() const488     void logItem() const
489     {
490         if (mWildcard)
491         {
492             VERBOSE("          Wildcard (i.e. will match all GPUs)");
493         }
494         else
495         {
496             if (!mDeviceId.mWildcard)
497             {
498                 if (!mVersion.mWildcard)
499                 {
500                     VERBOSE("\t     GPU vendor: %s, deviceId: 0x%x, version: %s",
501                             mVendor.mPart.c_str(), mDeviceId.mPart, mVersion.getString().c_str());
502                 }
503                 else
504                 {
505                     VERBOSE("\t     GPU vendor: %s, deviceId: 0x%x", mVendor.mPart.c_str(),
506                             mDeviceId.mPart);
507                 }
508             }
509             else
510             {
511                 VERBOSE("\t     GPU vendor: %s", mVendor.mPart.c_str());
512             }
513         }
514     }
515 
516   public:
517     StringPart mVendor;
518     IntegerPart mDeviceId;
519     Version mVersion;
520     bool mWildcard;
521 };
522 
523 // This encapsulates a device, and potentially the device's model and/or a list of GPUs/drivers
524 // associated with the Device.  The default constructor (not given any values) assumes that this is
525 // a wildcard (i.e. will match all other Device objects).  Each part of a Device is stored in a
526 // class that may also be wildcarded.
527 class Device
528 {
529   public:
Device(const std::string manufacturer,const std::string model)530     Device(const std::string manufacturer, const std::string model)
531         : mManufacturer(manufacturer), mModel(model), mGpuList("GPU"), mWildcard(false)
532     {}
Device(const std::string manufacturer)533     Device(const std::string manufacturer)
534         : mManufacturer(manufacturer), mModel(), mGpuList("GPU"), mWildcard(false)
535     {}
Device()536     Device() : mManufacturer(), mModel(), mGpuList("GPU"), mWildcard(true) {}
~Device()537     ~Device() {}
538 
CreateDeviceFromJson(const Json::Value & jObject)539     static Device *CreateDeviceFromJson(const Json::Value &jObject)
540     {
541         Device *device = nullptr;
542         if (jObject.isMember(kJsonManufacturer) && jObject[kJsonManufacturer].isString())
543         {
544             std::string manufacturerName = jObject[kJsonManufacturer].asString();
545             // We don't let a model be specified without also specifying an Manufacturer:
546             if (jObject.isMember(kJsonModel) && jObject[kJsonModel].isString())
547             {
548                 std::string model = jObject[kJsonModel].asString();
549                 device            = new Device(manufacturerName, model);
550             }
551             else
552             {
553                 device = new Device(manufacturerName);
554             }
555         }
556         else
557         {
558             // This case is not treated as an error because a rule may wish to only call out one or
559             // more GPUs, but not any specific Manufacturer (e.g. for any manufacturer's device
560             // that uses a GPU from Vendor-A, with DeviceID-Foo, and with driver version 1.2.3.4):
561             device = new Device();
562         }
563         return device;
564     }
565 
addGPU(const GPU & gpu)566     void addGPU(const GPU &gpu) { mGpuList.addItem(gpu); }
match(const Device & toCheck) const567     bool match(const Device &toCheck) const
568     {
569         VERBOSE("\t Within Device match: wildcards are %s and %s,\n", mWildcard ? "true" : "false",
570                 toCheck.mWildcard ? "true" : "false");
571         if (!(mWildcard || toCheck.mWildcard))
572         {
573             VERBOSE("\t   Manufacturer match is %s, model is %s\n",
574                     toCheck.mManufacturer.match(mManufacturer) ? "true" : "false",
575                     toCheck.mModel.match(mModel) ? "true" : "false");
576         }
577         VERBOSE("\t   Need to check ListOf<GPU>\n");
578         return ((mWildcard || toCheck.mWildcard ||
579                  // The wildcards can override the Manufacturer/Model check, but not the GPU check
580                  (toCheck.mManufacturer.match(mManufacturer) && toCheck.mModel.match(mModel))) &&
581                 mGpuList.match(toCheck.mGpuList));
582     }
logItem() const583     void logItem() const
584     {
585         if (mWildcard)
586         {
587             if (mGpuList.mWildcard)
588             {
589                 VERBOSE("      Wildcard (i.e. will match all devices)");
590                 return;
591             }
592             else
593             {
594                 VERBOSE(
595                     "      Device with any manufacturer and model"
596                     ", and with the following GPUs:");
597             }
598         }
599         else
600         {
601             if (!mModel.mWildcard)
602             {
603                 VERBOSE(
604                     "      Device manufacturer: \"%s\" and model \"%s\""
605                     ", and with the following GPUs:",
606                     mManufacturer.mPart.c_str(), mModel.mPart.c_str());
607             }
608             else
609             {
610                 VERBOSE(
611                     "      Device manufacturer: \"%s\""
612                     ", and with the following GPUs:",
613                     mManufacturer.mPart.c_str());
614             }
615         }
616         mGpuList.logListOf("        ", "GPUs");
617     }
618 
619   public:
620     StringPart mManufacturer;
621     StringPart mModel;
622     ListOf<GPU> mGpuList;
623     bool mWildcard;
624 };
625 
626 // This encapsulates a particular scenario to check against the rules.  A Scenario is similar to a
627 // Rule, except that a Rule has an answer and potentially many wildcards, and a Scenario is the
628 // fully-specified combination of an Application and a Device that is proposed to be run with
629 // ANGLE.  It is compared with the list of Rules.
630 class Scenario
631 {
632   public:
Scenario(const char * appName,const char * deviceMfr,const char * deviceModel)633     Scenario(const char *appName, const char *deviceMfr, const char *deviceModel)
634         : mApplication(Application(appName)), mDevice(Device(deviceMfr, deviceModel))
635     {}
~Scenario()636     ~Scenario() {}
logScenario()637     void logScenario()
638     {
639         VERBOSE("  Scenario to compare against the rules");
640         VERBOSE("    Application:");
641         mApplication.logItem();
642         VERBOSE("    Device:");
643         mDevice.logItem();
644     }
645 
646   public:
647     Application mApplication;
648     Device mDevice;
649 };
650 
651 // This encapsulates a Rule that provides an answer based on whether a particular Scenario matches
652 // the Rule.  A Rule always has an answer, but can potentially wildcard every item in it (i.e.
653 // match every scenario).
654 class Rule
655 {
656   public:
Rule(const std::string description,bool useANGLE)657     Rule(const std::string description, bool useANGLE)
658         : mDescription(description),
659           mAppList("Application"),
660           mDevList("Device"),
661           mUseANGLE(useANGLE)
662     {}
~Rule()663     ~Rule() {}
addApp(const Application & app)664     void addApp(const Application &app) { mAppList.addItem(app); }
addDevice(const Device & dev)665     void addDevice(const Device &dev) { mDevList.addItem(dev); }
match(const Scenario & toCheck) const666     bool match(const Scenario &toCheck) const
667     {
668         VERBOSE("    Within \"%s\" Rule: application match is %s and device match is %s\n",
669                 mDescription.c_str(), mAppList.match(toCheck.mApplication) ? "true" : "false",
670                 mDevList.match(toCheck.mDevice) ? "true" : "false");
671         return (mAppList.match(toCheck.mApplication) && mDevList.match(toCheck.mDevice));
672     }
getUseANGLE() const673     bool getUseANGLE() const { return mUseANGLE; }
logRule() const674     void logRule() const
675     {
676         VERBOSE("  Rule: \"%s\" %s ANGLE", mDescription.c_str(),
677                 mUseANGLE ? "enables" : "disables");
678         mAppList.logListOf("    ", "Applications");
679         mDevList.logListOf("    ", "Devices");
680     }
681 
682     std::string mDescription;
683     ListOf<Application> mAppList;
684     ListOf<Device> mDevList;
685     bool mUseANGLE;
686 };
687 
688 // This encapsulates a list of Rules that Scenarios are matched against.  A Scenario is compared
689 // with each Rule, in order.  Any time a Scenario matches a Rule, the current answer is overridden
690 // with the answer of the matched Rule.
691 class RuleList
692 {
693   public:
RuleList()694     RuleList() {}
~RuleList()695     ~RuleList() { mRuleList.clear(); }
696 
ReadRulesFromJsonString(const std::string jsonFileContents)697     static RuleList *ReadRulesFromJsonString(const std::string jsonFileContents)
698     {
699         RuleList *rules = new RuleList;
700 
701         // Open the file and start parsing it:
702         Json::Reader jReader;
703         Json::Value jTopLevelObject;
704         jReader.parse(jsonFileContents, jTopLevelObject);
705         Json::Value jRules = jTopLevelObject[kJsonRules];
706         for (unsigned int ruleIndex = 0; ruleIndex < jRules.size(); ruleIndex++)
707         {
708             Json::Value jRule           = jRules[ruleIndex];
709             std::string ruleDescription = jRule[kJsonRule].asString();
710             bool useANGLE               = jRule[kJsonUseANGLE].asBool();
711             Rule *newRule               = new Rule(ruleDescription, useANGLE);
712 
713             Json::Value jApps = jRule[kJsonApplications];
714             for (unsigned int appIndex = 0; appIndex < jApps.size(); appIndex++)
715             {
716                 Json::Value jApp    = jApps[appIndex];
717                 Application *newApp = Application::CreateApplicationFromJson(jApp);
718                 newRule->addApp(*newApp);
719                 delete newApp;
720             }
721 
722             Json::Value jDevs = jRule[kJsonDevices];
723             for (unsigned int deviceIndex = 0; deviceIndex < jDevs.size(); deviceIndex++)
724             {
725                 Json::Value jDev = jDevs[deviceIndex];
726                 Device *newDev   = Device::CreateDeviceFromJson(jDev);
727 
728                 Json::Value jGPUs = jDev[kJsonGPUs];
729                 for (unsigned int gpuIndex = 0; gpuIndex < jGPUs.size(); gpuIndex++)
730                 {
731                     Json::Value jGPU = jGPUs[gpuIndex];
732                     GPU *newGPU      = GPU::CreateGpuFromJson(jGPU);
733                     if (newGPU)
734                     {
735                         newDev->addGPU(*newGPU);
736                         delete newGPU;
737                     }
738                 }
739                 newRule->addDevice(*newDev);
740                 delete newDev;
741             }
742 
743             rules->addRule(*newRule);
744             delete newRule;
745         }
746 
747         // Make sure there is at least one, default rule.  If not, add it here:
748         if (rules->mRuleList.size() == 0)
749         {
750             Rule defaultRule("Default Rule", false);
751             rules->addRule(defaultRule);
752         }
753         return rules;
754     }
755 
addRule(const Rule & rule)756     void addRule(const Rule &rule) { mRuleList.push_back(rule); }
getUseANGLE(const Scenario & toCheck)757     bool getUseANGLE(const Scenario &toCheck)
758     {
759         // Initialize useANGLE to the system-wide default (that should be set in the default
760         // rule, but just in case, set it here too):
761         bool useANGLE = false;
762         VERBOSE("Checking scenario against %d ANGLE-for-Android rules:",
763                 static_cast<int>(mRuleList.size()));
764 
765         for (const Rule &rule : mRuleList)
766         {
767             VERBOSE("  Checking Rule: \"%s\" (to see whether there's a match)",
768                     rule.mDescription.c_str());
769             if (rule.match(toCheck))
770             {
771                 VERBOSE("  -> Rule matches.  Setting useANGLE to %s",
772                         rule.getUseANGLE() ? "true" : "false");
773                 useANGLE = rule.getUseANGLE();
774             }
775             else
776             {
777                 VERBOSE("  -> Rule doesn't match.");
778             }
779         }
780 
781         return useANGLE;
782     }
logRules()783     void logRules()
784     {
785         VERBOSE("Showing %d ANGLE-for-Android rules:", static_cast<int>(mRuleList.size()));
786         for (const Rule &rule : mRuleList)
787         {
788             rule.logRule();
789         }
790     }
791 
792   public:
793     std::vector<Rule> mRuleList;
794 };
795 
796 }  // namespace angle
797 
798 extern "C" {
799 
800 using namespace angle;
801 
802 // This function is part of the version-2 API:
ANGLEGetFeatureSupportUtilAPIVersion(unsigned int * versionToUse)803 ANGLE_EXPORT bool ANGLEGetFeatureSupportUtilAPIVersion(unsigned int *versionToUse)
804 {
805     if (!versionToUse || (*versionToUse < kFeatureVersion_LowestSupported))
806     {
807         // The versionToUse is either nullptr or is less than the lowest version supported, which
808         // is an error.
809         return false;
810     }
811     if (*versionToUse > kFeatureVersion_HighestSupported)
812     {
813         // The versionToUse is greater than the highest version supported; change it to the
814         // highest version supported (caller will decide if it can use that version).
815         *versionToUse = kFeatureVersion_HighestSupported;
816     }
817     return true;
818 }
819 
820 // This function is part of the version-2 API:
ANGLEAndroidParseRulesString(const char * rulesString,RulesHandle * rulesHandle,int * rulesVersion)821 ANGLE_EXPORT bool ANGLEAndroidParseRulesString(const char *rulesString,
822                                                RulesHandle *rulesHandle,
823                                                int *rulesVersion)
824 {
825     if (!rulesString || !rulesHandle || !rulesVersion)
826     {
827         return false;
828     }
829 
830     std::string rulesFileContents = rulesString;
831     RuleList *rules               = RuleList::ReadRulesFromJsonString(rulesFileContents);
832     rules->logRules();
833 
834     *rulesHandle  = rules;
835     *rulesVersion = 0;
836     return true;
837 }
838 
839 // This function is part of the version-2 API:
ANGLEGetSystemInfo(SystemInfoHandle * systemInfoHandle)840 ANGLE_EXPORT bool ANGLEGetSystemInfo(SystemInfoHandle *systemInfoHandle)
841 {
842     if (!systemInfoHandle)
843     {
844         return false;
845     }
846 
847     // TODO (http://anglebug.com/3036): Restore the real code
848     angle::SystemInfo *systemInfo = new angle::SystemInfo;
849     systemInfo->gpus.resize(1);
850     GPUDeviceInfo &gpu = systemInfo->gpus[0];
851     gpu.vendorId       = 0xFEFEFEFE;
852     gpu.deviceId       = 0xFEEEFEEE;
853     gpu.driverVendor   = "Foo";
854     gpu.driverVersion  = "1.2.3.4";
855 
856     *systemInfoHandle = systemInfo;
857     return true;
858 }
859 
860 // This function is part of the version-2 API:
ANGLEAddDeviceInfoToSystemInfo(const char * deviceMfr,const char * deviceModel,SystemInfoHandle systemInfoHandle)861 ANGLE_EXPORT bool ANGLEAddDeviceInfoToSystemInfo(const char *deviceMfr,
862                                                  const char *deviceModel,
863                                                  SystemInfoHandle systemInfoHandle)
864 {
865     angle::SystemInfo *systemInfo = static_cast<angle::SystemInfo *>(systemInfoHandle);
866     if (!deviceMfr || !deviceModel || !systemInfo)
867     {
868         return false;
869     }
870 
871     systemInfo->machineManufacturer = deviceMfr;
872     systemInfo->machineModelName    = deviceModel;
873     return true;
874 }
875 
876 // This function is part of the version-2 API:
ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle,int rulesVersion,const SystemInfoHandle systemInfoHandle,const char * appName)877 ANGLE_EXPORT bool ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle,
878                                                   int rulesVersion,
879                                                   const SystemInfoHandle systemInfoHandle,
880                                                   const char *appName)
881 {
882     RuleList *rules               = static_cast<RuleList *>(rulesHandle);
883     angle::SystemInfo *systemInfo = static_cast<angle::SystemInfo *>(systemInfoHandle);
884     if (!rules || !systemInfo || !appName || (systemInfo->gpus.size() != 1))
885     {
886         return false;
887     }
888 
889     Scenario scenario(appName, systemInfo->machineManufacturer.c_str(),
890                       systemInfo->machineModelName.c_str());
891     Version gpuDriverVersion(systemInfo->gpus[0].detailedDriverVersion.major,
892                              systemInfo->gpus[0].detailedDriverVersion.minor,
893                              systemInfo->gpus[0].detailedDriverVersion.subMinor,
894                              systemInfo->gpus[0].detailedDriverVersion.patch);
895     GPU gpuDriver(systemInfo->gpus[0].driverVendor, systemInfo->gpus[0].deviceId, gpuDriverVersion);
896     scenario.mDevice.addGPU(gpuDriver);
897     scenario.logScenario();
898 
899     bool rtn = rules->getUseANGLE(scenario);
900     VERBOSE("Application \"%s\" should %s ANGLE", appName, rtn ? "use" : "NOT use");
901 
902     return rtn;
903 }
904 
905 // This function is part of the version-2 API:
ANGLEFreeRulesHandle(const RulesHandle rulesHandle)906 ANGLE_EXPORT void ANGLEFreeRulesHandle(const RulesHandle rulesHandle)
907 {
908     RuleList *rules = static_cast<RuleList *>(rulesHandle);
909     if (rules)
910     {
911         delete rules;
912     }
913 }
914 
915 // This function is part of the version-2 API:
ANGLEFreeSystemInfoHandle(const SystemInfoHandle systemInfoHandle)916 ANGLE_EXPORT void ANGLEFreeSystemInfoHandle(const SystemInfoHandle systemInfoHandle)
917 {
918     angle::SystemInfo *systemInfo = static_cast<angle::SystemInfo *>(systemInfoHandle);
919     if (systemInfo)
920     {
921         delete systemInfo;
922     }
923 }
924 
925 }  // extern "C"
926