зеркало из https://github.com/AvaloniaUI/angle.git
Create a whitelist for use in Android platform
In order to reduce the startup impact to near zero, we are creating a whitelist to be checked before parsing rules. The whitelist will be shared over Global Settings. To generate it, we will listen for intents at boot (LOCKED_BOOT_COMPLETED) and when ANGLE itself has been updated (MY_PACKAGE_REPLACED). The whitelist can also be populated by hand: adb shell settings put global angle_whitelist app1,app2,appN We plan to further mitigate the ANGLE-enabled app impact by parsing the full rules when creating the whitelist, off of the critical path. Bug: angleproject:3086 Test: Internal CTS tests and manual verification Change-Id: I6263358e2fdbfaa7183d1b941005b5455285cbff Reviewed-on: https://chromium-review.googlesource.com/c/1415715 Reviewed-by: Tim Van Patten <timvp@google.com> Commit-Queue: Cody Northrop <cnorthrop@google.com>
This commit is contained in:
Родитель
1f750d1e3b
Коммит
85ca71c216
|
@ -10,6 +10,7 @@
|
|||
package="{{manifest_package|default('com.android.angle')}}">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<uses-sdk android:minSdkVersion="26"
|
||||
android:targetSdkVersion="28">
|
||||
|
@ -50,5 +51,14 @@
|
|||
<meta-data android:name="com.android.settings.order" android:value="100" />
|
||||
<meta-data android:name="com.android.settings.profile" android:value="primary_profile_only" />
|
||||
</activity>
|
||||
|
||||
<receiver android:name="com.android.angle.common.Receiver"
|
||||
android:directBootAware="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
@ -10,4 +10,5 @@
|
|||
<string name="global_settings_show_angle_in_use_dialog_box">show_angle_in_use_dialog_box</string>
|
||||
<string name="global_settings_driver_selection_pkgs">angle_gl_driver_selection_pkgs</string>
|
||||
<string name="global_settings_driver_selection_values">angle_gl_driver_selection_values</string>
|
||||
<string name="global_settings_angle_whitelist">angle_whitelist</string>
|
||||
</resources>
|
|
@ -78,6 +78,13 @@ class GlobalSettings
|
|||
showAngleInUseDialog ? 1 : 0);
|
||||
}
|
||||
|
||||
static void updateAngleWhitelist(Context context, String packageNames)
|
||||
{
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Settings.Global.putString(contentResolver,
|
||||
context.getString(R.string.global_settings_angle_whitelist), packageNames);
|
||||
}
|
||||
|
||||
void updatePkg(String pkgName, String driver)
|
||||
{
|
||||
int pkgIndex = getGlobalSettingsPkgIndex(pkgName);
|
||||
|
|
|
@ -13,15 +13,98 @@ import android.content.SharedPreferences;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class Receiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
private final static String TAG = Receiver.class.getSimpleName();
|
||||
private final static String TAG = "AngleReceiver";
|
||||
private final static String ANGLE_RULES_FILE = "a4a_rules.json";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
// Nothing to do yet...
|
||||
Log.v(TAG, "Received intent, updating ANGLE whitelist...");
|
||||
|
||||
String jsonStr = loadRules(context);
|
||||
|
||||
String packageNames = parsePackageNames(jsonStr);
|
||||
|
||||
// Update the ANGLE whitelist
|
||||
if (packageNames != null) {
|
||||
GlobalSettings.updateAngleWhitelist(context, packageNames);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the rules file and pull all the JSON into a string
|
||||
*/
|
||||
private String loadRules(Context context)
|
||||
{
|
||||
String jsonStr = null;
|
||||
|
||||
try {
|
||||
InputStream rulesStream = context.getAssets().open(ANGLE_RULES_FILE);
|
||||
int size = rulesStream.available();
|
||||
byte[] buffer = new byte[size];
|
||||
rulesStream.read(buffer);
|
||||
rulesStream.close();
|
||||
jsonStr = new String(buffer, "UTF-8");
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.e(TAG, "Failed to open " + ANGLE_RULES_FILE + ": ", ioe);
|
||||
}
|
||||
|
||||
return jsonStr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract all app package names from the json file and return them comma separated
|
||||
*/
|
||||
private String parsePackageNames(String rulesJSON)
|
||||
{
|
||||
String packageNames = "";
|
||||
|
||||
try {
|
||||
JSONObject jsonObj = new JSONObject(rulesJSON);
|
||||
JSONArray rules = jsonObj.getJSONArray("Rules");
|
||||
if (rules == null) {
|
||||
Log.e(TAG, "No Rules in " + ANGLE_RULES_FILE);
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < rules.length(); i++) {
|
||||
JSONObject rule = rules.getJSONObject(i);
|
||||
JSONArray apps = rule.optJSONArray("Applications");
|
||||
if (apps == null) {
|
||||
Log.v(TAG, "Skipping Rules entry with no Applications");
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < apps.length(); j++) {
|
||||
JSONObject app = apps.optJSONObject(j);
|
||||
String appName = app.optString("AppName");
|
||||
if ((appName == null) || appName.isEmpty()) {
|
||||
Log.e(TAG, "Invalid AppName: '" + appName + "'");
|
||||
}
|
||||
if (packageNames.isEmpty()) {
|
||||
packageNames += appName;
|
||||
} else {
|
||||
packageNames += "," + appName;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.v(TAG, "Parsed the following package names from " +
|
||||
ANGLE_RULES_FILE + ": " + packageNames);
|
||||
} catch (JSONException je) {
|
||||
Log.e(TAG, "Error when parsing angle JSON: ", je);
|
||||
return null;
|
||||
}
|
||||
|
||||
return packageNames;
|
||||
}
|
||||
|
||||
static void updateAllUseAngle(Context context)
|
||||
|
|
Загрузка…
Ссылка в новой задаче