am c5fc9988: Made it easier to disable overlay mechanism of location components.

* commit 'c5fc9988f11acc58229fb6ae80d346277318ada4':
  Made it easier to disable overlay mechanism of location components.
This commit is contained in:
Zhentao Sun
2013-04-23 03:50:20 -07:00
committed by Android Git Automerger
7 changed files with 204 additions and 65 deletions

View File

@@ -633,6 +633,60 @@
<!-- True if WallpaperService is enabled -->
<bool name="config_enableWallpaperService">true</bool>
<!-- Whether to enable network location overlay which allows network
location provider to be replaced by an app at run-time. When disabled,
only the config_networkLocationProviderPackageName package will be
searched for network location provider, otherwise packages whose
signature matches the signatures of config_locationProviderPackageNames
will be searched, and the service with the highest version number will
be picked. Anyone who wants to disable the overlay mechanism can set it
to false.
-->
<bool name="config_enableNetworkLocationOverlay" translatable="false">true</bool>
<!-- Package name providing network location support. Used only when
config_enableNetworkLocationOverlay is false. -->
<string name="config_networkLocationProviderPackageName" translatable="false">@null</string>
<!-- Whether to enable fused location provider overlay which allows fused
location provider to be replaced by an app at run-time. When disabled,
only the config_fusedLocationProviderPackageName package will be
searched for fused location provider, otherwise packages whose
signature matches the signatures of config_locationProviderPackageNames
will be searched, and the service with the highest version number will
be picked. Anyone who wants to disable the overlay mechanism can set it
to false.
-->
<bool name="config_enableFusedLocationOverlay" translatable="false">true</bool>
<!-- Package name providing fused location support. Used only when
config_enableFusedLocationOverlay is false. -->
<string name="config_fusedLocationProviderPackageName" translatable="false">com.android.location.fused</string>
<!-- Whether to enable geocoder overlay which allows geocoder to be replaced
by an app at run-time. When disabled, only the
config_geocoderProviderPackageName package will be searched for
geocoder, otherwise packages whose signature matches the signatures of
config_locationProviderPackageNames will be searched, and the service
with the highest version number will be picked. Anyone who wants to
disable the overlay mechanism can set it to false.
-->
<bool name="config_enableGeocoderOverlay" translatable="false">true</bool>
<!-- Package name providing geocoder API support. Used only when
config_enableGeocoderOverlay is false. -->
<string name="config_geocoderProviderPackageName" translatable="false">@null</string>
<!-- Whether to enable geofence overlay which allows geofence to be replaced
by an app at run-time. When disabled, only the
config_geofenceProviderPackageName package will be searched for
geofence implementation, otherwise packages whose signature matches the
signatures of config_locationProviderPackageNames will be searched, and
the service with the highest version number will be picked. Anyone who
wants to disable the overlay mechanism can set it to false.
-->
<bool name="config_enableGeofenceOverlay" translatable="false">true</bool>
<!-- Package name providing geofence API support. Used only when
config_enableGeofenceOverlay is false. -->
<string name="config_geofenceProviderPackageName" translatable="false">@null</string>
<!-- Package name(s) containing location provider support.
These packages can contain services implementing location providers,
such as the Geocode Provider, Network Location Provider, and

View File

@@ -1534,6 +1534,10 @@
<java-symbol type="array" name="config_notificationFallbackVibePattern" />
<java-symbol type="bool" name="config_animateScreenLights" />
<java-symbol type="bool" name="config_automatic_brightness_available" />
<java-symbol type="bool" name="config_enableFusedLocationOverlay" />
<java-symbol type="bool" name="config_enableGeocoderOverlay" />
<java-symbol type="bool" name="config_enableGeofenceOverlay" />
<java-symbol type="bool" name="config_enableNetworkLocationOverlay" />
<java-symbol type="bool" name="config_sf_limitedAlpha" />
<java-symbol type="bool" name="config_unplugTurnsOnScreen" />
<java-symbol type="bool" name="config_wifi_background_scan_support" />
@@ -1618,6 +1622,10 @@
<java-symbol type="string" name="car_mode_disable_notification_title" />
<java-symbol type="string" name="chooser_wallpaper" />
<java-symbol type="string" name="config_datause_iface" />
<java-symbol type="string" name="config_fusedLocationProviderPackageName" />
<java-symbol type="string" name="config_geocoderProviderPackageName" />
<java-symbol type="string" name="config_geofenceProviderPackageName" />
<java-symbol type="string" name="config_networkLocationProviderPackageName" />
<java-symbol type="string" name="config_wimaxManagerClassname" />
<java-symbol type="string" name="config_wimaxNativeLibLocation" />
<java-symbol type="string" name="config_wimaxServiceClassname" />

