/*
 * Copyright (C) 2016 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.internal.telephony;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.Registrant;
import android.os.RegistrantList;
import android.provider.Settings;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.util.LocalLog;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;

/**
 * Carrier Action Agent(CAA) paired with
 * {@link com.android.internal.telephony.CarrierSignalAgent CarrierSignalAgent},
 * serves as an agent to dispatch carrier actions from carrier apps to different telephony modules,
 * {@link android.telephony.TelephonyManager#carrierActionSetRadioEnabled(int, boolean)
 * carrierActionSetRadioEnabled} for example.
 *
 * CAA supports dynamic registration where different telephony modules could listen for a specific
 * carrier action event and implement their own handler. CCA will dispatch the event to all
 * interested parties and maintain the received action states internally for future inspection.
 * Each CarrierActionAgent is associated with a phone object.
 */
public class CarrierActionAgent extends Handler {
    private static final String LOG_TAG = "CarrierActionAgent";
    private static final boolean DBG = true;
    private static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE);

    /** A list of carrier actions */
    public static final int CARRIER_ACTION_SET_METERED_APNS_ENABLED        = 0;
    public static final int CARRIER_ACTION_SET_RADIO_ENABLED               = 1;
    public static final int CARRIER_ACTION_RESET                           = 2;
    public static final int CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS   = 3;
    public static final int EVENT_APM_SETTINGS_CHANGED                     = 4;
    public static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED             = 5;
    public static final int EVENT_DATA_ROAMING_OFF                         = 6;
    public static final int EVENT_SIM_STATE_CHANGED                        = 7;

    /** Member variables */
    private final Phone mPhone;
    /** registrant list per carrier action */
    private RegistrantList mMeteredApnEnableRegistrants = new RegistrantList();
    private RegistrantList mRadioEnableRegistrants = new RegistrantList();
    private RegistrantList mDefaultNetworkReportRegistrants = new RegistrantList();
    /** local log for carrier actions */
    private LocalLog mMeteredApnEnabledLog = new LocalLog(10);
    private LocalLog mRadioEnabledLog = new LocalLog(10);
    private LocalLog mReportDefaultNetworkStatusLog = new LocalLog(10);
    /** carrier actions */
    private Boolean mCarrierActionOnMeteredApnEnabled = true;
    private Boolean mCarrierActionOnRadioEnabled = true;
    private Boolean mCarrierActionReportDefaultNetworkStatus = false;
    /** content observer for APM change */
    private final SettingsObserver mSettingsObserver;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            final String iccState = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
            if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)){
                if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                    // ignore rebroadcast since carrier apps are direct boot aware.
                    return;
                }
                sendMessage(obtainMessage(EVENT_SIM_STATE_CHANGED, iccState));
            }
        }
    };

    /** Constructor */
    public CarrierActionAgent(Phone phone) {
        mPhone = phone;
        mPhone.getContext().registerReceiver(mReceiver,
                new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
        mSettingsObserver = new SettingsObserver(mPhone.getContext(), this);
        if (DBG) log("Creating CarrierActionAgent");
    }

    @Override
    public void handleMessage(Message msg) {
        // skip notification if the input carrier action is same as the current one.
        Boolean enabled = getCarrierActionEnabled(msg.what);
        if (enabled != null && enabled == (boolean) msg.obj) return;
        switch (msg.what) {
            case CARRIER_ACTION_SET_METERED_APNS_ENABLED:
                mCarrierActionOnMeteredApnEnabled = (boolean) msg.obj;
                log("SET_METERED_APNS_ENABLED: " + mCarrierActionOnMeteredApnEnabled);
                mMeteredApnEnabledLog.log("SET_METERED_APNS_ENABLED: "
                        + mCarrierActionOnMeteredApnEnabled);
                mMeteredApnEnableRegistrants.notifyRegistrants(
                        new AsyncResult(null, mCarrierActionOnMeteredApnEnabled, null));
                break;
            case CARRIER_ACTION_SET_RADIO_ENABLED:
                mCarrierActionOnRadioEnabled = (boolean) msg.obj;
                log("SET_RADIO_ENABLED: " + mCarrierActionOnRadioEnabled);
                mRadioEnabledLog.log("SET_RADIO_ENABLED: " + mCarrierActionOnRadioEnabled);
                mRadioEnableRegistrants.notifyRegistrants(
                        new AsyncResult(null, mCarrierActionOnRadioEnabled, null));
                break;
            case CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS:
                mCarrierActionReportDefaultNetworkStatus = (boolean) msg.obj;
                log("CARRIER_ACTION_REPORT_AT_DEFAULT_NETWORK_STATUS: "
                        + mCarrierActionReportDefaultNetworkStatus);
                mReportDefaultNetworkStatusLog.log("REGISTER_DEFAULT_NETWORK_STATUS: "
                        + mCarrierActionReportDefaultNetworkStatus);
                mDefaultNetworkReportRegistrants.notifyRegistrants(
                        new AsyncResult(null, mCarrierActionReportDefaultNetworkStatus, null));
                break;
            case CARRIER_ACTION_RESET:
                log("CARRIER_ACTION_RESET");
                carrierActionReset();
                break;
            case EVENT_APM_SETTINGS_CHANGED:
                log("EVENT_APM_SETTINGS_CHANGED");
                if ((Settings.Global.getInt(mPhone.getContext().getContentResolver(),
                        Settings.Global.AIRPLANE_MODE_ON, 0) != 0)) {
                    carrierActionReset();
                }
                break;
            case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
                log("EVENT_MOBILE_DATA_SETTINGS_CHANGED");
                if (!mPhone.getDataEnabled()) carrierActionReset();
                break;
            case EVENT_DATA_ROAMING_OFF:
                log("EVENT_DATA_ROAMING_OFF");
                // reset carrier actions when exit roaming state.
                carrierActionReset();
                break;
            case EVENT_SIM_STATE_CHANGED:
                String iccState = (String) msg.obj;
                if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(iccState)) {
                    log("EVENT_SIM_STATE_CHANGED status: " + iccState);
                    carrierActionReset();
                    String mobileData = Settings.Global.MOBILE_DATA;
                    if (TelephonyManager.getDefault().getSimCount() != 1) {
                        mobileData = mobileData + mPhone.getSubId();
                    }
                    mSettingsObserver.observe(Settings.Global.getUriFor(mobileData),
                            EVENT_MOBILE_DATA_SETTINGS_CHANGED);
                    mSettingsObserver.observe(
                            Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
                            EVENT_APM_SETTINGS_CHANGED);
                    if (mPhone.getServiceStateTracker() != null) {
                        mPhone.getServiceStateTracker().registerForDataRoamingOff(
                                this, EVENT_DATA_ROAMING_OFF, null, false);
                    }
                } else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(iccState)) {
                    log("EVENT_SIM_STATE_CHANGED status: " + iccState);
                    carrierActionReset();
                    mSettingsObserver.unobserve();
                    if (mPhone.getServiceStateTracker() != null) {
                        mPhone.getServiceStateTracker().unregisterForDataRoamingOff(this);
                    }
                }
                break;
            default:
                loge("Unknown carrier action: " + msg.what);
        }
    }

    /**
     * Action set from carrier app to enable/disable radio
     */
    public void carrierActionSetRadioEnabled(boolean enabled) {
        sendMessage(obtainMessage(CARRIER_ACTION_SET_RADIO_ENABLED, enabled));
    }

    /**
     * Action set from carrier app to enable/disable metered APNs
     */
    public void carrierActionSetMeteredApnsEnabled(boolean enabled) {
        sendMessage(obtainMessage(CARRIER_ACTION_SET_METERED_APNS_ENABLED, enabled));
    }

    /**
     * Action set from carrier app to start/stop reporting default network status.
     */
    public void carrierActionReportDefaultNetworkStatus(boolean report) {
        sendMessage(obtainMessage(CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS, report));
    }

    private void carrierActionReset() {
        carrierActionReportDefaultNetworkStatus(false);
        carrierActionSetMeteredApnsEnabled(true);
        carrierActionSetRadioEnabled(true);
        // notify configured carrier apps for reset
        mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(
                new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET));
    }

    private RegistrantList getRegistrantsFromAction(int action) {
        switch (action) {
            case CARRIER_ACTION_SET_METERED_APNS_ENABLED:
                return mMeteredApnEnableRegistrants;
            case CARRIER_ACTION_SET_RADIO_ENABLED:
                return mRadioEnableRegistrants;
            case CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS:
                return mDefaultNetworkReportRegistrants;
            default:
                loge("Unsupported action: " + action);
                return null;
        }
    }

    private Boolean getCarrierActionEnabled(int action) {
        switch (action) {
            case CARRIER_ACTION_SET_METERED_APNS_ENABLED:
                return mCarrierActionOnMeteredApnEnabled;
            case CARRIER_ACTION_SET_RADIO_ENABLED:
                return mCarrierActionOnRadioEnabled;
            case CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS:
                return mCarrierActionReportDefaultNetworkStatus;
            default:
                loge("Unsupported action: " + action);
                return null;
        }
    }

    /**
     * Register with CAA for a specific event.
     * @param action which carrier action registrant is interested in
     * @param notifyNow if carrier action has once set, notify registrant right after
     *                  registering, so that registrants will get the latest carrier action.
     */
    public void registerForCarrierAction(int action, Handler h, int what, Object obj,
                                         boolean notifyNow) {
        Boolean carrierAction = getCarrierActionEnabled(action);
        if (carrierAction == null) {
            throw new IllegalArgumentException("invalid carrier action: " + action);
        }
        RegistrantList list = getRegistrantsFromAction(action);
        Registrant r = new Registrant(h, what, obj);
        list.add(r);
        if (notifyNow) {
            r.notifyRegistrant(new AsyncResult(null, carrierAction, null));
        }
    }

    /**
     * Unregister with CAA for a specific event. Callers will no longer be notified upon such event.
     * @param action which carrier action caller is no longer interested in
     */
    public void unregisterForCarrierAction(Handler h, int action) {
        RegistrantList list = getRegistrantsFromAction(action);
        if (list == null) {
            throw new IllegalArgumentException("invalid carrier action: " + action);
        }
        list.remove(h);
    }

    @VisibleForTesting
    public ContentObserver getContentObserver() {
        return mSettingsObserver;
    }

    private void log(String s) {
        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }

    private void loge(String s) {
        Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }

    private void logv(String s) {
        Rlog.v(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
        pw.println(" mCarrierActionOnMeteredApnsEnabled Log:");
        ipw.increaseIndent();
        mMeteredApnEnabledLog.dump(fd, ipw, args);
        ipw.decreaseIndent();

        pw.println(" mCarrierActionOnRadioEnabled Log:");
        ipw.increaseIndent();
        mRadioEnabledLog.dump(fd, ipw, args);
        ipw.decreaseIndent();

        pw.println(" mCarrierActionReportDefaultNetworkStatus Log:");
        ipw.increaseIndent();
        mReportDefaultNetworkStatusLog.dump(fd, ipw, args);
        ipw.decreaseIndent();
    }
}
