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

Commit 080df3f3 authored by Victoria Lease's avatar Victoria Lease Committed by Android (Google) Code Review
Browse files

Merge "dual-mode switching single/multiuser ServiceWatcher"

parents 2d6ef862 03cdd3d2
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,5 @@ LOCAL_JAVA_LIBRARIES := com.android.location.provider


LOCAL_PACKAGE_NAME := FusedLocation
LOCAL_PACKAGE_NAME := FusedLocation
LOCAL_CERTIFICATE := platform
LOCAL_CERTIFICATE := platform
LOCAL_SDK_VERSION := current


include $(BUILD_PACKAGE)
include $(BUILD_PACKAGE)
+6 −2
Original line number Original line Diff line number Diff line
@@ -18,14 +18,17 @@
-->
-->
<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" />
    <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
    <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />


    <application
    <application
            android:label="@string/app_label">
            android:label="@string/app_label"
            android:process="system">


        <uses-library android:name="com.android.location.provider" />
        <uses-library android:name="com.android.location.provider" />


@@ -39,6 +42,7 @@
               <action android:name="com.android.location.service.FusedLocationProvider" />
               <action android:name="com.android.location.service.FusedLocationProvider" />
           </intent-filter>
           </intent-filter>
           <meta-data android:name="serviceVersion" android:value="0" />
           <meta-data android:name="serviceVersion" android:value="0" />
           <meta-data android:name="serviceIsMultiuser" android:value="true" />
        </service>
        </service>
    </application>
    </application>
</manifest>
</manifest>
+17 −0
Original line number Original line Diff line number Diff line
@@ -24,13 +24,17 @@ import com.android.location.provider.LocationProviderBase;
import com.android.location.provider.ProviderPropertiesUnbundled;
import com.android.location.provider.ProviderPropertiesUnbundled;
import com.android.location.provider.ProviderRequestUnbundled;
import com.android.location.provider.ProviderRequestUnbundled;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Criteria;
import android.location.Criteria;
import android.location.LocationProvider;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.Looper;
import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource;


public class FusedLocationProvider extends LocationProviderBase implements FusionEngine.Callback {
public class FusedLocationProvider extends LocationProviderBase implements FusionEngine.Callback {
@@ -60,6 +64,19 @@ public class FusedLocationProvider extends LocationProviderBase implements Fusio
        super(TAG, PROPERTIES);
        super(TAG, PROPERTIES);
        mContext = context;
        mContext = context;
        mEngine = new FusionEngine(context, Looper.myLooper());
        mEngine = new FusionEngine(context, Looper.myLooper());

