/*
 * Copyright (C) 2020 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.geofence;

import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.KEY_PROXIMITY_ENTERING;

import static com.android.server.location.LocationPermissions.PERMISSION_FINE;

import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.location.Geofence;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.location.util.identity.CallerIdentity;
import android.os.Binder;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.WorkSource;
import android.stats.location.LocationStatsEnums;
import android.util.ArraySet;

import com.android.internal.annotations.GuardedBy;
import com.android.server.FgThread;
import com.android.server.PendingIntentUtils;
import com.android.server.location.LocationPermissions;
import com.android.server.location.injector.Injector;
import com.android.server.location.injector.LocationPermissionsHelper;
import com.android.server.location.injector.LocationUsageLogger;
import com.android.server.location.injector.SettingsHelper;
import com.android.server.location.injector.UserInfoHelper;
import com.android.server.location.injector.UserInfoHelper.UserListener;
import com.android.server.location.listeners.ListenerMultiplexer;
import com.android.server.location.listeners.PendingIntentListenerRegistration;

import java.util.Collection;
import java.util.Objects;

/**
 * Manages all geofences.
 */
public class GeofenceManager extends
        ListenerMultiplexer<GeofenceManager.GeofenceKey, PendingIntent,
                GeofenceManager.GeofenceRegistration, LocationRequest> implements
        LocationListener {

    private static final String TAG = "GeofenceManager";

    private static final String ATTRIBUTION_TAG = "GeofencingService";

    private static final long WAKELOCK_TIMEOUT_MS = 30000;

    private static final int MAX_SPEED_M_S = 100;  // 360 km/hr (high speed train)
    private static final long MAX_LOCATION_AGE_MS = 5 * 60 * 1000L; // five minutes
    private static final long MAX_LOCATION_INTERVAL_MS = 2 * 60 * 60 * 1000; // two hours

    // geofencing unfortunately allows multiple geofences under the same pending intent, even though
    // this makes no real sense. therefore we manufacture an artificial key to use (pendingintent +
    // geofence) instead of (pendingintent).
    static class GeofenceKey {

        private final PendingIntent mPendingIntent;
        private final Geofence mGeofence;

        GeofenceKey(PendingIntent pendingIntent, Geofence geofence) {
            mPendingIntent = Objects.requireNonNull(pendingIntent);
            mGeofence = Objects.requireNonNull(geofence);
        }

        public PendingIntent getPendingIntent() {
            return mPendingIntent;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof GeofenceKey) {
                GeofenceKey that = (GeofenceKey) o;
                return mPendingIntent.equals(that.mPendingIntent) && mGeofence.equals(
                        that.mGeofence);
            }

            return false;
        }

        @Override
        public int hashCode() {
            return mPendingIntent.hashCode();
        }
    }

    protected class GeofenceRegistration extends
            PendingIntentListenerRegistration<GeofenceKey, PendingIntent> {

        private static final int STATE_UNKNOWN = 0;
        private static final int STATE_INSIDE = 1;
        private static final int STATE_OUTSIDE = 2;

        private final Geofence mGeofence;
        private final CallerIdentity mIdentity;
        private final Location mCenter;
        private final PowerManager.WakeLock mWakeLock;

        private int mGeofenceState;

        // we store these values because we don't trust the listeners not to give us dupes, not to
        // spam us, and because checking the values may be more expensive
        private boolean mPermitted;

        @Nullable private Location mCachedLocation;
        private float mCachedLocationDistanceM;

        GeofenceRegistration(Geofence geofence, CallerIdentity identity,
                PendingIntent pendingIntent) {
            super(pendingIntent);

            mGeofence = geofence;
            mIdentity = identity;
            mCenter = new Location("");
            mCenter.setLatitude(geofence.getLatitude());
            mCenter.setLongitude(geofence.getLongitude());

            mWakeLock = Objects.requireNonNull(mContext.getSystemService(PowerManager.class))
                    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                            TAG + ":" + identity.getPackageName());
            mWakeLock.setReferenceCounted(true);
            mWakeLock.setWorkSource(identity.addToWorkSource(null));
        }

        public Geofence getGeofence() {
            return mGeofence;
        }

        public CallerIdentity getIdentity() {
            return mIdentity;
        }

        @Override
        public String getTag() {
            return TAG;
        }

        @Override
        protected PendingIntent getPendingIntentFromKey(GeofenceKey geofenceKey) {
            return geofenceKey.getPendingIntent();
        }

        @Override
        protected GeofenceManager getOwner() {
            return GeofenceManager.this;
        }

        @Override
        protected void onRegister() {
            super.onRegister();

            mGeofenceState = STATE_UNKNOWN;
            mPermitted = mLocationPermissionsHelper.hasLocationPermissions(PERMISSION_FINE,
                    mIdentity);
        }

        @Override
        protected void onActive() {
            Location location = getLastLocation();
            if (location != null) {
                executeOperation(onLocationChanged(location));
            }
        }

        boolean isPermitted() {
            return mPermitted;
        }

        boolean onLocationPermissionsChanged(@Nullable String packageName) {
            if (packageName == null || mIdentity.getPackageName().equals(packageName)) {
                return onLocationPermissionsChanged();
            }

            return false;
        }

        boolean onLocationPermissionsChanged(int uid) {
            if (mIdentity.getUid() == uid) {
                return onLocationPermissionsChanged();
            }

            return false;
        }

        private boolean onLocationPermissionsChanged() {
            boolean permitted = mLocationPermissionsHelper.hasLocationPermissions(PERMISSION_FINE,
                    mIdentity);
            if (permitted != mPermitted) {
                mPermitted = permitted;
                return true;
            }

            return false;
        }

        double getDistanceToBoundary(Location location) {
            if (!location.equals(mCachedLocation)) {
                mCachedLocation = location;
                mCachedLocationDistanceM = mCenter.distanceTo(mCachedLocation);
            }

            return Math.abs(mGeofence.getRadius() - mCachedLocationDistanceM);
        }

        ListenerOperation<PendingIntent> onLocationChanged(Location location) {
            // remove expired fences
            if (mGeofence.isExpired()) {
                remove();
                return null;
            }

            mCachedLocation = location;
            mCachedLocationDistanceM = mCenter.distanceTo(mCachedLocation);

            int oldState = mGeofenceState;
            float radius = Math.max(mGeofence.getRadius(), location.getAccuracy());
            if (mCachedLocationDistanceM <= radius) {
                mGeofenceState = STATE_INSIDE;
                if (oldState != STATE_INSIDE) {
                    return pendingIntent -> sendIntent(pendingIntent, true);
                }
            } else {
                mGeofenceState = STATE_OUTSIDE;
                if (oldState == STATE_INSIDE) {
                    // return exit only if previously entered
                    return pendingIntent -> sendIntent(pendingIntent, false);
                }
            }

            return null;
        }

        private void sendIntent(PendingIntent pendingIntent, boolean entering) {
            Intent intent = new Intent().putExtra(KEY_PROXIMITY_ENTERING, entering);

            mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
            try {
                // send() only enforces permissions for broadcast intents, but since clients can
                // select any kind of pending intent we do not rely on send() to enforce permissions
                pendingIntent.send(mContext, 0, intent, (pI, i, rC, rD, rE) -> mWakeLock.release(),
                        null, null, PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
            } catch (PendingIntent.CanceledException e) {
                mWakeLock.release();
                removeRegistration(new GeofenceKey(pendingIntent, mGeofence), this);
            }
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append(mIdentity);

            ArraySet<String> flags = new ArraySet<>(1);
            if (!mPermitted) {
                flags.add("na");
            }
            if (!flags.isEmpty()) {
                builder.append(" ").append(flags);
            }

            builder.append(" ").append(mGeofence);
            return builder.toString();
        }
    }

    final Object mLock = new Object();

    protected final Context mContext;

    private final UserListener mUserChangedListener = this::onUserChanged;
    private final SettingsHelper.UserSettingChangedListener mLocationEnabledChangedListener =
            this::onLocationEnabledChanged;
    private final SettingsHelper.UserSettingChangedListener
            mLocationPackageBlacklistChangedListener =
            this::onLocationPackageBlacklistChanged;
    private final LocationPermissionsHelper.LocationPermissionsListener
            mLocationPermissionsListener =
            new LocationPermissionsHelper.LocationPermissionsListener() {
                @Override
                public void onLocationPermissionsChanged(@Nullable String packageName) {
                    GeofenceManager.this.onLocationPermissionsChanged(packageName);
                }

                @Override
                public void onLocationPermissionsChanged(int uid) {
                    GeofenceManager.this.onLocationPermissionsChanged(uid);
                }
            };

    protected final UserInfoHelper mUserInfoHelper;
    protected final LocationPermissionsHelper mLocationPermissionsHelper;
    protected final SettingsHelper mSettingsHelper;
    protected final LocationUsageLogger mLocationUsageLogger;

    @GuardedBy("mLock")
    @Nullable private LocationManager mLocationManager;

    @GuardedBy("mLock")
    @Nullable private Location mLastLocation;

    public GeofenceManager(Context context, Injector injector) {
        mContext = context.createAttributionContext(ATTRIBUTION_TAG);
        mUserInfoHelper = injector.getUserInfoHelper();
        mSettingsHelper = injector.getSettingsHelper();
        mLocationPermissionsHelper = injector.getLocationPermissionsHelper();
        mLocationUsageLogger = injector.getLocationUsageLogger();
    }

    private LocationManager getLocationManager() {
        synchronized (mLock) {
            if (mLocationManager == null) {
                mLocationManager = Objects.requireNonNull(
                        mContext.getSystemService(LocationManager.class));
            }

            return mLocationManager;
        }
    }

    /**
     * Adds a new geofence, replacing any geofence already associated with the PendingIntent. It
     * doesn't make any real sense to register multiple geofences with the same pending intent, but
     * we continue to allow this for backwards compatibility.
     */
    public void addGeofence(Geofence geofence, PendingIntent pendingIntent, String packageName,
            @Nullable String attributionTag) {
        LocationPermissions.enforceCallingOrSelfLocationPermission(mContext, PERMISSION_FINE);

        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName,
                attributionTag, AppOpsManager.toReceiverId(pendingIntent));

        final long ident = Binder.clearCallingIdentity();
        try {
            putRegistration(new GeofenceKey(pendingIntent, geofence),
                    new GeofenceRegistration(geofence, identity, pendingIntent));
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    /**
     * Removes the geofence associated with the PendingIntent.
     */
    public void removeGeofence(PendingIntent pendingIntent) {
        final long identity = Binder.clearCallingIdentity();
        try {
            removeRegistrationIf(key -> key.getPendingIntent().equals(pendingIntent));
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    protected boolean isActive(GeofenceRegistration registration) {
        return registration.isPermitted() && isActive(registration.getIdentity());
    }

    private boolean isActive(CallerIdentity identity) {
        if (identity.isSystemServer()) {
            if (!mSettingsHelper.isLocationEnabled(mUserInfoHelper.getCurrentUserId())) {
                return false;
            }
        } else {
            if (!mSettingsHelper.isLocationEnabled(identity.getUserId())) {
                return false;
            }
            if (!mUserInfoHelper.isVisibleUserId(identity.getUserId())) {
                return false;
            }
            if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
                    identity.getPackageName())) {
                return false;
            }
        }

        return true;
    }

    @Override
    protected void onRegister() {
        mUserInfoHelper.addListener(mUserChangedListener);
        mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
        mSettingsHelper.addOnLocationPackageBlacklistChangedListener(
                mLocationPackageBlacklistChangedListener);
        mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
    }

    @Override
    protected void onUnregister() {
        mUserInfoHelper.removeListener(mUserChangedListener);
        mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
        mSettingsHelper.removeOnLocationPackageBlacklistChangedListener(
                mLocationPackageBlacklistChangedListener);
        mLocationPermissionsHelper.removeListener(mLocationPermissionsListener);
    }

    @Override
    protected void onRegistrationAdded(GeofenceKey key, GeofenceRegistration registration) {
        mLocationUsageLogger.logLocationApiUsage(
                LocationStatsEnums.USAGE_ENDED,
                LocationStatsEnums.API_REQUEST_GEOFENCE,
                registration.getIdentity().getPackageName(),
                registration.getIdentity().getAttributionTag(),
                null,
                /* LocationRequest= */ null,
                /* hasListener= */ false,
                true,
                registration.getGeofence(), true);
    }

    @Override
    protected void onRegistrationRemoved(GeofenceKey key, GeofenceRegistration registration) {
        mLocationUsageLogger.logLocationApiUsage(
                LocationStatsEnums.USAGE_ENDED,
                LocationStatsEnums.API_REQUEST_GEOFENCE,
                registration.getIdentity().getPackageName(),
                registration.getIdentity().getAttributionTag(),
                null,
                /* LocationRequest= */ null,
                /* hasListener= */ false,
                true,
                registration.getGeofence(), true);
    }

    @Override
    protected boolean registerWithService(LocationRequest locationRequest,
            Collection<GeofenceRegistration> registrations) {
        getLocationManager().requestLocationUpdates(FUSED_PROVIDER, locationRequest,
                FgThread.getExecutor(), this);
        return true;
    }

    @Override
    protected void unregisterWithService() {
        synchronized (mLock) {
            getLocationManager().removeUpdates(this);
            mLastLocation = null;
        }
    }

    @Override
    protected LocationRequest mergeRegistrations(Collection<GeofenceRegistration> registrations) {
        Location location = getLastLocation();

        long realtimeMs = SystemClock.elapsedRealtime();

        WorkSource workSource = null;
        double minFenceDistanceM = Double.MAX_VALUE;
        for (GeofenceRegistration registration : registrations) {
            if (registration.getGeofence().isExpired(realtimeMs)) {
                continue;
            }

            workSource = registration.getIdentity().addToWorkSource(workSource);

            if (location != null) {
                double fenceDistanceM = registration.getDistanceToBoundary(location);
                if (fenceDistanceM < minFenceDistanceM) {
                    minFenceDistanceM = fenceDistanceM;
                }
            }
        }

        long intervalMs;
        if (Double.compare(minFenceDistanceM, Double.MAX_VALUE) < 0) {
            intervalMs = (long) Math.min(MAX_LOCATION_INTERVAL_MS,
                    Math.max(
                            mSettingsHelper.getBackgroundThrottleProximityAlertIntervalMs(),
                            minFenceDistanceM * 1000 / MAX_SPEED_M_S));
        } else {
            intervalMs = mSettingsHelper.getBackgroundThrottleProximityAlertIntervalMs();
        }

        return new LocationRequest.Builder(intervalMs)
                .setMinUpdateIntervalMillis(0)
                .setHiddenFromAppOps(true)
                .setWorkSource(workSource)
                .build();
    }


    @Override
    public void onLocationChanged(Location location) {
        synchronized (mLock) {
            mLastLocation = location;
        }

        deliverToListeners(registration -> {
            return registration.onLocationChanged(location);
        });
        updateService();
    }

    @Nullable Location getLastLocation() {
        Location location;
        synchronized (mLock) {
            location = mLastLocation;
        }

        if (location == null) {
            location = getLocationManager().getLastLocation();
        }

        if (location != null) {
            if (location.getElapsedRealtimeAgeMillis() > MAX_LOCATION_AGE_MS) {
                location = null;
            }
        }

        return location;
    }

    void onUserChanged(int userId, int change) {
        // current user changes affect whether system server location requests are allowed to access
        // location, and visibility changes affect whether any given user may access location.
        if (change == UserListener.CURRENT_USER_CHANGED
                || change == UserListener.USER_VISIBILITY_CHANGED) {
            updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
        }
    }

    void onLocationEnabledChanged(int userId) {
        updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
    }

    void onLocationPackageBlacklistChanged(int userId) {
        updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
    }

    void onLocationPermissionsChanged(@Nullable String packageName) {
        updateRegistrations(registration -> registration.onLocationPermissionsChanged(packageName));
    }

    void onLocationPermissionsChanged(int uid) {
        updateRegistrations(registration -> registration.onLocationPermissionsChanged(uid));
    }
}
