/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.location;

import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.FrameworkStatsLog;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Handles GNSS non-framework location access user visibility and control.
 *
 * The state of the GnssVisibilityControl object must be accessed/modified through the Handler
 * thread only.
 */
class GnssVisibilityControl {
    private static final String TAG = "GnssVisibilityControl";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private static final String LOCATION_PERMISSION_NAME =
            "android.permission.ACCESS_FINE_LOCATION";

    private static final String[] NO_LOCATION_ENABLED_PROXY_APPS = new String[0];

    // Max wait time for synchronous method onGpsEnabledChanged() to run.
    private static final long ON_GPS_ENABLED_CHANGED_TIMEOUT_MILLIS = 3 * 1000;

    // How long to display location icon for each non-framework non-emergency location request.
    private static final long LOCATION_ICON_DISPLAY_DURATION_MILLIS = 5 * 1000;

    // Wakelocks
    private static final String WAKELOCK_KEY = TAG;
    private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
    private final PowerManager.WakeLock mWakeLock;

    private final AppOpsManager mAppOps;
    private final PackageManager mPackageManager;

    private final Handler mHandler;
    private final Context mContext;
    private final GpsNetInitiatedHandler mNiHandler;

    private boolean mIsGpsEnabled;

    private static final class ProxyAppState {
        private boolean mHasLocationPermission;
        private boolean mIsLocationIconOn;

        private ProxyAppState(boolean hasLocationPermission) {
            mHasLocationPermission = hasLocationPermission;
        }
    }

    // Number of non-framework location access proxy apps is expected to be small (< 5).
    private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE = 5;
    private ArrayMap<String, ProxyAppState> mProxyAppsState = new ArrayMap<>(
            ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE);

    private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
            uid -> runOnHandler(() -> handlePermissionsChanged(uid));

    GnssVisibilityControl(Context context, Looper looper, GpsNetInitiatedHandler niHandler) {
        mContext = context;
        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
        mHandler = new Handler(looper);
        mNiHandler = niHandler;
        mAppOps = mContext.getSystemService(AppOpsManager.class);
        mPackageManager = mContext.getPackageManager();

        // Complete initialization as the first event to run in mHandler thread. After that,
        // all object state read/update events run in the mHandler thread.
        runOnHandler(this::handleInitialize);
    }

    void onGpsEnabledChanged(boolean isEnabled) {
        // The GnssLocationProvider's methods: handleEnable() calls this method after native_init()
        // and handleDisable() calls this method before native_cleanup(). This method must be
        // executed synchronously so that the NFW location access permissions are disabled in
        // the HAL before native_cleanup() method is called.
        //
        // NOTE: Since improper use of runWithScissors() method can result in deadlocks, the method
        // doc recommends limiting its use to cases where some initialization steps need to be
        // executed in sequence before continuing which fits this scenario.
        if (mHandler.runWithScissors(() -> handleGpsEnabledChanged(isEnabled),
                ON_GPS_ENABLED_CHANGED_TIMEOUT_MILLIS)) {
            return;
        }

        // After timeout, the method remains posted in the queue and hence future enable/disable
        // calls to this method will all get executed in the correct sequence. But this timeout
        // situation should not even arise because runWithScissors() will run in the caller's
        // thread without blocking as it is the same thread as mHandler's thread.
        if (!isEnabled) {
            Log.w(TAG, "Native call to disable non-framework location access in GNSS HAL may"
                    + " get executed after native_cleanup().");
        }
    }

