content: /*
   * Copyright (C) 2018 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 android.telephony.ims;
  
  import android.annotation.IntDef;
  import android.annotation.NonNull;
  import android.annotation.Nullable;
  import android.annotation.SystemApi;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.telephony.Rlog;
  
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  
  /**
   * Provides STK Call Control Supplementary Service information.
   *
   * {@hide}
   */
  @SystemApi
  public final class ImsSsData implements Parcelable {
  
      private static final String TAG = ImsSsData.class.getCanonicalName();
  
      // Supplementary Service Type
      // Call Forwarding
      public static final int SS_CFU = 0;
      public static final int SS_CF_BUSY = 1;
      public static final int SS_CF_NO_REPLY = 2;
      public static final int SS_CF_NOT_REACHABLE = 3;
      public static final int SS_CF_ALL = 4;
      public static final int SS_CF_ALL_CONDITIONAL = 5;
      public static final int SS_CFUT = 6;
      // Called Line Presentation
      public static final int SS_CLIP = 7;
      public static final int SS_CLIR = 8;
      public static final int SS_COLP = 9;
      public static final int SS_COLR = 10;
      // Calling Name Presentation
      public static final int SS_CNAP = 11;
      // Call Waiting
      public static final int SS_WAIT = 12;
      // Call Barring
      public static final int SS_BAOC = 13;
      public static final int SS_BAOIC = 14;
      public static final int SS_BAOIC_EXC_HOME = 15;
      public static final int SS_BAIC = 16;
      public static final int SS_BAIC_ROAMING = 17;
      public static final int SS_ALL_BARRING = 18;
      public static final int SS_OUTGOING_BARRING = 19;
      public static final int SS_INCOMING_BARRING = 20;
      public static final int SS_INCOMING_BARRING_DN = 21;
      public static final int SS_INCOMING_BARRING_ANONYMOUS = 22;
  
  
      /**@hide*/
      @IntDef(flag = true, prefix = {"SS_"}, value = {
              SS_ACTIVATION,
              SS_DEACTIVATION,
              SS_INTERROGATION,
              SS_REGISTRATION,
              SS_ERASURE})
      @Retention(RetentionPolicy.SOURCE)
      public @interface RequestType{}
  
      //Supplementary Service Request Types
      public static final int SS_ACTIVATION = 0;
      public static final int SS_DEACTIVATION = 1;
      public static final int SS_INTERROGATION = 2;
      public static final int SS_REGISTRATION = 3;
      public static final int SS_ERASURE = 4;
  
      /**@hide*/
      @IntDef(flag = true, prefix = {"SS_"}, value = {
              SS_ALL_TELE_AND_BEARER_SERVICES,
              SS_ALL_TELESEVICES,
              SS_TELEPHONY,
              SS_ALL_DATA_TELESERVICES,
              SS_SMS_SERVICES,
              SS_ALL_TELESERVICES_EXCEPT_SMS})
      @Retention(RetentionPolicy.SOURCE)
      public @interface TeleserviceType{}
  
      // Supplementary Service Teleservice Type
      public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0;
      public static final int SS_ALL_TELESEVICES = 1;
      public static final int SS_TELEPHONY = 2;
      public static final int SS_ALL_DATA_TELESERVICES = 3;
      public static final int SS_SMS_SERVICES = 4;
      public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5;
  
      /**
       * No call forwarding service class defined.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_NONE = 0;
  
      /**
       * Service class flag for voice telephony.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_VOICE = 1;
  
      /**
       * Service class flag for all data bearers (including
       * {@link #SERVICE_CLASS_DATA_CIRCUIT_SYNC,
       * {@link #SERVICE_CLASS_DATA_CIRCUIT_ASYNC}, {@link #SERVICE_CLASS_PACKET_ACCESS},
       * {@link #SERVICE_CLASS_PAD}}) if supported by the carrier.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_DATA = (1 << 1);
      /**
       * Service class flag for fax services.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_FAX = (1 << 2);
      /**
       * Service class flag for SMS services.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_SMS = (1 << 3);
      /**
       * Service class flag for the synchronous bearer service.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = (1 << 4);
  
      /**
       * Service class flag for the asynchronous bearer service.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = (1 << 5);
  
      /**
       * Service class flag for the packet access bearer service.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = (1 << 6);
  
      /**
       * Service class flag for the Packet Assembly/Disassembly bearer service.
       *
       * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
       */
      public static final int SERVICE_CLASS_DATA_PAD = (1 << 7);
  
      /**@hide*/
      @IntDef(flag = true, prefix = {"SERVICE_CLASS_"}, value = {
              SERVICE_CLASS_NONE,
              SERVICE_CLASS_VOICE,
              SERVICE_CLASS_DATA,
              SERVICE_CLASS_FAX,
              SERVICE_CLASS_SMS,
              SERVICE_CLASS_DATA_CIRCUIT_SYNC,
              SERVICE_CLASS_DATA_CIRCUIT_ASYNC,
              SERVICE_CLASS_DATA_PACKET_ACCESS,
              SERVICE_CLASS_DATA_PAD})
      @Retention(RetentionPolicy.SOURCE)
      public @interface ServiceClassFlags{}
  
      /**
       * Result code used if the operation was successful. See {@link #getResult()}.
       */
      public static final int RESULT_SUCCESS = 0;
  
      /** @hide */
      @IntDef(flag = true, prefix = { "SS_" }, value = {
              SS_CFU,
              SS_CF_BUSY,
              SS_CF_NO_REPLY,
              SS_CF_NOT_REACHABLE,
              SS_CF_ALL,
              SS_CF_ALL_CONDITIONAL,
              SS_CFUT,
              SS_CLIP,
              SS_CLIR,
              SS_COLP,
              SS_COLR,
              SS_CNAP,
              SS_WAIT,
              SS_BAOC,
              SS_BAOIC,
              SS_BAOIC_EXC_HOME,
              SS_BAIC,
              SS_BAIC_ROAMING,
              SS_ALL_BARRING,
              SS_OUTGOING_BARRING,
              SS_INCOMING_BARRING,
              SS_INCOMING_BARRING_DN,
              SS_INCOMING_BARRING_ANONYMOUS
      })
      @Retention(RetentionPolicy.SOURCE)
      public @interface ServiceType{}
  
      /**
       * The Service type of this Supplementary service.
       * @hide
       */
      public final @ServiceType int serviceType;
  
      /**
       * Supplementary Service request Type:
       *     {@link #SS_ACTIVATION),
       *     {@link #SS_DEACTIVATION},
       *     {@link #SS_INTERROGATION},
       *     {@link #SS_REGISTRATION},
       *     {@link #SS_ERASURE}
       * @hide
       */
      public final @RequestType int requestType;
  
      /**
       * Supplementary Service teleservice type:
       *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
       *     {@link #SS_ALL_TELESEVICES},
       *     {@link #SS_TELEPHONY},
       *     {@link #SS_ALL_DATA_TELESERVICES},
       *     {@link #SS_SMS_SERVICES},
       *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
       *
       * @hide
       */
      public final @TeleserviceType int teleserviceType;
  
      /**
       * Supplementary Service service class.
       *
       * @hide
       */
      public final @ServiceClassFlags int serviceClass;
  
      /**
       * Result of Supplementary Service operation. Valid values are:
       *     {@link #RESULT_SUCCESS} if the result is success, or
       *     ImsReasonInfo code if the result is a failure.
       *
       * @hide
       */
      public final int result;
  
      private int[] mSsInfo;
      private List<ImsCallForwardInfo> mCfInfo;
      private List<ImsSsInfo> mImsSsInfo;
  
      /**
       * Builder for optional ImsSsData parameters.
       */
      public static final class Builder {
          private ImsSsData mImsSsData;
  
          /**
           * Generate IMS Supplementary Service information.
           * @param serviceType The Supplementary Service type.
           * @param requestType Supplementary Service request Type:
           *     {@link #SS_ACTIVATION},
           *     {@link #SS_DEACTIVATION},
           *     {@link #SS_INTERROGATION},
           *     {@link #SS_REGISTRATION},
           *     {@link #SS_ERASURE}
           * @param teleserviceType Supplementary Service teleservice type:
           *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
           *     {@link #SS_ALL_TELESEVICES},
           *     {@link #SS_TELEPHONY},
           *     {@link #SS_ALL_DATA_TELESERVICES},
           *     {@link #SS_SMS_SERVICES},
           *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
           * @param serviceClass Supplementary Service service class. See See 27.007 +CCFC or +CLCK.
           * @param result Result of Supplementary Service operation. Valid values are 0 if the result
           *               is success, or {@link ImsReasonInfo} code if the result is a failure.
           * @return this Builder instance for further constructing.
           * @see #build()
           */
          public Builder(@ServiceType int serviceType, int requestType, int teleserviceType,
                  @ServiceClassFlags int serviceClass, int result) {
              mImsSsData = new ImsSsData(serviceType, requestType, teleserviceType, serviceClass,
                      result);
          }
  
          /**
           * Set the array of {@link ImsSsInfo}s that are associated with this supplementary service
           * data.
           */
          public @NonNull Builder setSuppServiceInfo(@NonNull List<ImsSsInfo> imsSsInfos) {
              mImsSsData.mImsSsInfo = imsSsInfos;
              return this;
          }
  
          /**
           * Set the array of {@link ImsCallForwardInfo}s that are associated with this supplementary
           * service data.
           */
          public @NonNull Builder setCallForwardingInfo(
                  @NonNull List<ImsCallForwardInfo> imsCallForwardInfos) {
              mImsSsData.mCfInfo = imsCallForwardInfos;
              return this;
          }
  
          /**
           * @return an {@link ImsSsData} containing optional parameters.
           */
          public @NonNull ImsSsData build() {
              return mImsSsData;
          }
      }
  
      /**
       * Generate IMS Supplementary Service information.
       * @param serviceType The Supplementary Service type.
       * @param requestType Supplementary Service request Type. Valid values are:
       *     {@link #SS_ACTIVATION},
       *     {@link #SS_DEACTIVATION},
       *     {@link #SS_INTERROGATION},
       *     {@link #SS_REGISTRATION},
       *     {@link #SS_ERASURE}
       * @param teleserviceType Supplementary Service teleservice type:
       *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
       *     {@link #SS_ALL_TELESEVICES},
       *     {@link #SS_TELEPHONY},
       *     {@link #SS_ALL_DATA_TELESERVICES},
       *     {@link #SS_SMS_SERVICES},
       *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
       * @param serviceClass Supplementary Service service class. See See 27.007 +CCFC or +CLCK.
       * @param result Result of Supplementary Service operation. Valid values are 0 if the result is
       *               success, or ImsReasonInfo code if the result is a failure.
       */
      public ImsSsData(@ServiceType int serviceType, int requestType, int teleserviceType,
              @ServiceClassFlags int serviceClass, int result) {
          this.serviceType = serviceType;
          this.requestType = requestType;
          this.teleserviceType = teleserviceType;
          this.serviceClass = serviceClass;
          this.result = result;
      }
  
      private ImsSsData(Parcel in) {
          serviceType = in.readInt();
          requestType = in.readInt();
          teleserviceType = in.readInt();
          serviceClass = in.readInt();
          result = in.readInt();
          mSsInfo = in.createIntArray();
          mCfInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader());
          mImsSsInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader());
      }
  
      public static final @android.annotation.NonNull Creator<ImsSsData> CREATOR = new Creator<ImsSsData>() {
          @Override
          public ImsSsData createFromParcel(Parcel in) {
              return new ImsSsData(in);
          }
  
          @Override
          public ImsSsData[] newArray(int size) {
              return new ImsSsData[size];
          }
      };
  
      @Override
      public void writeToParcel(Parcel out, int flags) {
          out.writeInt(getServiceType());
          out.writeInt(getRequestType());
          out.writeInt(getTeleserviceType());
          out.writeInt(getServiceClass());
          out.writeInt(getResult());
          out.writeIntArray(mSsInfo);
          out.writeParcelableList(mCfInfo, 0);
          out.writeParcelableList(mImsSsInfo, 0);
      }
  
      @Override
      public int describeContents() {
          return 0;
      }
  
      /**
       * Old method, kept for compatibility. See {@link #isTypeCf()}
       * @hide
       */
      public boolean isTypeCF() {
          return (getServiceType() == SS_CFU || getServiceType() == SS_CF_BUSY
                  || getServiceType() == SS_CF_NO_REPLY || getServiceType() == SS_CF_NOT_REACHABLE
                  || getServiceType() == SS_CF_ALL || getServiceType() == SS_CF_ALL_CONDITIONAL);
      }
  
      public boolean isTypeCf() {
          return isTypeCF();
      }
  
      public boolean isTypeUnConditional() {
          return (getServiceType() == SS_CFU || getServiceType() == SS_CF_ALL);
      }
  
      /**
       * Old method, kept for compatibility. See {@link #isTypeCf()}
       * @hide
       */
      public boolean isTypeCW() {
          return (getServiceType() == SS_WAIT);
      }
  
      public boolean isTypeCw() {
          return isTypeCW();
      }
  
      public boolean isTypeClip() {
          return (getServiceType() == SS_CLIP);
      }
  
      public boolean isTypeColr() {
          return (getServiceType() == SS_COLR);
      }
  
      public boolean isTypeColp() {
          return (getServiceType() == SS_COLP);
      }
  
      public boolean isTypeClir() {
          return (getServiceType() == SS_CLIR);
      }
  
      public boolean isTypeIcb() {
          return (getServiceType() == SS_INCOMING_BARRING_DN
                  || getServiceType() == SS_INCOMING_BARRING_ANONYMOUS);
      }
  
      public boolean isTypeBarring() {
          return (getServiceType() == SS_BAOC || getServiceType() == SS_BAOIC
                  || getServiceType() == SS_BAOIC_EXC_HOME || getServiceType() == SS_BAIC
                  || getServiceType() == SS_BAIC_ROAMING || getServiceType() == SS_ALL_BARRING
                  || getServiceType() == SS_OUTGOING_BARRING
                  || getServiceType() == SS_INCOMING_BARRING);
      }
  
      public boolean isTypeInterrogation() {
          return (getRequestType() == SS_INTERROGATION);
      }
  
      /**
       * Supplementary Service request Type.
       */
      public @RequestType int getRequestType() {
          return requestType;
      }
  
      /**
       * The Service type of this Supplementary service.
       */
      public @ServiceType int getServiceType() {
          return serviceType;
      }
  
      /**
       * Supplementary Service teleservice type.
       */
      public @TeleserviceType int getTeleserviceType() {
          return teleserviceType;
      }
  
      /**
       * Supplementary Service service class.
       */
      public @ServiceClassFlags int getServiceClass() {
          return serviceClass;
      }
  
      /**
       * Result of Supplementary Service operation. Valid values are:
       *     {@link #RESULT_SUCCESS} if the result is success, or
       *     {@link ImsReasonInfo.UtReason} code if the result is a failure.
       */
      public @ImsReasonInfo.UtReason int getResult() {
          return result;
      }
  
      /** @hide */
      public void setSuppServiceInfo(int[] ssInfo) {
          mSsInfo = ssInfo;
      }
  
      /** @hide */
      public void setImsSpecificSuppServiceInfo(ImsSsInfo[] imsSsInfo) {
          mImsSsInfo = Arrays.asList(imsSsInfo);
      }
  
      /** @hide */
      public void setCallForwardingInfo(ImsCallForwardInfo[] cfInfo) {
          mCfInfo = Arrays.asList(cfInfo);
      }
  
      /**
       * This is a compatibility function to transform the public API to a form that can be processed
       * by telephony.
       *
       * @hide
       */
      //TODO: Refactor Telephony to use well defined classes instead of an int[] to process SS.
      public int[] getSuppServiceInfoCompat() {
          if (mSsInfo != null) {
              // Something has set the ssInfo using hidden APIs, so for compatibility just return that
              // structure directly.
              return mSsInfo;
          }
  
  
          int[] result = new int[2];
          if (mImsSsInfo == null || mImsSsInfo.size() == 0) {
              Rlog.e(TAG, "getSuppServiceInfoCompat: Could not parse mImsSsInfo, returning empty "
                      + "int[]");
              return result;
          }
  
          // Convert ImsSsInfo into a form that telephony can read (as per 3GPP 27.007)
          // CLIR (section 7.7)
          if (isTypeClir()) {
              // Assume there will only be one ImsSsInfo.
              // contains {"n","m"} parameters
              result[0] = mImsSsInfo.get(0).getClirOutgoingState();
              result[1] = mImsSsInfo.get(0).getClirInterrogationStatus();
              return result;
          }
          // COLR 7.31
          if (isTypeColr()) {
              result[0] = mImsSsInfo.get(0).getProvisionStatus();
          }
          // Facility Lock CLCK 7.4 (for call barring), CLIP 7.6, COLP 7.8, as well as any
          // other result, just return the status for the "n" parameter and provisioning status for
          // "m" as the default.
          result[0] = mImsSsInfo.get(0).getStatus();
          result[1] = mImsSsInfo.get(0).getProvisionStatus();
          return result;
      }
  
      /**
       * @return an array of {@link ImsSsInfo}s associated with this supplementary service data.
       */
      public @NonNull List<ImsSsInfo> getSuppServiceInfo() {
          return mImsSsInfo;
      }
  
      /**
       * @return an array of {@link ImsCallForwardInfo}s associated with this supplementary service
       * data.
       **/
      public @Nullable List<ImsCallForwardInfo> getCallForwardInfo() {
          return mCfInfo;
      }
  
      public String toString() {
          return "[ImsSsData] " + "ServiceType: " + getServiceType()
              + " RequestType: " + getRequestType()
              + " TeleserviceType: " + getTeleserviceType()
              + " ServiceClass: " + getServiceClass()
              + " Result: " + getResult();
      }
  }
  