/*
 * 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.internal.telephony;

import android.compat.annotation.UnsupportedAppUsage;

import com.android.telephony.Rlog;

/**
 * Utilities that check if the phone supports specified capabilities.
 */
public class TelephonyCapabilities {
    private static final String LOG_TAG = "TelephonyCapabilities";

    /** This class is never instantiated. */
    private TelephonyCapabilities() {
    }

    /**
     * Return true if the current phone supports ECM ("Emergency Callback
     * Mode"), which is a feature where the device goes into a special
     * state for a short period of time after making an outgoing emergency
     * call.
     *
     * (On current devices, that state lasts 5 minutes.  It prevents data
     * usage by other apps, to avoid conflicts with any possible incoming
     * calls.  It also puts up a notification in the status bar, showing a
     * countdown while ECM is active, and allowing the user to exit ECM.)
     *
     * Currently this is assumed to be true for CDMA phones, and false
     * otherwise.
     */
    public static boolean supportsEcm(Phone phone) {
        Rlog.d(LOG_TAG, "supportsEcm: Phone type = " + phone.getPhoneType() +
                  " Ims Phone = " + phone.getImsPhone());
        return (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||
                phone.getImsPhone() != null);
    }

    /**
     * Return true if the current phone supports Over The Air Service
     * Provisioning (OTASP)
     *
     * Currently this is assumed to be true for CDMA phones, and false
     * otherwise.
     *
     * TODO: Watch out: this is also highly carrier-specific, since the
     * OTASP procedure is different from one carrier to the next, *and* the
     * different carriers may want very different onscreen UI as well.
     * The procedure may even be different for different devices with the
     * same carrier.
     *
     * So we eventually will need a much more flexible, pluggable design.
     * This method here is just a placeholder to reduce hardcoded
     * "if (CDMA)" checks sprinkled throughout the phone app.
     */
    public static boolean supportsOtasp(Phone phone) {
        return (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA);
    }

    /**
     * Return true if the current phone supports voice message count.
     * and the count is available
     * Both CDMA and GSM phones support voice message count
     */
    public static boolean supportsVoiceMessageCount(Phone phone) {
        return (phone.getVoiceMessageCount() != -1);
    }

    /**
     * Return true if this phone allows the user to select which
     * network to use.
     *
     * Currently this is assumed to be true only on GSM phones.
     *
     * TODO: Should CDMA phones allow this as well?
     */
    public static boolean supportsNetworkSelection(Phone phone) {
        return (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM);
    }

    /**
     * Returns a resource ID for a label to use when displaying the
     * "device id" of the current device.  (This is currently used as the
     * title of the "device id" dialog.)
     *
     * This is specific to the device's telephony technology: the device
     * id is called "IMEI" on GSM phones and "MEID" on CDMA phones.
     */
    public static int getDeviceIdLabel(Phone phone) {
        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
            return com.android.internal.R.string.imei;
        } else if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
            return com.android.internal.R.string.meid;
        } else {
            Rlog.w(LOG_TAG, "getDeviceIdLabel: no known label for phone "
                  + phone.getPhoneName());
            return 0;
        }
    }

    /**
     * Return true if the current phone supports the ability to explicitly
     * manage the state of a conference call (i.e. view the participants,
     * and hangup or separate individual callers.)
     *
     * The in-call screen's "Manage conference" UI is available only on
     * devices that support this feature.
     *
     * Currently this is assumed to be true on GSM phones and false otherwise.
     */
    public static boolean supportsConferenceCallManagement(Phone phone) {
        return ((phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM)
                || (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_SIP));
    }

    /**
     * Return true if the current phone supports explicit "Hold" and
     * "Unhold" actions for an active call.  (If so, the in-call UI will
     * provide onscreen "Hold" / "Unhold" buttons.)
     *
     * Currently this is assumed to be true on GSM phones and false
     * otherwise.  (In particular, CDMA has no concept of "putting a call
     * on hold.")
     */
    public static boolean supportsHoldAndUnhold(Phone phone) {
        return ((phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM)
                || (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_SIP)
                || (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS));
    }

    /**
     * Return true if the current phone supports distinct "Answer & Hold"
     * and "Answer & End" behaviors in the call-waiting scenario.  If so,
     * the in-call UI may provide separate buttons or menu items for these
     * two actions.
     *
     * Currently this is assumed to be true on GSM phones and false
     * otherwise.  (In particular, CDMA has no concept of explicitly
     * managing the background call, or "putting a call on hold.")
     *
     * TODO: It might be better to expose this capability in a more
     * generic form, like maybe "supportsExplicitMultipleLineManagement()"
     * rather than focusing specifically on call-waiting behavior.
     */
    public static boolean supportsAnswerAndHold(Phone phone) {
        return ((phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM)
                || (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_SIP));
    }

    /**
     * Return true if phones with the given phone type support ADN
     * (Abbreviated Dialing Numbers).
     *
     * Currently this returns true when the phone type is GSM
     * ({@link PhoneConstants#PHONE_TYPE_GSM}).
     *
     * This is using int for an argument for letting apps outside
     * Phone process access to it, while other methods in this class is
     * using Phone object.
     *
     * TODO: Theoretically phones other than GSM may have the ADN capability.
     * Consider having better check here, or have better capability as part
     * of public API, with which the argument should be replaced with
     * something more appropriate.
     */
    @UnsupportedAppUsage
    public static boolean supportsAdn(int phoneType) {
        return phoneType == PhoneConstants.PHONE_TYPE_GSM;
    }

    /**
     * Returns true if the device can distinguish the phone's dialing state
     * (Call.State.DIALING/ALERTING) and connected state (Call.State.ACTIVE).
     *
     * Currently this returns true for GSM phones as we cannot know when a CDMA
     * phone has transitioned from dialing/active to connected.
     */
    public static boolean canDistinguishDialingAndConnected(int phoneType) {
        return phoneType == PhoneConstants.PHONE_TYPE_GSM;
    }
}
