Merge "Changes to support updating location providers." into jb-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e09aed49e3
@@ -636,19 +636,12 @@
|
|||||||
of new location providers at run-time. The new package does not
|
of new location providers at run-time. The new package does not
|
||||||
have to be explicitly listed here, however it must have a signature
|
have to be explicitly listed here, however it must have a signature
|
||||||
that matches the signature of at least one package on this list.
|
that matches the signature of at least one package on this list.
|
||||||
Platforms should overlay additional packages in
|
|
||||||
config_overlay_locationProviderPackageNames, instead of overlaying
|
|
||||||
this config, if they only want to append packages and not replace
|
|
||||||
the entire array.
|
|
||||||
-->
|
-->
|
||||||
<string-array name="config_locationProviderPackageNames" translatable="false">
|
<string-array name="config_locationProviderPackageNames" translatable="false">
|
||||||
|
<!-- The standard AOSP fused location provider -->
|
||||||
<item>com.android.location.fused</item>
|
<item>com.android.location.fused</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Pacakge name(s) supplied by overlay, and appended to
|
|
||||||
config_locationProviderPackageNames. -->
|
|
||||||
<string-array name="config_overlay_locationProviderPackageNames" translatable="false" />
|
|
||||||
|
|
||||||
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
|
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
|
||||||
use cases -->
|
use cases -->
|
||||||
<bool name="config_bluetooth_sco_off_call">true</bool>
|
<bool name="config_bluetooth_sco_off_call">true</bool>
|
||||||
|
|||||||
@@ -1475,7 +1475,6 @@
|
|||||||
<java-symbol type="array" name="radioAttributes" />
|
<java-symbol type="array" name="radioAttributes" />
|
||||||
<java-symbol type="array" name="config_oemUsbModeOverride" />
|
<java-symbol type="array" name="config_oemUsbModeOverride" />
|
||||||
<java-symbol type="array" name="config_locationProviderPackageNames" />
|
<java-symbol type="array" name="config_locationProviderPackageNames" />
|
||||||
<java-symbol type="array" name="config_overlay_locationProviderPackageNames" />
|
|
||||||
<java-symbol type="bool" name="config_animateScreenLights" />
|
<java-symbol type="bool" name="config_animateScreenLights" />
|
||||||
<java-symbol type="bool" name="config_automatic_brightness_available" />
|
<java-symbol type="bool" name="config_automatic_brightness_available" />
|
||||||
<java-symbol type="bool" name="config_sf_limitedAlpha" />
|
<java-symbol type="bool" name="config_sf_limitedAlpha" />
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
-->
|
-->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.android.location.fused"
|
package="com.android.location.fused"
|
||||||
coreApp="true">
|
coreApp="true"
|
||||||
|
android:sharedUserId="android.uid.system">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.android.location.service.FusedLocationProvider" />
|
<action android:name="com.android.location.service.FusedLocationProvider" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="version" android:value="1" />
|
<meta-data android:name="serviceVersion" android:value="0" />
|
||||||
</service>
|
</service>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -23,8 +23,11 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.content.pm.Signature;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.location.Address;
|
import android.location.Address;
|
||||||
@@ -249,6 +252,74 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
updateProvidersLocked();
|
updateProvidersLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
|
||||||
|
PackageManager pm = mContext.getPackageManager();
|
||||||
|
String systemPackageName = mContext.getPackageName();
|
||||||
|
ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
|
||||||
|
|
||||||
|
List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
|
||||||
|
new Intent(FUSED_LOCATION_SERVICE_ACTION),
|
||||||
|
PackageManager.GET_META_DATA, mCurrentUserId);
|
||||||
|
for (ResolveInfo rInfo : rInfos) {
|
||||||
|
String packageName = rInfo.serviceInfo.packageName;
|
||||||
|
|
||||||
|
// Check that the signature is in the list of supported sigs. If it's not in
|
||||||
|
// this list the standard provider binding logic won't bind to it.
|
||||||
|
try {
|
||||||
|
PackageInfo pInfo;
|
||||||
|
pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
|
||||||
|
if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
|
||||||
|
Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
|
||||||
|
", but has wrong signature, ignoring");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "missing package: " + packageName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the version info
|
||||||
|
if (rInfo.serviceInfo.metaData == null) {
|
||||||
|
Log.w(TAG, "Found fused provider without metadata: " + packageName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = rInfo.serviceInfo.metaData.getInt(
|
||||||
|
ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
|
||||||
|
if (version == 0) {
|
||||||
|
// This should be the fallback fused location provider.
|
||||||
|
|
||||||
|
// Make sure it's in the system partition.
|
||||||
|
if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||||
|
if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the fallback is signed the same as the OS
|
||||||
|
// as a proxy for coreApp="true"
|
||||||
|
if (pm.checkSignatures(systemPackageName, packageName)
|
||||||
|
!= PackageManager.SIGNATURE_MATCH) {
|
||||||
|
if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
|
||||||
|
+ packageName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Found a valid fallback.
|
||||||
|
if (D) Log.d(TAG, "Found fallback provider: " + packageName);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Unable to find a fused location provider that is in the "
|
||||||
|
+ "system partition with version 0 and signed with the platform certificate. "
|
||||||
|
+ "Such a package is needed to provide a default fused location provider in the "
|
||||||
|
+ "event that no other fused location provider has been installed or is currently "
|
||||||
|
+ "available. For example, coreOnly boot mode when decrypting the data "
|
||||||
|
+ "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
|
||||||
|
}
|
||||||
|
|
||||||
private void loadProvidersLocked() {
|
private void loadProvidersLocked() {
|
||||||
// create a passive location provider, which is always enabled
|
// create a passive location provider, which is always enabled
|
||||||
PassiveProvider passiveProvider = new PassiveProvider(this);
|
PassiveProvider passiveProvider = new PassiveProvider(this);
|
||||||
@@ -278,14 +349,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
*/
|
*/
|
||||||
Resources resources = mContext.getResources();
|
Resources resources = mContext.getResources();
|
||||||
ArrayList<String> providerPackageNames = new ArrayList<String>();
|
ArrayList<String> providerPackageNames = new ArrayList<String>();
|
||||||
String[] pkgs1 = resources.getStringArray(
|
String[] pkgs = resources.getStringArray(
|
||||||
com.android.internal.R.array.config_locationProviderPackageNames);
|
com.android.internal.R.array.config_locationProviderPackageNames);
|
||||||
String[] pkgs2 = resources.getStringArray(
|
if (D) Log.d(TAG, "certificates for location providers pulled from: " +
|
||||||
com.android.internal.R.array.config_overlay_locationProviderPackageNames);
|
Arrays.toString(pkgs));
|
||||||
if (D) Log.d(TAG, "built-in location providers: " + Arrays.toString(pkgs1));
|
if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
|
||||||
if (D) Log.d(TAG, "overlay location providers: " + Arrays.toString(pkgs2));
|
|
||||||
if (pkgs1 != null) providerPackageNames.addAll(Arrays.asList(pkgs1));
|
ensureFallbackFusedProviderPresentLocked(providerPackageNames);
|
||||||
if (pkgs2 != null) providerPackageNames.addAll(Arrays.asList(pkgs2));
|
|
||||||
|
|
||||||
// bind to network provider
|
// bind to network provider
|
||||||
LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
|
LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ServiceWatcher implements ServiceConnection {
|
public class ServiceWatcher implements ServiceConnection {
|
||||||
private static final boolean D = false;
|
private static final boolean D = false;
|
||||||
private static final String EXTRA_VERSION = "version";
|
public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
|
||||||
|
|
||||||
private final String mTag;
|
private final String mTag;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -58,9 +58,27 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
// all fields below synchronized on mLock
|
// all fields below synchronized on mLock
|
||||||
private IBinder mBinder; // connected service
|
private IBinder mBinder; // connected service
|
||||||
private String mPackageName; // current best package
|
private String mPackageName; // current best package
|
||||||
private int mVersion; // current best version
|
private int mVersion = Integer.MIN_VALUE; // current best version
|
||||||
private int mCurrentUserId;
|
private int mCurrentUserId;
|
||||||
|
|
||||||
|
public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
|
||||||
|
List<String> initialPackageNames) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
|
||||||
|
for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
|
||||||
|
String pkg = initialPackageNames.get(i);
|
||||||
|
try {
|
||||||
|
HashSet<Signature> set = new HashSet<Signature>();
|
||||||
|
Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES).signatures;
|
||||||
|
set.addAll(Arrays.asList(sigs));
|
||||||
|
sigSets.add(set);
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
Log.w("ServiceWatcher", pkg + " not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sigSets;
|
||||||
|
}
|
||||||
|
|
||||||
public ServiceWatcher(Context context, String logTag, String action,
|
public ServiceWatcher(Context context, String logTag, String action,
|
||||||
List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
|
List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@@ -71,20 +89,7 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mCurrentUserId = userId;
|
mCurrentUserId = userId;
|
||||||
|
|
||||||
mSignatureSets = new ArrayList<HashSet<Signature>>();
|
mSignatureSets = getSignatureSets(context, initialPackageNames);
|
||||||
for (int i=0; i < initialPackageNames.size(); i++) {
|
|
||||||
String pkg = initialPackageNames.get(i);
|
|
||||||
HashSet<Signature> set = new HashSet<Signature>();
|
|
||||||
try {
|
|
||||||
Signature[] sigs =
|
|
||||||
mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES).signatures;
|
|
||||||
set.addAll(Arrays.asList(sigs));
|
|
||||||
mSignatureSets.add(set);
|
|
||||||
} catch (NameNotFoundException e) {
|
|
||||||
Log.w(logTag, pkg + " not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
@@ -132,15 +137,16 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
// check version
|
// check version
|
||||||
int version = 0;
|
int version = 0;
|
||||||
if (rInfo.serviceInfo.metaData != null) {
|
if (rInfo.serviceInfo.metaData != null) {
|
||||||
version = rInfo.serviceInfo.metaData.getInt(EXTRA_VERSION, 0);
|
version = rInfo.serviceInfo.metaData.getInt(EXTRA_SERVICE_VERSION, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version > mVersion) {
|
if (version > mVersion) {
|
||||||
bestVersion = version;
|
bestVersion = version;
|
||||||
bestPackage = packageName;
|
bestPackage = packageName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (D) Log.d(mTag, String.format("bindBestPackage %s found %d, %s",
|
if (D) Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
|
||||||
(justCheckThisPackage == null ? "" : "(" + justCheckThisPackage + ") "),
|
(justCheckThisPackage == null ? "" : "(" + justCheckThisPackage + ") "),
|
||||||
rInfos.size(),
|
rInfos.size(),
|
||||||
(bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
|
(bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
|
||||||
@@ -174,7 +180,8 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
| Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
|
| Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSignatureMatch(Signature[] signatures) {
|
public static boolean isSignatureMatch(Signature[] signatures,
|
||||||
|
List<HashSet<Signature>> sigSets) {
|
||||||
if (signatures == null) return false;
|
if (signatures == null) return false;
|
||||||
|
|
||||||
// build hashset of input to test against
|
// build hashset of input to test against
|
||||||
@@ -184,7 +191,7 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// test input against each of the signature sets
|
// test input against each of the signature sets
|
||||||
for (HashSet<Signature> referenceSet : mSignatureSets) {
|
for (HashSet<Signature> referenceSet : sigSets) {
|
||||||
if (referenceSet.equals(inputSet)) {
|
if (referenceSet.equals(inputSet)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -192,6 +199,10 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSignatureMatch(Signature[] signatures) {
|
||||||
|
return isSignatureMatch(signatures, mSignatureSets);
|
||||||
|
}
|
||||||
|
|
||||||
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
||||||
/**
|
/**
|
||||||
* Called when package has been reinstalled
|
* Called when package has been reinstalled
|
||||||
|
|||||||
Reference in New Issue
Block a user