* commit '0daad84e5105970d33baf3cdcf4543c6421ccc72': Restrict Settings injection to system-signed apps
This commit is contained in:
@@ -22,6 +22,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.location.LocationManager;
|
||||||
import android.location.SettingInjectorService;
|
import android.location.SettingInjectorService;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
@@ -165,29 +166,7 @@ public class LocationSettings extends LocationSettingsBase
|
|||||||
categoryRecentLocationRequests.addPreference(banner);
|
categoryRecentLocationRequests.addPreference(banner);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferenceCategory categoryAppSettings =
|
addAppSettings(activity, root);
|
||||||
(PreferenceCategory) root.findPreference(KEY_APP_SETTINGS);
|
|
||||||
final SettingsInjector injector = new SettingsInjector(activity);
|
|
||||||
List<Preference> appSettings = injector.getInjectedSettings();
|
|
||||||
|
|
||||||
mReceiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
|
||||||
Log.d(TAG, "Received settings change intent: " + intent);
|
|
||||||
}
|
|
||||||
injector.reloadStatusMessages();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
activity.registerReceiver(mReceiver,
|
|
||||||
new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED));
|
|
||||||
|
|
||||||
if (appSettings.size() > 0) {
|
|
||||||
addPreferencesSorted(appSettings, categoryAppSettings);
|
|
||||||
} else {
|
|
||||||
// If there's no item to display, remove the whole category.
|
|
||||||
root.removePreference(categoryAppSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only show the master switch when we're not in multi-pane mode, and not being used as
|
// Only show the master switch when we're not in multi-pane mode, and not being used as
|
||||||
// Setup Wizard.
|
// Setup Wizard.
|
||||||
@@ -209,6 +188,45 @@ public class LocationSettings extends LocationSettingsBase
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the settings injected by external apps into the "App Settings" category. Hides the
|
||||||
|
* category if there are no injected settings.
|
||||||
|
*
|
||||||
|
* Reloads the settings whenever receives
|
||||||
|
* {@link SettingInjectorService#ACTION_INJECTED_SETTING_CHANGED}. As a safety measure,
|
||||||
|
* also reloads on {@link LocationManager#MODE_CHANGED_ACTION} to ensure the settings are
|
||||||
|
* up-to-date after mode changes even if an affected app doesn't send the setting changed
|
||||||
|
* broadcast.
|
||||||
|
*/
|
||||||
|
private void addAppSettings(Context context, PreferenceScreen root) {
|
||||||
|
PreferenceCategory categoryAppSettings =
|
||||||
|
(PreferenceCategory) root.findPreference(KEY_APP_SETTINGS);
|
||||||
|
final SettingsInjector injector = new SettingsInjector(context);
|
||||||
|
List<Preference> appSettings = injector.getInjectedSettings();
|
||||||
|
|
||||||
|
mReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
|
Log.d(TAG, "Received settings change intent: " + intent);
|
||||||
|
}
|
||||||
|
injector.reloadStatusMessages();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
|
||||||
|
filter.addAction(LocationManager.MODE_CHANGED_ACTION);
|
||||||
|
context.registerReceiver(mReceiver, filter);
|
||||||
|
|
||||||
|
if (appSettings.size() > 0) {
|
||||||
|
addPreferencesSorted(appSettings, categoryAppSettings);
|
||||||
|
} else {
|
||||||
|
// If there's no item to display, remove the whole category.
|
||||||
|
root.removePreference(categoryAppSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHelpResource() {
|
public int getHelpResource() {
|
||||||
return R.string.help_url_location_access;
|
return R.string.help_url_location_access;
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.location;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
@@ -138,8 +139,8 @@ class SettingsInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses {@link InjectedSetting} from the attributes of the
|
* Returns the settings parsed from the attributes of the
|
||||||
* {@link SettingInjectorService#META_DATA_NAME} tag.
|
* {@link SettingInjectorService#META_DATA_NAME} tag, or null.
|
||||||
*
|
*
|
||||||
* Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
|
* Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
|
||||||
*/
|
*/
|
||||||
@@ -147,6 +148,15 @@ class SettingsInjector {
|
|||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
|
|
||||||
ServiceInfo si = service.serviceInfo;
|
ServiceInfo si = service.serviceInfo;
|
||||||
|
ApplicationInfo ai = si.applicationInfo;
|
||||||
|
|
||||||
|
if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||||
|
if (Log.isLoggable(TAG, Log.WARN)) {
|
||||||
|
Log.w(TAG, "Ignoring attempt to inject setting from app not in system image: "
|
||||||
|
+ service);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XmlResourceParser parser = null;
|
XmlResourceParser parser = null;
|
||||||
try {
|
try {
|
||||||
@@ -169,7 +179,7 @@ class SettingsInjector {
|
|||||||
+ SettingInjectorService.ATTRIBUTES_NAME + " tag");
|
+ SettingInjectorService.ATTRIBUTES_NAME + " tag");
|
||||||
}
|
}
|
||||||
|
|
||||||
Resources res = pm.getResourcesForApplication(si.applicationInfo);
|
Resources res = pm.getResourcesForApplication(ai);
|
||||||
return parseAttributes(si.packageName, si.name, res, attrs);
|
return parseAttributes(si.packageName, si.name, res, attrs);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
throw new XmlPullParserException(
|
throw new XmlPullParserException(
|
||||||
@@ -191,17 +201,17 @@ class SettingsInjector {
|
|||||||
try {
|
try {
|
||||||
// Note that to help guard against malicious string injection, we do not allow dynamic
|
// Note that to help guard against malicious string injection, we do not allow dynamic
|
||||||
// specification of the label (setting title)
|
// specification of the label (setting title)
|
||||||
final String label = sa.getString(android.R.styleable.SettingInjectorService_title);
|
final String title = sa.getString(android.R.styleable.SettingInjectorService_title);
|
||||||
final int iconId = sa.getResourceId(
|
final int iconId =
|
||||||
android.R.styleable.SettingInjectorService_icon, 0);
|
sa.getResourceId(android.R.styleable.SettingInjectorService_icon, 0);
|
||||||
final String settingsActivity =
|
final String settingsActivity =
|
||||||
sa.getString(android.R.styleable.SettingInjectorService_settingsActivity);
|
sa.getString(android.R.styleable.SettingInjectorService_settingsActivity);
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
Log.d(TAG, "parsed label: " + label + ", iconId: " + iconId
|
Log.d(TAG, "parsed title: " + title + ", iconId: " + iconId
|
||||||
+ ", settingsActivity: " + settingsActivity);
|
+ ", settingsActivity: " + settingsActivity);
|
||||||
}
|
}
|
||||||
return InjectedSetting.newInstance(packageName, className,
|
return InjectedSetting.newInstance(packageName, className,
|
||||||
label, iconId, settingsActivity);
|
title, iconId, settingsActivity);
|
||||||
} finally {
|
} finally {
|
||||||
sa.recycle();
|
sa.recycle();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user