        // listen for user change
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
        mContext.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                    mEngine.switchUser();
                }
            }
        }, UserHandle.ALL, intentFilter, null, mHandler);
    }
    }


    /**
    /**
+8 −0
Original line number Original line Diff line number Diff line
@@ -300,4 +300,12 @@ public class FusionEngine implements LocationListener {
        s.append("    ").append(mStats.get(NETWORK)).append('\n');
        s.append("    ").append(mStats.get(NETWORK)).append('\n');
        pw.append(s);
        pw.append(s);
    }
    }

    /** Called on mLooper thread */
    public void switchUser() {
        // reset state to prevent location data leakage
        mFusedLocation = null;
        mGpsLocation = null;
        mNetworkLocation = null;
    }
}
}
+46 −21
Original line number Original line Diff line number Diff line
@@ -365,7 +365,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                mContext,
                mContext,
                LocationManager.NETWORK_PROVIDER,
                LocationManager.NETWORK_PROVIDER,
                NETWORK_LOCATION_SERVICE_ACTION,
                NETWORK_LOCATION_SERVICE_ACTION,
                providerPackageNames, mLocationHandler, mCurrentUserId);
                providerPackageNames, mLocationHandler);
        if (networkProvider != null) {
        if (networkProvider != null) {
            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
            mProxyProviders.add(networkProvider);
            mProxyProviders.add(networkProvider);
@@ -379,7 +379,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                mContext,
                mContext,
                LocationManager.FUSED_PROVIDER,
                LocationManager.FUSED_PROVIDER,
                FUSED_LOCATION_SERVICE_ACTION,
                FUSED_LOCATION_SERVICE_ACTION,
                providerPackageNames, mLocationHandler, mCurrentUserId);
                providerPackageNames, mLocationHandler);
        if (fusedLocationProvider != null) {
        if (fusedLocationProvider != null) {
            addProviderLocked(fusedLocationProvider);
            addProviderLocked(fusedLocationProvider);
            mProxyProviders.add(fusedLocationProvider);
            mProxyProviders.add(fusedLocationProvider);
@@ -392,7 +392,7 @@ public class LocationManagerService extends ILocationManager.Stub {


        // bind to geocoder provider
        // bind to geocoder provider
        mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
        mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
                mLocationHandler, mCurrentUserId);
                mLocationHandler);
        if (mGeocodeProvider == null) {
        if (mGeocodeProvider == null) {
            Slog.e(TAG,  "no geocoder provider found");
            Slog.e(TAG,  "no geocoder provider found");
        }
        }
@@ -404,11 +404,11 @@ public class LocationManagerService extends ILocationManager.Stub {
     */
     */
    private void switchUser(int userId) {
    private void switchUser(int userId) {
        mBlacklist.switchUser(userId);
        mBlacklist.switchUser(userId);
        mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
        synchronized (mLock) {
        synchronized (mLock) {
            mLastLocation.clear();
            mLastLocation.clear();
            for (LocationProviderInterface p : mProviders) {
            for (LocationProviderInterface p : mProviders) {
                updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
                updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
                p.switchUser(userId);
            }
            }
            mCurrentUserId = userId;
            mCurrentUserId = userId;
            updateProvidersLocked();
            updateProvidersLocked();
@@ -668,8 +668,17 @@ public class LocationManagerService extends ILocationManager.Stub {
    }
    }




    private boolean isAllowedBySettingsLocked(String provider, int userId) {
    /**
        if (userId != mCurrentUserId) {
     * Returns "true" if access to the specified location provider is allowed by the current user's
     * settings. Access to all location providers is forbidden to non-location-provider processes
     * belonging to background users.
     *
     * @param provider the name of the location provider
     * @param uid the requestor's UID
     * @return
     */
    private boolean isAllowedBySettingsLocked(String provider, int uid) {
        if (UserHandle.getUserId(uid) != mCurrentUserId && !isUidALocationProvider(uid)) {
            return false;
            return false;
        }
        }
        if (mEnabledProviders.contains(provider)) {
        if (mEnabledProviders.contains(provider)) {
@@ -862,7 +871,7 @@ public class LocationManagerService extends ILocationManager.Stub {
    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
        ArrayList<String> out;
        ArrayList<String> out;
        int callingUserId = UserHandle.getCallingUserId();
        int uid = Binder.getCallingUid();;
        long identity = Binder.clearCallingIdentity();
        long identity = Binder.clearCallingIdentity();
        try {
        try {
            synchronized (mLock) {
            synchronized (mLock) {
@@ -873,7 +882,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                        continue;
                        continue;
                    }
                    }
                    if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
                    if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
                        if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
                        if (enabledOnly && !isAllowedBySettingsLocked(name, uid)) {
                            continue;
                            continue;
                        }
                        }
                        if (criteria != null && !LocationProvider.propertiesMeetCriteria(
                        if (criteria != null && !LocationProvider.propertiesMeetCriteria(
@@ -949,7 +958,8 @@ public class LocationManagerService extends ILocationManager.Stub {
            LocationProviderInterface p = mProviders.get(i);
            LocationProviderInterface p = mProviders.get(i);
            boolean isEnabled = p.isEnabled();
            boolean isEnabled = p.isEnabled();
            String name = p.getName();
            String name = p.getName();
            boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
            boolean shouldBeEnabled = isAllowedBySettingsLocked(name,
                    UserHandle.getUid(mCurrentUserId, 0));
            if (isEnabled && !shouldBeEnabled) {
            if (isEnabled && !shouldBeEnabled) {
                updateProviderListenersLocked(name, false, mCurrentUserId);
                updateProviderListenersLocked(name, false, mCurrentUserId);
                changesMade = true;
                changesMade = true;
@@ -1260,7 +1270,7 @@ public class LocationManagerService extends ILocationManager.Stub {
            oldRecord.disposeLocked(false);
            oldRecord.disposeLocked(false);
        }
        }


        boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
        boolean isProviderEnabled = isAllowedBySettingsLocked(name, uid);
        if (isProviderEnabled) {
        if (isProviderEnabled) {
            applyRequirementsLocked(name);
            applyRequirementsLocked(name);
        } else {
        } else {
@@ -1317,7 +1327,7 @@ public class LocationManagerService extends ILocationManager.Stub {
        // update provider
        // update provider
        for (String provider : providers) {
        for (String provider : providers) {
            // If provider is already disabled, don't need to do anything
            // If provider is already disabled, don't need to do anything
            if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
            if (!isAllowedBySettingsLocked(provider, UserHandle.getUid(mCurrentUserId, 0))) {
                continue;
                continue;
            }
            }


@@ -1358,7 +1368,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                LocationProviderInterface provider = mProvidersByName.get(name);
                LocationProviderInterface provider = mProvidersByName.get(name);
                if (provider == null) return null;
                if (provider == null) return null;


                if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
                if (!isAllowedBySettingsLocked(name, uid)) return null;


                Location location = mLastLocation.get(name);
                Location location = mLastLocation.get(name);
                if (location == null) {
                if (location == null) {
@@ -1538,13 +1548,32 @@ public class LocationManagerService extends ILocationManager.Stub {
                LocationProviderInterface p = mProvidersByName.get(provider);
                LocationProviderInterface p = mProvidersByName.get(provider);
                if (p == null) return false;
                if (p == null) return false;


                return isAllowedBySettingsLocked(provider, mCurrentUserId);
                return isAllowedBySettingsLocked(provider, UserHandle.getUid(mCurrentUserId, 0));
            }
            }
        } finally {
        } finally {
            Binder.restoreCallingIdentity(identity);
            Binder.restoreCallingIdentity(identity);
        }
        }
    }
    }


    /**
     * Returns "true" if the UID belongs to a bound location provider.
     *
     * @param uid the uid
     * @return true if uid belongs to a bound location provider
     */
    private boolean isUidALocationProvider(int uid) {
        if (uid == Process.SYSTEM_UID) {
            return true;
        }
        if (mGeocodeProvider != null) {
            if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return true;
        }
        for (LocationProviderProxy proxy : mProxyProviders) {
            if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return true;
        }
        return false;
    }

    private void checkCallerIsProvider() {
    private void checkCallerIsProvider() {
        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
                == PackageManager.PERMISSION_GRANTED) {
                == PackageManager.PERMISSION_GRANTED) {
@@ -1558,14 +1587,10 @@ public class LocationManagerService extends ILocationManager.Stub {
        // also allow providers with a UID matching the
        // also allow providers with a UID matching the
        // currently bound package name
        // currently bound package name


        int uid = Binder.getCallingUid();
        if (isUidALocationProvider(Binder.getCallingUid())) {

            return;
        if (mGeocodeProvider != null) {
            if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return;
        }
        for (LocationProviderProxy proxy : mProxyProviders) {
            if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return;
        }
        }

        throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
        throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
                "or UID of a currently bound location provider");
                "or UID of a currently bound location provider");
    }
    }
@@ -1817,7 +1842,7 @@ public class LocationManagerService extends ILocationManager.Stub {
        }
        }


        synchronized (mLock) {
        synchronized (mLock) {
            if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
            if (isAllowedBySettingsLocked(provider, UserHandle.getUid(mCurrentUserId, 0))) {
                handleLocationChangedLocked(myLocation, passive);
                handleLocationChangedLocked(myLocation, passive);
            }
            }
        }
        }
Loading