Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fbadb699 authored by Jeff Hamilton's avatar Jeff Hamilton
Browse files

Changes to support updating location providers.

This reverts commit 20de160c.

Bug: 7242814
Change-Id: I9ec49a14feb835b6683186fc6da4a74ae19fbae2
parent 0f2d0147
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -636,19 +636,12 @@
         of new location providers at run-time. The new package does not
         have to be explicitly listed here, however it must have a signature
         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">
        <!-- The standard AOSP fused location provider -->
        <item>com.android.location.fused</item>
    </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
    use cases -->
    <bool name="config_bluetooth_sco_off_call">true</bool>
+0 −1
Original line number Diff line number Diff line
@@ -1475,7 +1475,6 @@
  <java-symbol type="array" name="radioAttributes" />
  <java-symbol type="array" name="config_oemUsbModeOverride" />
  <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_automatic_brightness_available" />
  <java-symbol type="bool" name="config_sf_limitedAlpha" />
+3 −2
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        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_FINE_LOCATION" />
@@ -39,7 +40,7 @@
           <intent-filter>
               <action android:name="com.android.location.service.FusedLocationProvider" />
           </intent-filter>
           <meta-data android:name="version" android:value="1" />
           <meta-data android:name="serviceVersion" android:value="0" />
        </service>
    </application>
</manifest>
+77 −7
Original line number Diff line number Diff line
@@ -23,8 +23,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
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.database.ContentObserver;
import android.location.Address;
@@ -246,6 +249,74 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
        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() {
        // create a passive location provider, which is always enabled
        PassiveProvider passiveProvider = new PassiveProvider(this);
@@ -275,14 +346,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
        */
        Resources resources = mContext.getResources();
        ArrayList<String> providerPackageNames = new ArrayList<String>();
        String[] pkgs1 = resources.getStringArray(
        String[] pkgs = resources.getStringArray(
                com.android.internal.R.array.config_locationProviderPackageNames);
        String[] pkgs2 = resources.getStringArray(
                com.android.internal.R.array.config_overlay_locationProviderPackageNames);
        if (D) Log.d(TAG, "built-in location providers: " + Arrays.toString(pkgs1));
        if (D) Log.d(TAG, "overlay location providers: " + Arrays.toString(pkgs2));
        if (pkgs1 != null) providerPackageNames.addAll(Arrays.asList(pkgs1));
        if (pkgs2 != null) providerPackageNames.addAll(Arrays.asList(pkgs2));
        if (D) Log.d(TAG, "certificates for location providers pulled from: " +
                Arrays.toString(pkgs));
        if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));

        ensureFallbackFusedProviderPresentLocked(providerPackageNames);

        // bind to network provider
        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
+31 −20
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ import java.util.List;
 */
public class ServiceWatcher implements ServiceConnection {
    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 Context mContext;
@@ -58,9 +58,27 @@ public class ServiceWatcher implements ServiceConnection {
    // all fields below synchronized on mLock
    private IBinder mBinder;   // connected service
    private String mPackageName;  // current best package
    private int mVersion;  // current best version
    private int mVersion = Integer.MIN_VALUE;  // current best version
    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,
            List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
        mContext = context;
@@ -71,20 +89,7 @@ public class ServiceWatcher implements ServiceConnection {
        mHandler = handler;
        mCurrentUserId = userId;

        mSignatureSets = new ArrayList<HashSet<Signature>>();
        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");
            }
        }

        mSignatureSets = getSignatureSets(context, initialPackageNames);
    }

    public boolean start() {
@@ -132,15 +137,16 @@ public class ServiceWatcher implements ServiceConnection {
            // check version
            int version = 0;
            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) {
                bestVersion = version;
                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 + ") "),
                rInfos.size(),
                (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);
    }

    private boolean isSignatureMatch(Signature[] signatures) {
    public static boolean isSignatureMatch(Signature[] signatures,
            List<HashSet<Signature>> sigSets) {
        if (signatures == null) return false;

        // build hashset of input to test against
@@ -184,7 +191,7 @@ public class ServiceWatcher implements ServiceConnection {
        }

        // test input against each of the signature sets
        for (HashSet<Signature> referenceSet : mSignatureSets) {
        for (HashSet<Signature> referenceSet : sigSets) {
            if (referenceSet.equals(inputSet)) {
                return true;
            }
@@ -192,6 +199,10 @@ public class ServiceWatcher implements ServiceConnection {
        return false;
    }

    private boolean isSignatureMatch(Signature[] signatures) {
        return isSignatureMatch(signatures, mSignatureSets);
    }

    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
        /**
         * Called when package has been reinstalled