/*
 * Copyright (C) 2010 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.location.provider;

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintWriter;

import android.content.Context;
import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.WorkSource;
import android.util.Log;

import com.android.internal.location.ILocationProvider;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.util.FastPrintWriter;

/**
 * Base class for location providers implemented as unbundled services.
 *
 * <p>The network location provider must export a service with action
 * "com.android.location.service.v2.NetworkLocationProvider"
 * and a valid minor version in a meta-data field on the service, and
 * then return the result of {@link #getBinder()} on service binding.
 *
 * <p>The fused location provider must export a service with action
 * "com.android.location.service.FusedLocationProvider"
 * and a valid minor version in a meta-data field on the service, and
 * then return the result of {@link #getBinder()} on service binding.
 *
 * <p>IMPORTANT: This class is effectively a public API for unbundled
 * applications, and must remain API stable. See README.txt in the root
 * of this package for more information.
 */
public abstract class LocationProviderBase {
    private final String TAG;

    protected final ILocationManager mLocationManager;
    private final ProviderProperties mProperties;
    private final IBinder mBinder;

    /**
     * Bundle key for a version of the location containing no GPS data.
     * Allows location providers to flag locations as being safe to
     * feed to LocationFudger.
     */
    public static final String EXTRA_NO_GPS_LOCATION = Location.EXTRA_NO_GPS_LOCATION;

    /**
     * Name of the Fused location provider.
     *
     * <p>This provider combines inputs for all possible location sources
     * to provide the best possible Location fix.
     */
    public static final String FUSED_PROVIDER = LocationManager.FUSED_PROVIDER;

    private final class Service extends ILocationProvider.Stub {
        @Override
        public void enable() {
            onEnable();
        }
        @Override
        public void disable() {
            onDisable();
        }
        @Override
        public void setRequest(ProviderRequest request, WorkSource ws) {
            onSetRequest(new ProviderRequestUnbundled(request), ws);
        }
        @Override
        public ProviderProperties getProperties() {
            return mProperties;
        }
        @Override
        public int getStatus(Bundle extras) {
            return onGetStatus(extras);
        }
        @Override
        public long getStatusUpdateTime() {
            return onGetStatusUpdateTime();
        }
        @Override
        public boolean sendExtraCommand(String command, Bundle extras) {
            return onSendExtraCommand(command, extras);
        }
        @Override
        public void dump(FileDescriptor fd, String[] args) {
            PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
            onDump(fd, pw, args);
            pw.flush();
        }
    }

    public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) {
        TAG = tag;
        IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
        mLocationManager = ILocationManager.Stub.asInterface(b);
        mProperties = properties.getProviderProperties();
        mBinder = new Service();
    }

    public IBinder getBinder() {
        return mBinder;
    }

    /**
     * Used by the location provider to report new locations.
     *
     * @param location new Location to report
     *
     * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission.
     */
    public final void reportLocation(Location location) {
        try {
            mLocationManager.reportLocation(location, false);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException", e);
        } catch (Exception e) {
            // never crash provider, might be running in a system process
            Log.e(TAG, "Exception", e);
        }
    }

    /**
     * Enable the location provider.
     * <p>The provider may initialize resources, but does
     * not yet need to report locations.
     */
    public abstract void onEnable();

    /**
     * Disable the location provider.
     * <p>The provider must release resources, and stop
     * performing work. It may no longer report locations.
     */
    public abstract void onDisable();

    /**
     * Set the {@link ProviderRequest} requirements for this provider.
     * <p>Each call to this method overrides all previous requests.
     * <p>This method might trigger the provider to start returning
     * locations, or to stop returning locations, depending on the
     * parameters in the request.
     */
    public abstract void onSetRequest(ProviderRequestUnbundled request, WorkSource source);

    /**
     * Dump debug information.
     */
    public void onDump(FileDescriptor fd, PrintWriter pw, String[] args) {
    }

    /**
     * Returns a information on the status of this provider.
     * <p>{@link android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is
     * out of service, and this is not expected to change in the near
     * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if
     * the provider is temporarily unavailable but is expected to be
     * available shortly; and {@link android.location.LocationProvider#AVAILABLE} is returned
     * if the provider is currently available.
     *
     * <p>If extras is non-null, additional status information may be
     * added to it in the form of provider-specific key/value pairs.
     */
    public abstract int onGetStatus(Bundle extras);

    /**
     * Returns the time at which the status was last updated. It is the
     * responsibility of the provider to appropriately set this value using
     * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()}.
     * there is a status update that it wishes to broadcast to all its
     * listeners. The provider should be careful not to broadcast
     * the same status again.
     *
     * @return time of last status update in millis since last reboot
     */
    public abstract long onGetStatusUpdateTime();

    /**
     * Implements addditional location provider specific additional commands.
     *
     * @param command name of the command to send to the provider.
     * @param extras optional arguments for the command (or null).
     * The provider may optionally fill the extras Bundle with results from the command.
     *
     * @return true if the command succeeds.
     */
    public boolean onSendExtraCommand(String command, Bundle extras) {
        // default implementation
        return false;
    }
}