    void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
            String otherProtocolStackName, byte requestor, String requestorId, byte responseType,
            boolean inEmergencyMode, boolean isCachedLocation) {
        runOnHandler(() -> handleNfwNotification(
                new NfwNotification(proxyAppPackageName, protocolStack, otherProtocolStackName,
                        requestor, requestorId, responseType, inEmergencyMode, isCachedLocation)));
    }

    void onConfigurationUpdated(GnssConfiguration configuration) {
        // The configuration object must be accessed only in the caller thread and not in mHandler.
        List<String> nfwLocationAccessProxyApps = configuration.getProxyApps();
        runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
    }

    private void handleInitialize() {
        listenForProxyAppsPackageUpdates();
    }

    private void listenForProxyAppsPackageUpdates() {
        // Listen for proxy apps package installation, removal events.
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        intentFilter.addDataScheme("package");
        mContext.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (action == null) {
                    return;
                }

                switch (action) {
                    case Intent.ACTION_PACKAGE_ADDED:
                    case Intent.ACTION_PACKAGE_REMOVED:
                    case Intent.ACTION_PACKAGE_REPLACED:
                    case Intent.ACTION_PACKAGE_CHANGED:
                        String pkgName = intent.getData().getEncodedSchemeSpecificPart();
                        handleProxyAppPackageUpdate(pkgName, action);
                        break;
                }
            }
        }, UserHandle.ALL, intentFilter, null, mHandler);
    }

    private void handleProxyAppPackageUpdate(String pkgName, String action) {
        final ProxyAppState proxyAppState = mProxyAppsState.get(pkgName);
        if (proxyAppState == null) {
            return; // ignore, pkgName is not one of the proxy apps in our list.
        }

        if (DEBUG) Log.d(TAG, "Proxy app " + pkgName + " package changed: " + action);
        final boolean updatedLocationPermission = shouldEnableLocationPermissionInGnssHal(pkgName);
        if (proxyAppState.mHasLocationPermission != updatedLocationPermission) {
            // Permission changed. So, update the GNSS HAL with the updated list.
            Log.i(TAG, "Proxy app " + pkgName + " location permission changed."
                    + " IsLocationPermissionEnabled: " + updatedLocationPermission);
            proxyAppState.mHasLocationPermission = updatedLocationPermission;
            updateNfwLocationAccessProxyAppsInGnssHal();
        }
    }

    private void handleUpdateProxyApps(List<String> nfwLocationAccessProxyApps) {
        if (!isProxyAppListUpdated(nfwLocationAccessProxyApps)) {
            return;
        }

        if (nfwLocationAccessProxyApps.isEmpty()) {
            // Stop listening for app permission changes. Clear the app list in GNSS HAL.
            if (!mProxyAppsState.isEmpty()) {
                mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
                resetProxyAppsState();
                updateNfwLocationAccessProxyAppsInGnssHal();
            }
            return;
        }

        if (mProxyAppsState.isEmpty()) {
            mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
        } else {
            resetProxyAppsState();
        }

        for (String proxyAppPkgName : nfwLocationAccessProxyApps) {
            ProxyAppState proxyAppState = new ProxyAppState(shouldEnableLocationPermissionInGnssHal(
                    proxyAppPkgName));
            mProxyAppsState.put(proxyAppPkgName, proxyAppState);
        }

        updateNfwLocationAccessProxyAppsInGnssHal();
    }

    private void resetProxyAppsState() {
        // Clear location icons displayed.
        for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
            ProxyAppState proxyAppState = entry.getValue();
            if (!proxyAppState.mIsLocationIconOn) {
                continue;
            }

            mHandler.removeCallbacksAndMessages(proxyAppState);
            final ApplicationInfo proxyAppInfo = getProxyAppInfo(entry.getKey());
            if (proxyAppInfo != null) {
                clearLocationIcon(proxyAppState, proxyAppInfo.uid, entry.getKey());
            }
        }
        mProxyAppsState.clear();
    }

    private boolean isProxyAppListUpdated(List<String> nfwLocationAccessProxyApps) {
        if (nfwLocationAccessProxyApps.size() != mProxyAppsState.size()) {
            return true;
        }

        for (String nfwLocationAccessProxyApp : nfwLocationAccessProxyApps) {
            if (!mProxyAppsState.containsKey(nfwLocationAccessProxyApp)) {
                return true;
            }
        }
        return false;
    }

    private void handleGpsEnabledChanged(boolean isGpsEnabled) {
        if (DEBUG) {
            Log.d(TAG, "handleGpsEnabledChanged, mIsGpsEnabled: " + mIsGpsEnabled
                    + ", isGpsEnabled: " + isGpsEnabled);
        }

        // The proxy app list in the GNSS HAL needs to be configured if it restarts after
        // a crash. So, update HAL irrespective of the previous GPS enabled state.
        mIsGpsEnabled = isGpsEnabled;
        if (!mIsGpsEnabled) {
            disableNfwLocationAccess();
            return;
        }

        setNfwLocationAccessProxyAppsInGnssHal(getLocationPermissionEnabledProxyApps());
    }

    private void disableNfwLocationAccess() {
        setNfwLocationAccessProxyAppsInGnssHal(NO_LOCATION_ENABLED_PROXY_APPS);
    }

    // Represents NfwNotification structure in IGnssVisibilityControlCallback.hal
    private static class NfwNotification {
        // These must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
        private static final byte NFW_RESPONSE_TYPE_REJECTED = 0;
        private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
        private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;

        private final String mProxyAppPackageName;
        private final byte mProtocolStack;
        private final String mOtherProtocolStackName;
        private final byte mRequestor;
        private final String mRequestorId;
        private final byte mResponseType;
        private final boolean mInEmergencyMode;
        private final boolean mIsCachedLocation;

        private NfwNotification(String proxyAppPackageName, byte protocolStack,
                String otherProtocolStackName, byte requestor, String requestorId,
                byte responseType, boolean inEmergencyMode, boolean isCachedLocation) {
            mProxyAppPackageName = proxyAppPackageName;
            mProtocolStack = protocolStack;
            mOtherProtocolStackName = otherProtocolStackName;
            mRequestor = requestor;
            mRequestorId = requestorId;
            mResponseType = responseType;
            mInEmergencyMode = inEmergencyMode;
            mIsCachedLocation = isCachedLocation;
        }

        @SuppressLint("DefaultLocale")
        public String toString() {
            return String.format(
                    "{proxyAppPackageName: %s, protocolStack: %d, otherProtocolStackName: %s, "
                            + "requestor: %d, requestorId: %s, responseType: %s, inEmergencyMode:"
                            + " %b, isCachedLocation: %b}",
                    mProxyAppPackageName, mProtocolStack, mOtherProtocolStackName, mRequestor,
                    mRequestorId, getResponseTypeAsString(), mInEmergencyMode, mIsCachedLocation);
        }

        private String getResponseTypeAsString() {
            switch (mResponseType) {
                case NFW_RESPONSE_TYPE_REJECTED:
                    return "REJECTED";
                case NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED:
                    return "ACCEPTED_NO_LOCATION_PROVIDED";
                case NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED:
                    return "ACCEPTED_LOCATION_PROVIDED";
                default:
                    return "<Unknown>";
            }
        }

        private boolean isRequestAccepted() {
            return mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED;
        }

        private boolean isLocationProvided() {
            return mResponseType == NfwNotification.NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED;
        }

        private boolean isRequestAttributedToProxyApp() {
            return !TextUtils.isEmpty(mProxyAppPackageName);
        }

        private boolean isEmergencyRequestNotification() {
            return mInEmergencyMode && !isRequestAttributedToProxyApp();
        }
    }

    private void handlePermissionsChanged(int uid) {
        if (mProxyAppsState.isEmpty()) {
            return;
        }

        for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
            final String proxyAppPkgName = entry.getKey();
            final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
            if (proxyAppInfo == null || proxyAppInfo.uid != uid) {
                continue;
            }

            final boolean isLocationPermissionEnabled = shouldEnableLocationPermissionInGnssHal(
                    proxyAppPkgName);
            ProxyAppState proxyAppState = entry.getValue();
            if (isLocationPermissionEnabled != proxyAppState.mHasLocationPermission) {
                Log.i(TAG, "Proxy app " + proxyAppPkgName + " location permission changed."
                        + " IsLocationPermissionEnabled: " + isLocationPermissionEnabled);
                proxyAppState.mHasLocationPermission = isLocationPermissionEnabled;
                updateNfwLocationAccessProxyAppsInGnssHal();
            }
            return;
        }
    }

    private ApplicationInfo getProxyAppInfo(String proxyAppPkgName) {
        try {
            return mPackageManager.getApplicationInfo(proxyAppPkgName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            if (DEBUG) Log.d(TAG, "Proxy app " + proxyAppPkgName + " is not found.");
            return null;
        }
    }

    private boolean shouldEnableLocationPermissionInGnssHal(String proxyAppPkgName) {
        return isProxyAppInstalled(proxyAppPkgName) && hasLocationPermission(proxyAppPkgName);
    }

    private boolean isProxyAppInstalled(String pkgName) {
        ApplicationInfo proxyAppInfo = getProxyAppInfo(pkgName);
        return (proxyAppInfo != null) && proxyAppInfo.enabled;
    }

    private boolean hasLocationPermission(String pkgName) {
        return mPackageManager.checkPermission(LOCATION_PERMISSION_NAME, pkgName)
                == PackageManager.PERMISSION_GRANTED;
    }

    private void updateNfwLocationAccessProxyAppsInGnssHal() {
        if (!mIsGpsEnabled) {
            return; // Keep non-framework location access disabled.
        }
        setNfwLocationAccessProxyAppsInGnssHal(getLocationPermissionEnabledProxyApps());
    }

    private void setNfwLocationAccessProxyAppsInGnssHal(
            String[] locationPermissionEnabledProxyApps) {
        final String proxyAppsStr = Arrays.toString(locationPermissionEnabledProxyApps);
        Log.i(TAG, "Updating non-framework location access proxy apps in the GNSS HAL to: "
                + proxyAppsStr);
        boolean result = native_enable_nfw_location_access(locationPermissionEnabledProxyApps);
        if (!result) {
            Log.e(TAG, "Failed to update non-framework location access proxy apps in the"
                    + " GNSS HAL to: " + proxyAppsStr);
        }
    }

    private String[] getLocationPermissionEnabledProxyApps() {
        // Get a count of proxy apps with location permission enabled for array creation size.
        int countLocationPermissionEnabledProxyApps = 0;
        for (ProxyAppState proxyAppState : mProxyAppsState.values()) {
            if (proxyAppState.mHasLocationPermission) {
                ++countLocationPermissionEnabledProxyApps;
            }
        }

        int i = 0;
        String[] locationPermissionEnabledProxyApps =
                new String[countLocationPermissionEnabledProxyApps];
        for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
            final String proxyApp = entry.getKey();
            if (entry.getValue().mHasLocationPermission) {
                locationPermissionEnabledProxyApps[i++] = proxyApp;
            }
        }
        return locationPermissionEnabledProxyApps;
    }

    private void handleNfwNotification(NfwNotification nfwNotification) {
        if (DEBUG) Log.d(TAG, "Non-framework location access notification: " + nfwNotification);

        if (nfwNotification.isEmergencyRequestNotification()) {
            handleEmergencyNfwNotification(nfwNotification);
            return;
        }

        final String proxyAppPkgName = nfwNotification.mProxyAppPackageName;
        final ProxyAppState proxyAppState = mProxyAppsState.get(proxyAppPkgName);
        final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
        final boolean isPermissionMismatched = isPermissionMismatched(proxyAppState,
                nfwNotification);
        logEvent(nfwNotification, isPermissionMismatched);

        if (!nfwNotification.isRequestAttributedToProxyApp()) {
            // Handle cases where GNSS HAL implementation correctly rejected NFW location request.
            // 1. GNSS HAL implementation doesn't provide location to any NFW location use cases.
            //    There is no Location Attribution App configured in the framework.
            // 2. GNSS HAL implementation doesn't provide location to some NFW location use cases.
            //    Location Attribution Apps are configured only for the supported NFW location
            //    use cases. All other use cases which are not supported (and always rejected) by
            //    the GNSS HAL implementation will have proxyAppPackageName set to empty string.
            if (!isLocationRequestAccepted) {
                if (DEBUG) {
                    Log.d(TAG, "Non-framework location request rejected. ProxyAppPackageName field"
                            + " is not set in the notification: " + nfwNotification + ". Number of"
                            + " configured proxy apps: " + mProxyAppsState.size());
                }
                return;
            }

            Log.e(TAG, "ProxyAppPackageName field is not set. AppOps service not notified"
                    + " for notification: " + nfwNotification);
            return;
        }

        if (proxyAppState == null) {
            Log.w(TAG, "Could not find proxy app " + proxyAppPkgName + " in the value specified for"
                    + " config parameter: " + GnssConfiguration.CONFIG_NFW_PROXY_APPS
                    + ". AppOps service not notified for notification: " + nfwNotification);
            return;
        }

        // Display location icon attributed to this proxy app.
        final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
        if (proxyAppInfo == null) {
            Log.e(TAG, "Proxy app " + proxyAppPkgName + " is not found. AppOps service not "
                    + "notified for notification: " + nfwNotification);
            return;
        }

        if (nfwNotification.isLocationProvided()) {
            showLocationIcon(proxyAppState, nfwNotification, proxyAppInfo.uid, proxyAppPkgName);
            mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid,
                    proxyAppPkgName);
        }

        // Log proxy app permission mismatch between framework and GNSS HAL.
        if (isPermissionMismatched) {
            Log.w(TAG, "Permission mismatch. Proxy app " + proxyAppPkgName
                    + " location permission is set to " + proxyAppState.mHasLocationPermission
                    + " and GNSS HAL enabled is set to " + mIsGpsEnabled
                    + " but GNSS non-framework location access response type is "
                    + nfwNotification.getResponseTypeAsString() + " for notification: "
                    + nfwNotification);
        }
    }

    private boolean isPermissionMismatched(ProxyAppState proxyAppState,
            NfwNotification nfwNotification) {
        // Non-framework non-emergency location requests must be accepted only when IGnss.hal
        // is enabled and the proxy app has location permission.
        final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
        return (proxyAppState == null || !mIsGpsEnabled) ? isLocationRequestAccepted
                        : (proxyAppState.mHasLocationPermission != isLocationRequestAccepted);
    }

    private void showLocationIcon(ProxyAppState proxyAppState, NfwNotification nfwNotification,
            int uid, String proxyAppPkgName) {
        // If we receive a new NfwNotification before the location icon is turned off for the
        // previous notification, update the timer to extend the location icon display duration.
        final boolean isLocationIconOn = proxyAppState.mIsLocationIconOn;
        if (!isLocationIconOn) {
            if (!updateLocationIcon(/* displayLocationIcon = */ true, uid, proxyAppPkgName)) {
                Log.w(TAG, "Failed to show Location icon for notification: " + nfwNotification);
                return;
            }
            proxyAppState.mIsLocationIconOn = true;
        } else {
            // Extend timer by canceling the current one and starting a new one.
            mHandler.removeCallbacksAndMessages(proxyAppState);
        }

        // Start timer to turn off location icon. proxyAppState is used as a token to cancel timer.
        if (DEBUG) {
            Log.d(TAG, "Location icon on. " + (isLocationIconOn ? "Extending" : "Setting")
                    + " icon display timer. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
        }
        if (!mHandler.postDelayed(() -> handleLocationIconTimeout(proxyAppPkgName),
                /* token = */ proxyAppState, LOCATION_ICON_DISPLAY_DURATION_MILLIS)) {
            clearLocationIcon(proxyAppState, uid, proxyAppPkgName);
            Log.w(TAG, "Failed to show location icon for the full duration for notification: "
                    + nfwNotification);
        }
    }

    private void handleLocationIconTimeout(String proxyAppPkgName) {
        // Get uid again instead of using the one provided in startOp() call as the app could have
        // been uninstalled and reinstalled during the timeout duration (unlikely in real world).
        final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
        if (proxyAppInfo != null) {
            clearLocationIcon(mProxyAppsState.get(proxyAppPkgName), proxyAppInfo.uid,
                    proxyAppPkgName);
        }
    }

    private void clearLocationIcon(@Nullable ProxyAppState proxyAppState, int uid,
            String proxyAppPkgName) {
        updateLocationIcon(/* displayLocationIcon = */ false, uid, proxyAppPkgName);
        if (proxyAppState != null) proxyAppState.mIsLocationIconOn = false;
        if (DEBUG) {
            Log.d(TAG, "Location icon off. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
        }
    }

    private boolean updateLocationIcon(boolean displayLocationIcon, int uid,
            String proxyAppPkgName) {
        if (displayLocationIcon) {
            // Need two calls to startOp() here with different op code so that the proxy app shows
            // up in the recent location requests page and also the location icon gets displayed.
            if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, uid,
                    proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
                return false;
            }
            if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid,
                    proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
                mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
                return false;
            }
        } else {
            mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
            mAppOps.finishOp(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid, proxyAppPkgName);
        }
        sendHighPowerMonitoringBroadcast();
        return true;
    }

    private void sendHighPowerMonitoringBroadcast() {
        // Send an intent to notify that a high power request has been added/removed so that
        // the SystemUi checks the state of AppOps and updates the location icon accordingly.
        Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
    }

    private void handleEmergencyNfwNotification(NfwNotification nfwNotification) {
        boolean isPermissionMismatched = false;
        if (!nfwNotification.isRequestAccepted()) {
            Log.e(TAG, "Emergency non-framework location request incorrectly rejected."
                    + " Notification: " + nfwNotification);
            isPermissionMismatched = true;
        }

        if (!mNiHandler.getInEmergency()) {
            Log.w(TAG, "Emergency state mismatch. Device currently not in user initiated emergency"
                    + " session. Notification: " + nfwNotification);
            isPermissionMismatched = true;
        }

        logEvent(nfwNotification, isPermissionMismatched);

        if (nfwNotification.isLocationProvided()) {
            postEmergencyLocationUserNotification(nfwNotification);
        }
    }

    private void postEmergencyLocationUserNotification(NfwNotification nfwNotification) {
        // Emulate deprecated IGnssNi.hal user notification of emergency NI requests.
        NotificationManager notificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        if (notificationManager == null) {
            Log.w(TAG, "Could not notify user of emergency location request. Notification: "
                    + nfwNotification);
            return;
        }

        notificationManager.notifyAsUser(/* tag= */ null, /* notificationId= */ 0,
                createEmergencyLocationUserNotification(mContext), UserHandle.ALL);
    }

    private static Notification createEmergencyLocationUserNotification(Context context) {
        // NOTE: Do not reuse the returned notification object as it will not reflect
        //       changes to notification text when the system language is changed.
        final String firstLineText = context.getString(R.string.gpsNotifTitle);
        final String secondLineText =  context.getString(R.string.global_action_emergency);
        final String accessibilityServicesText = firstLineText + " (" + secondLineText + ")";
        return new Notification.Builder(context, SystemNotificationChannels.NETWORK_ALERTS)
                .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
                .setWhen(0)
                .setOngoing(false)
                .setAutoCancel(true)
                .setColor(context.getColor(
                        com.android.internal.R.color.system_notification_accent_color))
                .setDefaults(0)
                .setTicker(accessibilityServicesText)
                .setContentTitle(firstLineText)
                .setContentText(secondLineText)
                .setContentIntent(PendingIntent.getBroadcast(context, 0, new Intent(), 0))
                .build();
    }

    private void logEvent(NfwNotification notification, boolean isPermissionMismatched) {
        FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NFW_NOTIFICATION_REPORTED,
                notification.mProxyAppPackageName,
                notification.mProtocolStack,
                notification.mOtherProtocolStackName,
                notification.mRequestor,
                notification.mRequestorId,
                notification.mResponseType,
                notification.mInEmergencyMode,
                notification.mIsCachedLocation,
                isPermissionMismatched);
    }

    private void runOnHandler(Runnable event) {
        // Hold a wake lock until this message is delivered.
        // Note that this assumes the message will not be removed from the queue before
        // it is handled (otherwise the wake lock would be leaked).
        mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
        if (!mHandler.post(runEventAndReleaseWakeLock(event))) {
            mWakeLock.release();
        }
    }

    private Runnable runEventAndReleaseWakeLock(Runnable event) {
        return () -> {
            try {
                event.run();
            } finally {
                mWakeLock.release();
            }
        };
    }

    private native boolean native_enable_nfw_location_access(String[] proxyApps);
}