View File

@@ -380,7 +380,10 @@ public class LocationManagerService extends ILocationManager.Stub {
mContext,
LocationManager.NETWORK_PROVIDER,
NETWORK_LOCATION_SERVICE_ACTION,
providerPackageNames, mLocationHandler);
com.android.internal.R.bool.config_enableNetworkLocationOverlay,
com.android.internal.R.string.config_networkLocationProviderPackageName,
com.android.internal.R.array.config_locationProviderPackageNames,
mLocationHandler);
if (networkProvider != null) {
mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
mProxyProviders.add(networkProvider);
@@ -394,7 +397,10 @@ public class LocationManagerService extends ILocationManager.Stub {
mContext,
LocationManager.FUSED_PROVIDER,
FUSED_LOCATION_SERVICE_ACTION,
providerPackageNames, mLocationHandler);
com.android.internal.R.bool.config_enableFusedLocationOverlay,
com.android.internal.R.string.config_fusedLocationProviderPackageName,
com.android.internal.R.array.config_locationProviderPackageNames,
mLocationHandler);
if (fusedLocationProvider != null) {
addProviderLocked(fusedLocationProvider);
mProxyProviders.add(fusedLocationProvider);
@@ -406,15 +412,22 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// bind to geocoder provider
mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
com.android.internal.R.bool.config_enableGeocoderOverlay,
com.android.internal.R.string.config_geocoderProviderPackageName,
com.android.internal.R.array.config_locationProviderPackageNames,
mLocationHandler);
if (mGeocodeProvider == null) {
Slog.e(TAG, "no geocoder provider found");
}
// bind to geofence provider
GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, providerPackageNames,
mLocationHandler, gpsProvider.getGpsGeofenceProxy());
GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
com.android.internal.R.bool.config_enableGeofenceOverlay,
com.android.internal.R.string.config_geofenceProviderPackageName,
com.android.internal.R.array.config_locationProviderPackageNames,
mLocationHandler,
gpsProvider.getGpsGeofenceProxy());
if (provider == null) {
Slog.e(TAG, "no geofence provider found");
}
@@ -1290,14 +1303,14 @@ public class LocationManagerService extends ILocationManager.Stub {
if (name == null) {
throw new IllegalArgumentException("provider name must not be null");
}
if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
+ " " + name + " " + request + " from " + packageName + "(" + uid + ")");
LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null) {
throw new IllegalArgumentException("provider doesn't exisit: " + provider);
}
if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
+ " " + name + " " + request + " from " + packageName + "(" + uid + ")");
UpdateRecord record = new UpdateRecord(name, request, receiver);
UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
if (oldRecord != null) {

View File

@@ -27,6 +27,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
@@ -36,6 +37,7 @@ import com.android.internal.content.PackageMonitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -53,6 +55,13 @@ public class ServiceWatcher implements ServiceConnection {
private final PackageManager mPm;
private final List<HashSet<Signature>> mSignatureSets;
private final String mAction;
/**
* If mServicePackageName is not null, only this package will be searched for the service that
* implements mAction. When null, all packages in the system that matches one of the signature
* in mSignatureSets are searched.
*/
private final String mServicePackageName;
private final Runnable mNewServiceWork;
private final Handler mHandler;
@@ -87,19 +96,40 @@ public class ServiceWatcher implements ServiceConnection {
}
public ServiceWatcher(Context context, String logTag, String action,
List<String> initialPackageNames, Runnable newServiceWork, Handler handler) {
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Runnable newServiceWork,
Handler handler) {
mContext = context;
mTag = logTag;
mAction = action;
mPm = mContext.getPackageManager();
mNewServiceWork = newServiceWork;
mHandler = handler;
Resources resources = context.getResources();
// Whether to enable service overlay.
boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
ArrayList<String> initialPackageNames = new ArrayList<String>();
if (enableOverlay) {
// A list of package names used to create the signatures.
String[] pkgs = resources.getStringArray(initialPackageNamesResId);
if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs));
mServicePackageName = null;
if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
} else {
// The default package name that is searched for service implementation when overlay is
// disabled.
String servicePackageName = resources.getString(defaultServicePackageNameResId);
if (servicePackageName != null) initialPackageNames.add(servicePackageName);
mServicePackageName = servicePackageName;
if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName);
}
mSignatureSets = getSignatureSets(context, initialPackageNames);
}
public boolean start() {
synchronized (mLock) {
if (!bindBestPackageLocked(null)) return false;
if (!bindBestPackageLocked(mServicePackageName)) return false;
}
// listen for user change
@@ -115,8 +145,10 @@ public class ServiceWatcher implements ServiceConnection {
}
}, UserHandle.ALL, intentFilter, null, mHandler);
// listen for relevant package changes
mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
// listen for relevant package changes if service overlay is enabled.
if (mServicePackageName == null) {
mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
}
return true;
}
@@ -133,50 +165,55 @@ public class ServiceWatcher implements ServiceConnection {
if (justCheckThisPackage != null) {
intent.setPackage(justCheckThisPackage);
}
List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(new Intent(mAction),
List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
PackageManager.GET_META_DATA, UserHandle.USER_OWNER);
int bestVersion = Integer.MIN_VALUE;
String bestPackage = null;
boolean bestIsMultiuser = false;
for (ResolveInfo rInfo : rInfos) {
String packageName = rInfo.serviceInfo.packageName;
if (rInfos != null) {
for (ResolveInfo rInfo : rInfos) {
String packageName = rInfo.serviceInfo.packageName;
// check signature
try {
PackageInfo pInfo;
pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
if (!isSignatureMatch(pInfo.signatures)) {
Log.w(mTag, packageName + " resolves service " + mAction +
", but has wrong signature, ignoring");
// check signature
try {
PackageInfo pInfo;
pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
if (!isSignatureMatch(pInfo.signatures)) {
Log.w(mTag, packageName + " resolves service " + mAction
+ ", but has wrong signature, ignoring");
continue;
}
} catch (NameNotFoundException e) {
Log.wtf(mTag, e);
continue;
}
} catch (NameNotFoundException e) {
Log.wtf(mTag, e);
continue;
// check metadata
int version = Integer.MIN_VALUE;
boolean isMultiuser = false;
if (rInfo.serviceInfo.metaData != null) {
version = rInfo.serviceInfo.metaData.getInt(
EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
}
if (version > mVersion) {
bestVersion = version;
bestPackage = packageName;
bestIsMultiuser = isMultiuser;
}
}
// check metadata
int version = Integer.MIN_VALUE;
boolean isMultiuser = false;
if (rInfo.serviceInfo.metaData != null) {
version = rInfo.serviceInfo.metaData.getInt(EXTRA_SERVICE_VERSION,
Integer.MIN_VALUE);
isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
}
if (version > mVersion) {
bestVersion = version;
bestPackage = packageName;
bestIsMultiuser = isMultiuser;
if (D) {
Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
(justCheckThisPackage == null ? ""
: "(" + justCheckThisPackage + ") "), rInfos.size(),
(bestPackage == null ? "no new best package"
: "new best package: " + bestPackage)));
}
} else {
if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
}
if (D) Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
(justCheckThisPackage == null ? "" : "(" + justCheckThisPackage + ") "),
rInfos.size(),
(bestPackage == null ? "no new best package" : "new best package: "
+ bestPackage)));
if (bestPackage != null) {
bindToPackageLocked(bestPackage, bestVersion, bestIsMultiuser);
return true;
@@ -243,8 +280,9 @@ public class ServiceWatcher implements ServiceConnection {
// package updated, make sure to rebind
unbindLocked();
}
// check the updated package in case it is better
bindBestPackageLocked(packageName);
// Need to check all packages because this method is also called when a
// system app is uninstalled and the stock version in reinstalled.
bindBestPackageLocked(null);
}
}
@@ -256,7 +294,7 @@ public class ServiceWatcher implements ServiceConnection {
unbindLocked();
}
// check the new package is case it is better
bindBestPackageLocked(packageName);
bindBestPackageLocked(null);
}
}
@@ -271,6 +309,20 @@ public class ServiceWatcher implements ServiceConnection {
}
}
}
@Override
public boolean onPackageChanged(String packageName, int uid, String[] components) {
synchronized (mLock) {
if (packageName.equals(mPackageName)) {
// service enabled or disabled, make sure to rebind
unbindLocked();
}
// the service might be disabled, need to search for a new
// package
bindBestPackageLocked(null);
}
return super.onPackageChanged(packageName, uid, components);
}
};
@Override
@@ -323,7 +375,7 @@ public class ServiceWatcher implements ServiceConnection {
synchronized (mLock) {
if (!mIsMultiuser) {
unbindLocked();
bindBestPackageLocked(null);
bindBestPackageLocked(mServicePackageName);
}
}
}

