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

Commit 480f5dae authored by Nate Myren's avatar Nate Myren Committed by Android (Google) Code Review
Browse files

Merge "Observe location changes" into rvc-dev

parents 46e333d1 37a81de5
Loading
Loading
Loading
Loading
+32 −6
Original line number Diff line number Diff line
@@ -51,13 +51,18 @@ class AppPermGroupUiInfoLiveData private constructor(
    private val packageName: String,
    private val permGroupName: String,
    private val user: UserHandle
) : SmartUpdateMediatorLiveData<AppPermGroupUiInfo>() {
) : SmartUpdateMediatorLiveData<AppPermGroupUiInfo>(), LocationUtils.LocationListener {

    private var isSpecialLocation = false
    private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
    private val permGroupLiveData = PermGroupLiveData[permGroupName]
    private val permissionStateLiveData = PermStateLiveData[packageName, permGroupName, user]

    init {
        isSpecialLocation = LocationUtils.isLocationGroupAndProvider(app,
            permGroupName, packageName) ||
            LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)

        addSource(packageInfoLiveData) {
            updateIfActive()
        }
@@ -157,7 +162,7 @@ class AppPermGroupUiInfoLiveData private constructor(
        }

        if (groupInfo.packageName == Utils.OS_PKG &&
            !Utils.isModernPermissionGroup(groupInfo.name)) {
            !isModernPermissionGroup(groupInfo.name)) {
            return false
        }
        return true
@@ -212,6 +217,7 @@ class AppPermGroupUiInfoLiveData private constructor(
        allPermInfos: Map<String, LightPermInfo>,
        packageName: String
    ): PermGrantState {
        val specialLocationState = getIsSpecialLocationState()

        var hasPermWithBackground = false
        var isUserFixed = false
@@ -220,7 +226,8 @@ class AppPermGroupUiInfoLiveData private constructor(
            val permInfo = allPermInfos[permName] ?: continue
            permInfo.backgroundPermission?.let { backgroundPerm ->
                hasPermWithBackground = true
                if (permissionState[backgroundPerm]?.granted == true) {
                if (permissionState[backgroundPerm]?.granted == true &&
                    specialLocationState != false) {
                    return PermGrantState.PERMS_ALLOWED_ALWAYS
                }
            }
@@ -230,7 +237,7 @@ class AppPermGroupUiInfoLiveData private constructor(
                    permState.permFlags and PackageManager.FLAG_PERMISSION_ONE_TIME != 0
        }

        val anyAllowed = getIsSpecialLocationState() ?: permissionState.any { it.value.granted }
        val anyAllowed = specialLocationState ?: permissionState.any { it.value.granted }
        if (anyAllowed && (hasPermWithBackground || shouldShowAsForegroundGroup())) {
            if (isOneTime) {
                return PermGrantState.PERMS_ASK
@@ -259,8 +266,7 @@ class AppPermGroupUiInfoLiveData private constructor(

    private fun getIsSpecialLocationState(): Boolean? {
        val userContext = Utils.getUserContext(app, user)
        if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName,
                packageName)) {
        if (isSpecialLocation) {
            return LocationUtils.isLocationEnabled(userContext)
        }
        // The permission of the extra location controller package is determined by the
@@ -278,6 +284,26 @@ class AppPermGroupUiInfoLiveData private constructor(
                permGroupName.equals(Manifest.permission_group.MICROPHONE)
    }

    override fun onLocationStateChange(enabled: Boolean) {
        updateIfActive()
    }

    override fun onActive() {
        super.onActive()

        if (isSpecialLocation) {
            LocationUtils.addLocationListener(this)
        }
    }

    override fun onInactive() {
        super.onInactive()

        if (isSpecialLocation) {
            LocationUtils.removeLocationListener(this)
        }
    }

    /**
     * Repository for AppPermGroupUiInfoLiveDatas.
     * <p> Key value is a triple of string package name, string permission group name, and UserHandle,
+27 −3
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightAppP
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission
import com.android.permissioncontroller.permission.utils.LocationUtils
import com.android.permissioncontroller.permission.utils.SoftRestrictedPermissionPolicy
import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.permission.utils.Utils.OS_PKG

@@ -45,16 +44,21 @@ class LightAppPermGroupLiveData private constructor(
    private val packageName: String,
    private val permGroupName: String,
    private val user: UserHandle
) : SmartUpdateMediatorLiveData<LightAppPermGroup?>() {
) : SmartUpdateMediatorLiveData<LightAppPermGroup?>(), LocationUtils.LocationListener {

    val LOG_TAG = this::class.java.simpleName

    private var isSpecialLocation = false
    private val permStateLiveData = PermStateLiveData[packageName, permGroupName, user]
    private val permGroupLiveData = PermGroupLiveData[permGroupName]
    private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
    private val fgPermNamesLiveData = ForegroundPermNamesLiveData

    init {
        isSpecialLocation = LocationUtils.isLocationGroupAndProvider(app,
            permGroupName, packageName) ||
            LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName)

        addSource(fgPermNamesLiveData) {
            updateIfActive()
        }
@@ -113,7 +117,7 @@ class LightAppPermGroupLiveData private constructor(
        // Determine if this app permission group is a special location package or provider
        var specialLocationGrant: Boolean? = null
        val userContext = Utils.getUserContext(app, user)
        if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)) {
        if (isSpecialLocation) {
            specialLocationGrant = LocationUtils.isLocationEnabled(app)
        }
        // The permission of the extra location controller package is determined by the status of
@@ -172,6 +176,26 @@ class LightAppPermGroupLiveData private constructor(
        return false
    }

    override fun onLocationStateChange(enabled: Boolean) {
        updateIfActive()
    }

    override fun onActive() {
        super.onActive()

        if (isSpecialLocation) {
            LocationUtils.addLocationListener(this)
        }
    }

    override fun onInactive() {
        super.onInactive()

        if (isSpecialLocation) {
            LocationUtils.removeLocationListener(this)
        }
    }

    /**
     * Repository for AppPermGroupLiveDatas.
     * <p> Key value is a triple of string package name, string permission group name, and
+69 −0
Original line number Diff line number Diff line
@@ -15,13 +15,17 @@
 */
package com.android.permissioncontroller.permission.utils;

import static android.location.LocationManager.EXTRA_LOCATION_ENABLED;

import android.Manifest;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -29,8 +33,11 @@ import android.util.Log;

import androidx.annotation.NonNull;

import com.android.permissioncontroller.PermissionControllerApplication;
import com.android.permissioncontroller.R;

import java.util.ArrayList;

public class LocationUtils {

    public static final String LOCATION_PERMISSION = Manifest.permission_group.LOCATION;
@@ -94,4 +101,66 @@ public class LocationUtils {
        }

    }

    /**
     * A Listener which responds to enabling or disabling of location on the device
     */
    public interface LocationListener {

        /**
         * A callback run any time we receive a broadcast stating the location enable state has
         * changed.
         * @param enabled Whether or not location is enabled
         */
        void onLocationStateChange(boolean enabled);
    }

    private static final ArrayList<LocationListener> sLocationListeners = new ArrayList<>();

    private static BroadcastReceiver sLocationBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            boolean isEnabled = intent.getBooleanExtra(EXTRA_LOCATION_ENABLED, true);
            synchronized (sLocationListeners) {
                for (LocationListener l: sLocationListeners) {
                    l.onLocationStateChange(isEnabled);
                }
            }
        }
    };

    /**
     * Add a LocationListener, which will be notified if the location provider is enabled or
     * disabled
     * @param listener the listener to add
     */
    public static void addLocationListener(LocationListener listener) {
        synchronized (sLocationListeners) {
            boolean wasEmpty = sLocationListeners.isEmpty();
            sLocationListeners.add(listener);
            if (wasEmpty) {
                IntentFilter intentFilter = new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
                PermissionControllerApplication.get().getApplicationContext()
                        .registerReceiverForAllUsers(sLocationBroadcastReceiver, intentFilter,
                                null, null);
            }
        }
    }

    /**
     * Remove a LocationListener
     * @param listener The listener to remove
     *
     * @return True if it was successfully removed, false otherwise
     */
    public static boolean removeLocationListener(LocationListener listener) {
        synchronized (sLocationListeners) {
            boolean success = sLocationListeners.remove(listener);
            if (success && sLocationListeners.isEmpty()) {
                PermissionControllerApplication.get().getApplicationContext()
                        .unregisterReceiver(sLocationBroadcastReceiver);
            }
            return success;
        }
    }
}