/** Create an action from common {@link Data} elements. */
  public DataAction(Context context, DataItem item) {
    mContext = context;
    mKind = item.getDataKind();
    mMimeType = item.getMimeType();

    /*
     * New Feature by Mediatek Begin.
     *   Original Android's code:
     *
     *   CR ID: ALPS00308657
     *   Descriptions: RCS
     */
    String exMimeType = null;
    boolean pluginStatus =
        ExtensionManager.getInstance()
            .getContactDetailExtension()
            .checkPluginSupport(ExtensionManager.COMMD_FOR_RCS);
    if (pluginStatus) {
      exMimeType =
          ExtensionManager.getInstance()
              .getContactDetailExtension()
              .getExtentionMimeType(ExtensionManager.COMMD_FOR_RCS);
    }
    /*
     * New Feature by Mediatek End.
     */

    // Determine type for subtitle
    mSubtitle = "";
    if (item.hasKindTypeColumn()) {
      final int typeValue = item.getKindTypeColumn();
      // get type string
      /** M:AAS @ { */
      if (SimUtils.isAasPhoneType(typeValue)) {
        int slotId =
            ExtensionManager.getInstance()
                .getContactAccountExtension()
                .getCurrentSlot(ExtensionManager.COMMD_FOR_AAS);
        mSubtitle =
            (String)
                ExtensionManager.getInstance()
                    .getContactAccountExtension()
                    .getTypeLabel(
                        context.getResources(),
                        typeValue,
                        item.getContentValues().getAsString(Data.DATA3),
                        slotId,
                        ExtensionManager.COMMD_FOR_AAS);
      } else {
        /** M: @ } */
        for (EditType type : item.getDataKind().typeList) {
          if (type.rawValue == typeValue) {
            if (type.customColumn == null) {
              // Non-custom type. Get its description from the
              // resource
              mSubtitle = context.getString(type.labelRes);
            } else {
              // Custom type. Read it from the database
              mSubtitle = item.getContentValues().getAsString(type.customColumn);
            }
            break;
          }
        }
      }
    }

    mIsPrimary = item.isSuperPrimary();
    mBody = item.buildDataStringForDisplay();

    mDataId = item.getId();
    mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, mDataId);

    final boolean hasPhone = PhoneCapabilityTester.isPhone(mContext);
    final boolean hasSms = PhoneCapabilityTester.isSmsIntentRegistered(mContext);

    // Handle well-known MIME-types with special care
    if (item instanceof PhoneDataItem) {
      if (PhoneCapabilityTester.isPhone(mContext)) {
        PhoneDataItem phone = (PhoneDataItem) item;
        final String number = phone.getNumber();
        if (!TextUtils.isEmpty(number)) {

          /*
           * New Feature by Mediatek Begin.
           *   Original Android's code:
           *
           *   CR ID: ALPS00308657
           *   Descriptions: RCS
           */
          mPhoneAndSubtitle.put(number, mSubtitle.toString());
          /*
           * New Feature by Mediatek End.
           */

          final Intent phoneIntent = hasPhone ? ContactsUtils.getCallIntent(number) : null;
          final Intent smsIntent =
              hasSms
                  ? new Intent(
                      Intent.ACTION_SENDTO, Uri.fromParts(Constants.SCHEME_SMSTO, number, null))
                  : null;

          // Configure Icons and Intents. Notice actionIcon is already set to the phone
          if (hasPhone && hasSms) {
            mIntent = phoneIntent;
            mAlternateIntent = smsIntent;
            mAlternateIconRes = item.getDataKind().iconAltRes;
            mAlternateIconDescriptionRes = item.getDataKind().iconAltDescriptionRes;
          } else if (hasPhone) {
            mIntent = phoneIntent;
          } else if (hasSms) {
            mIntent = smsIntent;
          }
        }
      }
    } else if (item instanceof SipAddressDataItem) {
      if (PhoneCapabilityTester.isSipPhone(mContext)) {
        final SipAddressDataItem sip = (SipAddressDataItem) item;
        final String address = sip.getSipAddress();
        if (!TextUtils.isEmpty(address)) {
          final Uri callUri = Uri.fromParts(Constants.SCHEME_SIP, address, null);
          mIntent = ContactsUtils.getCallIntent(callUri);
          // Note that this item will get a SIP-specific variant
          // of the "call phone" icon, rather than the standard
          // app icon for the Phone app (which we show for
          // regular phone numbers.)  That's because the phone
          // app explicitly specifies an android:icon attribute
          // for the SIP-related intent-filters in its manifest.
        }
      }
    } else if (item instanceof EmailDataItem) {
      final EmailDataItem email = (EmailDataItem) item;
      final String address = email.getData();
      if (!TextUtils.isEmpty(address)) {
        final Uri mailUri = Uri.fromParts(Constants.SCHEME_MAILTO, address, null);
        mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
      }

    } else if (item instanceof WebsiteDataItem) {
      final WebsiteDataItem website = (WebsiteDataItem) item;
      final String url = website.getUrl();
      if (!TextUtils.isEmpty(url)) {
        WebAddress webAddress = new WebAddress(url);
        mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
      }

    } else if (item instanceof ImDataItem) {
      ImDataItem im = (ImDataItem) item;
      final boolean isEmail = im.isCreatedFromEmail();
      if (isEmail || im.isProtocolValid()) {
        final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();

        if (isEmail) {
          // Use Google Talk string when using Email, and clear data
          // Uri so we don't try saving Email as primary.
          mSubtitle = Im.getProtocolLabel(context.getResources(), Im.PROTOCOL_GOOGLE_TALK, null);
          mDataUri = null;
        }

        String host = im.getCustomProtocol();
        String data = im.getData();
        if (protocol != Im.PROTOCOL_CUSTOM) {
          // Try bringing in a well-known host for specific protocols
          host = ContactsUtils.lookupProviderNameFromId(protocol);
        }

        if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
          final String authority = host.toLowerCase();
          final Uri imUri =
              new Uri.Builder()
                  .scheme(Constants.SCHEME_IMTO)
                  .authority(authority)
                  .appendPath(data)
                  .build();
          mIntent = new Intent(Intent.ACTION_SENDTO, imUri);

          // If the address is also available for a video chat, we'll show the capability
          // as a secondary action.
          final int chatCapability = im.getChatCapability();
          final boolean isVideoChatCapable = (chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
          final boolean isAudioChatCapable = (chatCapability & Im.CAPABILITY_HAS_VOICE) != 0;
          if (isVideoChatCapable || isAudioChatCapable) {
            mAlternateIntent =
                new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
            if (isVideoChatCapable) {
              mAlternateIconRes = R.drawable.sym_action_videochat_holo_light;
              mAlternateIconDescriptionRes = R.string.video_chat;
            } else {
              mAlternateIconRes = R.drawable.sym_action_audiochat_holo_light;
              mAlternateIconDescriptionRes = R.string.audio_chat;
            }
          }
        }
      }
    } else if (item instanceof StructuredPostalDataItem) {
      StructuredPostalDataItem postal = (StructuredPostalDataItem) item;
      final String postalAddress = postal.getFormattedAddress();
      if (!TextUtils.isEmpty(postalAddress)) {
        mIntent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
      }
    }

    /*
     * New Feature by Mediatek Begin.
     *   Original Android's code:
     *
     *   CR ID: ALPS00308657
     *   Descriptions: RCS
     */

    else if (exMimeType != null && exMimeType.equals(item.getMimeType())) {
      String number = item.getContentValues().getAsString(Data.DATA1);
      mSubtitle = mPhoneAndSubtitle.get(number);
      int im = item.getContentValues().getAsInteger(Data.DATA5);
      int ft = item.getContentValues().getAsInteger(Data.DATA6);
      Log.i(TAG, "mSubtitle : " + mSubtitle + " | number : " + number);
      Intent intent =
          ExtensionManager.getInstance()
              .getContactDetailExtension()
              .getExtentionIntent(im, ft, ExtensionManager.COMMD_FOR_RCS);
      Log.i(TAG, "intent : " + intent + " | exMimeType : " + exMimeType);
      if (intent != null) {
        String name = item.getContentValues().getAsString(Contacts.DISPLAY_NAME);
        Log.i(TAG, "name : " + name + " | number : " + number);
        intent.putExtra(RCS_PHONE_NUMBER, number);
        intent.putExtra(RCS_DISPLAY_NAME, name);
        mIntent = intent;
      }
    }
    /*
     * New Feature by Mediatek End.
     */

    if (mIntent == null) {
      // Otherwise fall back to default VIEW action
      mIntent = new Intent(Intent.ACTION_VIEW);
      mIntent.setDataAndType(mDataUri, item.getMimeType());
    }

    mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
  }
  @Override
  public void setValues(
      DataKind kind,
      ValuesDelta entry,
      RawContactDelta state,
      boolean readOnly,
      ViewIdGenerator vig) {
    super.setValues(kind, entry, state, readOnly, vig);
    // Remove edit texts that we currently have
    if (mFieldEditTexts != null) {
      for (EditText fieldEditText : mFieldEditTexts) {
        mFields.removeView(fieldEditText);
      }
    }
    boolean hidePossible = false;

    int fieldCount = kind.fieldList.size();
    mFieldEditTexts = new EditText[fieldCount];
    for (int index = 0; index < fieldCount; index++) {
      final EditField field = kind.fieldList.get(index);
      final EditText fieldView = new EditText(mContext);
      fieldView.setLayoutParams(
          new LinearLayout.LayoutParams(
              LayoutParams.MATCH_PARENT,
              field.isMultiLine() ? LayoutParams.WRAP_CONTENT : mMinFieldHeight));
      // Set either a minimum line requirement or a minimum height (because {@link TextView}
      // only takes one or the other at a single time).
      if (field.minLines != 0) {
        fieldView.setMinLines(field.minLines);
      } else {
        fieldView.setMinHeight(mMinFieldHeight);
      }
      fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium);
      fieldView.setGravity(Gravity.TOP);
      mFieldEditTexts[index] = fieldView;
      fieldView.setId(vig.getId(state, kind, entry, index));

      if (field.titleRes > 0) {
        fieldView.setHint(field.titleRes);
      }
      /** M:AAS @ { update fieldView's hint text */
      if (Phone.CONTENT_ITEM_TYPE.equals(kind.mimeType)) {
        int type = SimUtils.isAdditionalNumber(entry) ? 1 : 0;
        ExtensionManager.getInstance()
            .getContactDetailExtension()
            .updateView(
                fieldView,
                type,
                ContactDetailExtension.VIEW_UPDATE_HINT,
                ExtensionManager.COMMD_FOR_AAS);
      }
      /** M: @ } */

      /** M: New Feature xxx @{ */
      /* original code int inputType = field.inputType; */
      final int inputType = field.inputType;
      /** @} */
      fieldView.setInputType(inputType);
      if (inputType == InputType.TYPE_CLASS_PHONE) {
        /** M: New Feature xxx @{ */
        /*
         * original code
         * PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher
         * (mContext, fieldView);
         */
        // add by mediatek
        ExtensionManager.getInstance()
            .getContactDetailExtension()
            .setViewKeyListener(fieldView, ContactPluginDefault.COMMD_FOR_OP01);
        PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(mContext, fieldView, null);
        /** @} */
      }

      // Show the "next" button in IME to navigate between text fields
      // TODO: Still need to properly navigate to/from sections without text fields,
      // See Bug: 5713510
      fieldView.setImeOptions(EditorInfo.IME_ACTION_NEXT);

      // Read current value from state
      final String column = field.column;
      final String value = entry.getAsString(column);

      /*
       * Bug Fix by Mediatek Begin.
       *   Original Android's code:
       *     xxx
       *   CR ID: ALPS00244669
       *   Descriptions:
       */
      Log.i(TAG, "setValues setFilter");
      fieldView.setFilters(new InputFilter[] {new InputFilter.LengthFilter(FIELD_VIEW_MAX)});
      /*
       * Bug Fix by Mediatek End.
       */

      fieldView.setText(value);

      // Show the delete button if we have a non-null value
      setDeleteButtonVisible(value != null);

      // Prepare listener for writing changes
      fieldView.addTextChangedListener(
          new TextWatcher() {
            /** M: New Feature xxx @{ */
            int location = 0;

            /** @} */
            @Override
            public void afterTextChanged(Editable s) {
              // Trigger event for newly changed value
              /** M: New Feature Easy Porting @{ */
              /* original code onFieldChanged(column, s.toString()); */
              String phoneText = s.toString();
              phoneText =
                  ExtensionManager.getInstance()
                      .getContactDetailExtension()
                      .TextChanged(
                          inputType, s, phoneText, location, ContactPluginDefault.COMMD_FOR_OP01);
              onFieldChanged(column, phoneText);
              /** @} */
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {}
          });

      fieldView.setEnabled(isEnabled() && !readOnly);

      if (field.shortForm) {
        hidePossible = true;
        mHasShortAndLongForms = true;
        fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE);
      } else if (field.longForm) {
        hidePossible = true;
        mHasShortAndLongForms = true;
        fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE);
      } else {
        // Hide field when empty and optional value
        final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional);
        final boolean willHide = (mHideOptional && couldHide);
        fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE);
        hidePossible = hidePossible || couldHide;
      }

      mFields.addView(fieldView);
    }

    // When hiding fields, place expandable
    setupExpansionView(hidePossible, mHideOptional);
    mExpansionView.setEnabled(!readOnly && isEnabled());
  }