View File

@@ -40,8 +40,10 @@ public class GeocoderProxy {
private final ServiceWatcher mServiceWatcher;
public static GeocoderProxy createAndBind(Context context,
List<String> initialPackageNames, Handler handler) {
GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames, handler);
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Handler handler) {
GeocoderProxy proxy = new GeocoderProxy(context, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId, handler);
if (proxy.bind()) {
return proxy;
} else {
@@ -49,11 +51,13 @@ public class GeocoderProxy {
}
}
public GeocoderProxy(Context context, List<String> initialPackageNames, Handler handler) {
private GeocoderProxy(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Handler handler) {
mContext = context;
mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames,
null, handler);
mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId, null, handler);
}
private boolean bind () {

View File

@@ -59,8 +59,10 @@ public final class GeofenceProxy {
};
public static GeofenceProxy createAndBind(Context context,
List<String> initialPackageNames, Handler handler, IGpsGeofenceHardware gpsGeofence) {
GeofenceProxy proxy = new GeofenceProxy(context, initialPackageNames, handler, gpsGeofence);
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence) {
GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence);
if (proxy.bindGeofenceProvider()) {
return proxy;
} else {
@@ -68,11 +70,12 @@ public final class GeofenceProxy {
}
}
private GeofenceProxy(Context context, List<String> initialPackageName, Handler handler,
IGpsGeofenceHardware gpsGeofence) {
private GeofenceProxy(Context context,
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence) {
mContext = context;
mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, initialPackageName,
mRunnable, handler);
mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId, mRunnable, handler);
mGpsGeofenceHardware = gpsGeofence;
bindHardwareGeofence();
}

View File

@@ -53,10 +53,13 @@ public class LocationProviderProxy implements LocationProviderInterface {
private ProviderRequest mRequest = null;
private WorkSource mWorksource = new WorkSource();
public static LocationProviderProxy createAndBind(Context context, String name, String action,
List<String> initialPackageNames, Handler handler) {
public static LocationProviderProxy createAndBind(
Context context, String name, String action,
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Handler handler) {
LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
initialPackageNames, handler);
overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId,
handler);
if (proxy.bind()) {
return proxy;
} else {
@@ -65,10 +68,12 @@ public class LocationProviderProxy implements LocationProviderInterface {
}
private LocationProviderProxy(Context context, String name, String action,
List<String> initialPackageNames, Handler handler) {
int overlaySwitchResId, int defaultServicePackageNameResId,
int initialPackageNamesResId, Handler handler) {
mContext = context;
mName = name;
mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames,
mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId,
mNewServiceWork, handler);
}