/**
   * Class constructor.
   *
   * @param audioSource the recording source. See {@link MediaRecorder.AudioSource} for recording
   *     source definitions.
   * @param sampleRateInHz the sample rate expressed in Hertz. 44100Hz is currently the only rate
   *     that is guaranteed to work on all devices, but other rates such as 22050, 16000, and 11025
   *     may work on some devices.
   * @param channelConfig describes the configuration of the audio channels. See {@link
   *     AudioFormat#CHANNEL_IN_MONO} and {@link AudioFormat#CHANNEL_IN_STEREO}. {@link
   *     AudioFormat#CHANNEL_IN_MONO} is guaranteed to work on all devices.
   * @param audioFormat the format in which the audio data is represented. See {@link
   *     AudioFormat#ENCODING_PCM_16BIT} and {@link AudioFormat#ENCODING_PCM_8BIT}
   * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written to
   *     during the recording. New audio data can be read from this buffer in smaller chunks than
   *     this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum required
   *     buffer size for the successful creation of an AudioRecord instance. Using values smaller
   *     than getMinBufferSize() will result in an initialization failure.
   * @throws java.lang.IllegalArgumentException
   */
  public AudioRecord(
      int audioSource,
      int sampleRateInHz,
      int channelConfig,
      int audioFormat,
      int bufferSizeInBytes)
      throws IllegalArgumentException {
    /// M: Check record permission to user for CTA. {@
    if (FeatureOption.MTK_MOBILE_MANAGEMENT) {
      Xlog.d(TAG, "AudioRecord>>>");
      IBinder binder = ServiceManager.getService(Context.MOBILE_SERVICE);
      IMobileManagerService moms = IMobileManagerService.Stub.asInterface(binder);
      int uid = Binder.getCallingUid();
      String permission = SubPermissions.RECORD_MIC;
      try {
        if (moms != null
            && (moms.checkPermission(permission, uid) != PackageManager.PERMISSION_GRANTED)) {
          Xlog.d(TAG, "AudioRecord<<<: user denied permission " + permission + " for uid " + uid);
          throw new IllegalArgumentException();
        }
      } catch (RemoteException e) {
        Xlog.e(TAG, "CheckPermission failed in prepare with RemoteException, continues record.", e);
      }
    }
    /// @}

    mRecordingState = RECORDSTATE_STOPPED;

    // remember which looper is associated with the AudioRecord instanciation
    if ((mInitializationLooper = Looper.myLooper()) == null) {
      mInitializationLooper = Looper.getMainLooper();
    }

    audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat);

    audioBuffSizeCheck(bufferSizeInBytes);

    // native initialization
    int[] session = new int[1];
    session[0] = 0;
    // TODO: update native initialization when information about hardware init failure
    //      due to capture device already open is available.
    int initResult =
        native_setup(
            new WeakReference<AudioRecord>(this),
            mRecordSource,
            mSampleRate,
            mChannelMask,
            mAudioFormat,
            mNativeBufferSizeInBytes,
            session);
    if (initResult != SUCCESS) {
      loge("Error code " + initResult + " when initializing native AudioRecord object.");
      return; // with mState == STATE_UNINITIALIZED
    }

    mSessionId = session[0];

    mState = STATE_INITIALIZED;
  }
  /**
   * Class constructor.
   *
   * @param audioSource the recording source. See {@link MediaRecorder.AudioSource} for recording
   *     source definitions.
   * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but not
   *     limited to) 44100, 22050 and 11025.
   * @param channelConfig describes the configuration of the audio channels. See {@link
   *     AudioFormat#CHANNEL_IN_MONO} and {@link AudioFormat#CHANNEL_IN_STEREO}
   * @param audioFormat the format in which the audio data is represented. See {@link
   *     AudioFormat#ENCODING_PCM_16BIT} and {@link AudioFormat#ENCODING_PCM_8BIT}
   * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written to
   *     during the recording. New audio data can be read from this buffer in smaller chunks than
   *     this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum required
   *     buffer size for the successful creation of an AudioRecord instance. Using values smaller
   *     than getMinBufferSize() will result in an initialization failure.
   * @throws java.lang.IllegalArgumentException
   */
  public AudioRecord(
      int audioSource,
      int sampleRateInHz,
      int channelConfig,
      int audioFormat,
      int bufferSizeInBytes)
      throws IllegalArgumentException {
    mState = STATE_UNINITIALIZED;
    mRecordingState = RECORDSTATE_STOPPED;

    // remember which looper is associated with the AudioRecord instanciation
    if ((mInitializationLooper = Looper.myLooper()) == null) {
      mInitializationLooper = Looper.getMainLooper();
    }

    audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat);

    audioBuffSizeCheck(bufferSizeInBytes);

    // native initialization
    // TODO: update native initialization when information about hardware init failure
    //      due to capture device already open is available.
    int initResult =
        native_setup(
            new WeakReference<AudioRecord>(this),
            mRecordSource,
            mSampleRate,
            mChannels,
            mAudioFormat,
            mNativeBufferSizeInBytes);
    if (initResult != SUCCESS) {
      loge("Error code " + initResult + " when initializing native AudioRecord object.");
      return; // with mState == STATE_UNINITIALIZED
    }

    mState = STATE_INITIALIZED;
  }