/*
 * 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 android.nfc;

import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.proto.ProtoOutputStream;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * Represents an immutable NDEF Record.
 * <p>
 * NDEF (NFC Data Exchange Format) is a light-weight binary format,
 * used to encapsulate typed data. It is specified by the NFC Forum,
 * for transmission and storage with NFC, however it is transport agnostic.
 * <p>
 * NDEF defines messages and records. An NDEF Record contains
 * typed data, such as MIME-type media, a URI, or a custom
 * application payload. An NDEF Message is a container for
 * one or more NDEF Records.
 * <p>
 * This class represents logical (complete) NDEF Records, and can not be
 * used to represent chunked (partial) NDEF Records. However
 * {@link NdefMessage#NdefMessage(byte[])} can be used to parse a message
 * containing chunked records, and will return a message with unchunked
 * (complete) records.
 * <p>
 * A logical NDEF Record always contains a 3-bit TNF (Type Name Field)
 * that provides high level typing for the rest of the record. The
 * remaining fields are variable length and not always present:
 * <ul>
 * <li><em>type</em>: detailed typing for the payload</li>
 * <li><em>id</em>: identifier meta-data, not commonly used</li>
 * <li><em>payload</em>: the actual payload</li>
 * </ul>
 * <p>
 * Helpers such as {@link NdefRecord#createUri}, {@link NdefRecord#createMime}
 * and {@link NdefRecord#createExternal} are included to create well-formatted
 * NDEF Records with correctly set tnf, type, id and payload fields, please
 * use these helpers whenever possible.
 * <p>
 * Use the constructor {@link #NdefRecord(short, byte[], byte[], byte[])}
 * if you know what you are doing and what to set the fields individually.
 * Only basic validation is performed with this constructor, so it is possible
 * to create records that do not confirm to the strict NFC Forum
 * specifications.
 * <p>
 * The binary representation of an NDEF Record includes additional flags to
 * indicate location with an NDEF message, provide support for chunking of
 * NDEF records, and to pack optional fields. This class does not expose
 * those details. To write an NDEF Record as binary you must first put it
 * into an {@link NdefMessage}, then call {@link NdefMessage#toByteArray()}.
 * <p class="note">
 * {@link NdefMessage} and {@link NdefRecord} implementations are
 * always available, even on Android devices that do not have NFC hardware.
 * <p class="note">
 * {@link NdefRecord}s are intended to be immutable (and thread-safe),
 * however they may contain mutable fields. So take care not to modify
 * mutable fields passed into constructors, or modify mutable fields
 * obtained by getter methods, unless such modification is explicitly
 * marked as safe.
 *
 * @see NfcAdapter#ACTION_NDEF_DISCOVERED
 * @see NdefMessage
 */
public final class NdefRecord implements Parcelable {
    /**
     * Indicates the record is empty.<p>
     * Type, id and payload fields are empty in a {@literal TNF_EMPTY} record.
     */
    public static final short TNF_EMPTY = 0x00;

    /**
     * Indicates the type field contains a well-known RTD type name.<p>
     * Use this tnf with RTD types such as {@link #RTD_TEXT}, {@link #RTD_URI}.
     * <p>
     * The RTD type name format is specified in NFCForum-TS-RTD_1.0.
     *
     * @see #RTD_URI
     * @see #RTD_TEXT
     * @see #RTD_SMART_POSTER
     * @see #createUri
     */
    public static final short TNF_WELL_KNOWN = 0x01;

    /**
     * Indicates the type field contains a media-type BNF
     * construct, defined by RFC 2046.<p>
     * Use this with MIME type names such as {@literal "image/jpeg"}, or
     * using the helper {@link #createMime}.
     *
     * @see #createMime
     */
    public static final short TNF_MIME_MEDIA = 0x02;

    /**
     * Indicates the type field contains an absolute-URI
     * BNF construct defined by RFC 3986.<p>
     * When creating new records prefer {@link #createUri},
     * since it offers more compact URI encoding
     * ({@literal #RTD_URI} allows compression of common URI prefixes).
     *
     * @see #createUri
     */
    public static final short TNF_ABSOLUTE_URI = 0x03;

    /**
     * Indicates the type field contains an external type name.<p>
     * Used to encode custom payloads. When creating new records
     * use the helper {@link #createExternal}.<p>
     * The external-type RTD format is specified in NFCForum-TS-RTD_1.0.<p>
     * <p>
     * Note this TNF should not be used with RTD_TEXT or RTD_URI constants.
     * Those are well known RTD constants, not external RTD constants.
     *
     * @see #createExternal
     */
    public static final short TNF_EXTERNAL_TYPE = 0x04;

    /**
     * Indicates the payload type is unknown.<p>
     * NFC Forum explains this should be treated similarly to the
     * "application/octet-stream" MIME type. The payload
     * type is not explicitly encoded within the record.
     * <p>
     * The type field is empty in an {@literal TNF_UNKNOWN} record.
     */
    public static final short TNF_UNKNOWN = 0x05;

    /**
     * Indicates the payload is an intermediate or final chunk of a chunked
     * NDEF Record.<p>
     * {@literal TNF_UNCHANGED} can not be used with this class
     * since all {@link NdefRecord}s are already unchunked, however they
     * may appear in the binary format.
     */
    public static final short TNF_UNCHANGED = 0x06;

    /**
     * Reserved TNF type.
     * <p>
     * The NFC Forum NDEF Specification v1.0 suggests for NDEF parsers to treat this
     * value like TNF_UNKNOWN.
     * @hide
     */
    public static final short TNF_RESERVED = 0x07;

    /**
     * RTD Text type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_TEXT = {0x54};  // "T"

    /**
     * RTD URI type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_URI = {0x55};   // "U"

    /**
     * RTD Smart Poster type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_SMART_POSTER = {0x53, 0x70};  // "Sp"

    /**
     * RTD Alternative Carrier type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_ALTERNATIVE_CARRIER = {0x61, 0x63};  // "ac"

    /**
     * RTD Handover Carrier type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_HANDOVER_CARRIER = {0x48, 0x63};  // "Hc"

    /**
     * RTD Handover Request type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_HANDOVER_REQUEST = {0x48, 0x72};  // "Hr"

    /**
     * RTD Handover Select type. For use with {@literal TNF_WELL_KNOWN}.
     * @see #TNF_WELL_KNOWN
     */
    public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs"

    /**
     * RTD Android app type. For use with {@literal TNF_EXTERNAL}.
     * <p>
     * The payload of a record with type RTD_ANDROID_APP
     * should be the package name identifying an application.
     * Multiple RTD_ANDROID_APP records may be included
     * in a single {@link NdefMessage}.
     * <p>
     * Use {@link #createApplicationRecord(String)} to create
     * RTD_ANDROID_APP records.
     * @hide
     */
    public static final byte[] RTD_ANDROID_APP = "android.com:pkg".getBytes();

    private static final byte FLAG_MB = (byte) 0x80;
    private static final byte FLAG_ME = (byte) 0x40;
    private static final byte FLAG_CF = (byte) 0x20;
    private static final byte FLAG_SR = (byte) 0x10;
    private static final byte FLAG_IL = (byte) 0x08;

    /**
     * NFC Forum "URI Record Type Definition"<p>
     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
     */
    private static final String[] URI_PREFIX_MAP = new String[] {
            "", // 0x00
            "http://www.", // 0x01
            "https://www.", // 0x02
            "http://", // 0x03
            "https://", // 0x04
            "tel:", // 0x05
            "mailto:", // 0x06
            "ftp://anonymous:anonymous@", // 0x07
            "ftp://ftp.", // 0x08
            "ftps://", // 0x09
            "sftp://", // 0x0A
            "smb://", // 0x0B
            "nfs://", // 0x0C
            "ftp://", // 0x0D
            "dav://", // 0x0E
            "news:", // 0x0F
            "telnet://", // 0x10
            "imap:", // 0x11
            "rtsp://", // 0x12
            "urn:", // 0x13
            "pop:", // 0x14
            "sip:", // 0x15
            "sips:", // 0x16
            "tftp:", // 0x17
            "btspp://", // 0x18
            "btl2cap://", // 0x19
            "btgoep://", // 0x1A
            "tcpobex://", // 0x1B
            "irdaobex://", // 0x1C
            "file://", // 0x1D
            "urn:epc:id:", // 0x1E
            "urn:epc:tag:", // 0x1F
            "urn:epc:pat:", // 0x20
            "urn:epc:raw:", // 0x21
            "urn:epc:", // 0x22
            "urn:nfc:", // 0x23
    };

    private static final int MAX_PAYLOAD_SIZE = 10 * (1 << 20);  // 10 MB payload limit

    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];

    private final short mTnf;
    private final byte[] mType;
    @UnsupportedAppUsage
    private final byte[] mId;
    private final byte[] mPayload;

    /**
     * Create a new Android Application Record (AAR).
     * <p>
     * This record indicates to other Android devices the package
     * that should be used to handle the entire NDEF message.
     * You can embed this record anywhere into your message
     * to ensure that the intended package receives the message.
     * <p>
     * When an Android device dispatches an {@link NdefMessage}
     * containing one or more Android application records,
     * the applications contained in those records will be the
     * preferred target for the {@link NfcAdapter#ACTION_NDEF_DISCOVERED}
     * intent, in the order in which they appear in the message.
     * This dispatch behavior was first added to Android in
     * Ice Cream Sandwich.
     * <p>
     * If none of the applications have a are installed on the device,
     * a Market link will be opened to the first application.
     * <p>
     * Note that Android application records do not overrule
     * applications that have called
     * {@link NfcAdapter#enableForegroundDispatch}.
     *
     * @param packageName Android package name
     * @return Android application NDEF record
     */
    public static NdefRecord createApplicationRecord(String packageName) {
        if (packageName == null) throw new NullPointerException("packageName is null");
        if (packageName.length() == 0) throw new IllegalArgumentException("packageName is empty");

        return new NdefRecord(TNF_EXTERNAL_TYPE, RTD_ANDROID_APP, null,
                packageName.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Create a new NDEF Record containing a URI.<p>
     * Use this method to encode a URI (or URL) into an NDEF Record.<p>
     * Uses the well known URI type representation: {@link #TNF_WELL_KNOWN}
     * and {@link #RTD_URI}. This is the most efficient encoding
     * of a URI into NDEF.<p>
     * The uri parameter will be normalized with
     * {@link Uri#normalizeScheme} to set the scheme to lower case to
     * follow Android best practices for intent filtering.
     * However the unchecked exception
     * {@link IllegalArgumentException} may be thrown if the uri
     * parameter has serious problems, for example if it is empty, so always
     * catch this exception if you are passing user-generated data into this
     * method.<p>
     *
     * Reference specification: NFCForum-TS-RTD_URI_1.0
     *
     * @param uri URI to encode.
     * @return an NDEF Record containing the URI
     * @throws IllegalArugmentException if the uri is empty or invalid
     */
    public static NdefRecord createUri(Uri uri) {
        if (uri == null) throw new NullPointerException("uri is null");

        uri = uri.normalizeScheme();
        String uriString = uri.toString();
        if (uriString.length() == 0) throw new IllegalArgumentException("uri is empty");

        byte prefix = 0;
        for (int i = 1; i < URI_PREFIX_MAP.length; i++) {
            if (uriString.startsWith(URI_PREFIX_MAP[i])) {
                prefix = (byte) i;
                uriString = uriString.substring(URI_PREFIX_MAP[i].length());
                break;
            }
        }
        byte[] uriBytes = uriString.getBytes(StandardCharsets.UTF_8);
        byte[] recordBytes = new byte[uriBytes.length + 1];
        recordBytes[0] = prefix;
        System.arraycopy(uriBytes, 0, recordBytes, 1, uriBytes.length);
        return new NdefRecord(TNF_WELL_KNOWN, RTD_URI, null, recordBytes);
    }

    /**
     * Create a new NDEF Record containing a URI.<p>
     * Use this method to encode a URI (or URL) into an NDEF Record.<p>
     * Uses the well known URI type representation: {@link #TNF_WELL_KNOWN}
     * and {@link #RTD_URI}. This is the most efficient encoding
     * of a URI into NDEF.<p>
      * The uriString parameter will be normalized with
     * {@link Uri#normalizeScheme} to set the scheme to lower case to
     * follow Android best practices for intent filtering.
     * However the unchecked exception
     * {@link IllegalArgumentException} may be thrown if the uriString
     * parameter has serious problems, for example if it is empty, so always
     * catch this exception if you are passing user-generated data into this
     * method.<p>
     *
     * Reference specification: NFCForum-TS-RTD_URI_1.0
     *
     * @param uriString string URI to encode.
     * @return an NDEF Record containing the URI
     * @throws IllegalArugmentException if the uriString is empty or invalid
     */
    public static NdefRecord createUri(String uriString) {
        return createUri(Uri.parse(uriString));
    }

    /**
     * Create a new NDEF Record containing MIME data.<p>
     * Use this method to encode MIME-typed data into an NDEF Record,
     * such as "text/plain", or "image/jpeg".<p>
     * The mimeType parameter will be normalized with
     * {@link Intent#normalizeMimeType} to follow Android best
     * practices for intent filtering, for example to force lower-case.
     * However the unchecked exception
     * {@link IllegalArgumentException} may be thrown
     * if the mimeType parameter has serious problems,
     * for example if it is empty, so always catch this
     * exception if you are passing user-generated data into this method.
     * <p>
     * For efficiency, This method might not make an internal copy of the
     * mimeData byte array, so take care not
     * to modify the mimeData byte array while still using the returned
     * NdefRecord.
     *
     * @param mimeType a valid MIME type
     * @param mimeData MIME data as bytes
     * @return an NDEF Record containing the MIME-typed data
     * @throws IllegalArugmentException if the mimeType is empty or invalid
     *
     */
    public static NdefRecord createMime(String mimeType, byte[] mimeData) {
        if (mimeType == null) throw new NullPointerException("mimeType is null");

        // We only do basic MIME type validation: trying to follow the
        // RFCs strictly only ends in tears, since there are lots of MIME
        // types in common use that are not strictly valid as per RFC rules
        mimeType = Intent.normalizeMimeType(mimeType);
        if (mimeType.length() == 0) throw new IllegalArgumentException("mimeType is empty");
        int slashIndex = mimeType.indexOf('/');
        if (slashIndex == 0) throw new IllegalArgumentException("mimeType must have major type");
        if (slashIndex == mimeType.length() - 1) {
            throw new IllegalArgumentException("mimeType must have minor type");
        }
        // missing '/' is allowed

        // MIME RFCs suggest ASCII encoding for content-type
        byte[] typeBytes = mimeType.getBytes(StandardCharsets.US_ASCII);
        return new NdefRecord(TNF_MIME_MEDIA, typeBytes, null, mimeData);
    }

    /**
     * Create a new NDEF Record containing external (application-specific) data.<p>
     * Use this method to encode application specific data into an NDEF Record.
     * The data is typed by a domain name (usually your Android package name) and
     * a domain-specific type. This data is packaged into a "NFC Forum External
     * Type" NDEF Record.<p>
     * NFC Forum requires that the domain and type used in an external record
     * are treated as case insensitive, however Android intent filtering is
     * always case sensitive. So this method will force the domain and type to
     * lower-case before creating the NDEF Record.<p>
     * The unchecked exception {@link IllegalArgumentException} will be thrown
     * if the domain and type have serious problems, for example if either field
     * is empty, so always catch this
     * exception if you are passing user-generated data into this method.<p>
     * There are no such restrictions on the payload data.<p>
     * For efficiency, This method might not make an internal copy of the
     * data byte array, so take care not
     * to modify the data byte array while still using the returned
     * NdefRecord.
     *
     * Reference specification: NFCForum-TS-RTD_1.0
     * @param domain domain-name of issuing organization
     * @param type domain-specific type of data
     * @param data payload as bytes
     * @throws IllegalArugmentException if either domain or type are empty or invalid
     */
    public static NdefRecord createExternal(String domain, String type, byte[] data) {
        if (domain == null) throw new NullPointerException("domain is null");
        if (type == null) throw new NullPointerException("type is null");

        domain = domain.trim().toLowerCase(Locale.ROOT);
        type = type.trim().toLowerCase(Locale.ROOT);

        if (domain.length() == 0) throw new IllegalArgumentException("domain is empty");
        if (type.length() == 0) throw new IllegalArgumentException("type is empty");

        byte[] byteDomain = domain.getBytes(StandardCharsets.UTF_8);
        byte[] byteType = type.getBytes(StandardCharsets.UTF_8);
        byte[] b = new byte[byteDomain.length + 1 + byteType.length];
        System.arraycopy(byteDomain, 0, b, 0, byteDomain.length);
        b[byteDomain.length] = ':';
        System.arraycopy(byteType, 0, b, byteDomain.length + 1, byteType.length);

        return new NdefRecord(TNF_EXTERNAL_TYPE, b, null, data);
    }

    /**
     * Create a new NDEF record containing UTF-8 text data.<p>
     *
     * The caller can either specify the language code for the provided text,
     * or otherwise the language code corresponding to the current default
     * locale will be used.
     *
     * Reference specification: NFCForum-TS-RTD_Text_1.0
     * @param languageCode The languageCode for the record. If locale is empty or null,
     *                     the language code of the current default locale will be used.
     * @param text   The text to be encoded in the record. Will be represented in UTF-8 format.
     * @throws IllegalArgumentException if text is null
     */
    public static NdefRecord createTextRecord(String languageCode, String text) {
        if (text == null) throw new NullPointerException("text is null");

        byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);

        byte[] languageCodeBytes = null;
        if (languageCode != null && !languageCode.isEmpty()) {
            languageCodeBytes = languageCode.getBytes(StandardCharsets.US_ASCII);
        } else {
            languageCodeBytes = Locale.getDefault().getLanguage().
                    getBytes(StandardCharsets.US_ASCII);
        }
        // We only have 6 bits to indicate ISO/IANA language code.
        if (languageCodeBytes.length >= 64) {
            throw new IllegalArgumentException("language code is too long, must be <64 bytes.");
        }
        ByteBuffer buffer = ByteBuffer.allocate(1 + languageCodeBytes.length + textBytes.length);

        byte status = (byte) (languageCodeBytes.length & 0xFF);
        buffer.put(status);
        buffer.put(languageCodeBytes);
        buffer.put(textBytes);

        return new NdefRecord(TNF_WELL_KNOWN, RTD_TEXT, null, buffer.array());
    }

    /**
     * Construct an NDEF Record from its component fields.<p>
     * Recommend to use helpers such as {#createUri} or
     * {{@link #createExternal} where possible, since they perform
     * stricter validation that the record is correctly formatted
     * as per NDEF specifications. However if you know what you are
     * doing then this constructor offers the most flexibility.<p>
     * An {@link NdefRecord} represents a logical (complete)
     * record, and cannot represent NDEF Record chunks.<p>
     * Basic validation of the tnf, type, id and payload is performed
     * as per the following rules:
     * <ul>
     * <li>The tnf paramter must be a 3-bit value.</li>
     * <li>Records with a tnf of {@link #TNF_EMPTY} cannot have a type,
     * id or payload.</li>
     * <li>Records with a tnf of {@link #TNF_UNKNOWN} or {@literal 0x07}
     * cannot have a type.</li>
     * <li>Records with a tnf of {@link #TNF_UNCHANGED} are not allowed
     * since this class only represents complete (unchunked) records.</li>
     * </ul>
     * This minimal validation is specified by
     * NFCForum-TS-NDEF_1.0 section 3.2.6 (Type Name Format).<p>
     * If any of the above validation
     * steps fail then {@link IllegalArgumentException} is thrown.<p>
     * Deep inspection of the type, id and payload fields is not
     * performed, so it is possible to create NDEF Records
     * that conform to section 3.2.6
     * but fail other more strict NDEF specification requirements. For
     * example, the payload may be invalid given the tnf and type.
     * <p>
     * To omit a type, id or payload field, set the parameter to an
     * empty byte array or null.
     *
     * @param tnf  a 3-bit TNF constant
     * @param type byte array, containing zero to 255 bytes, or null
     * @param id   byte array, containing zero to 255 bytes, or null
     * @param payload byte array, containing zero to (2 ** 32 - 1) bytes,
     *                or null
     * @throws IllegalArugmentException if a valid record cannot be created
     */
    public NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload) {
        /* convert nulls */
        if (type == null) type = EMPTY_BYTE_ARRAY;
        if (id == null) id = EMPTY_BYTE_ARRAY;
        if (payload == null) payload = EMPTY_BYTE_ARRAY;

        String message = validateTnf(tnf, type, id, payload);
        if (message != null) {
            throw new IllegalArgumentException(message);
        }

        mTnf = tnf;
        mType = type;
        mId = id;
        mPayload = payload;
    }

    /**
     * Construct an NDEF Record from raw bytes.<p>
     * This method is deprecated, use {@link NdefMessage#NdefMessage(byte[])}
     * instead. This is because it does not make sense to parse a record:
     * the NDEF binary format is only defined for a message, and the
     * record flags MB and ME do not make sense outside of the context of
     * an entire message.<p>
     * This implementation will attempt to parse a single record by ignoring
     * the MB and ME flags, and otherwise following the rules of
     * {@link NdefMessage#NdefMessage(byte[])}.<p>
     *
     * @param data raw bytes to parse
     * @throws FormatException if the data cannot be parsed into a valid record
     * @deprecated use {@link NdefMessage#NdefMessage(byte[])} instead.
     */
    @Deprecated
    public NdefRecord(byte[] data) throws FormatException {
        ByteBuffer buffer = ByteBuffer.wrap(data);
        NdefRecord[] rs = parse(buffer, true);

        if (buffer.remaining() > 0) {
            throw new FormatException("data too long");
        }

        mTnf = rs[0].mTnf;
        mType = rs[0].mType;
        mId = rs[0].mId;
        mPayload = rs[0].mPayload;
    }

    /**
     * Returns the 3-bit TNF.
     * <p>
     * TNF is the top-level type.
     */
    public short getTnf() {
        return mTnf;
    }

    /**
     * Returns the variable length Type field.
     * <p>
     * This should be used in conjunction with the TNF field to determine the
     * payload format.
     * <p>
     * Returns an empty byte array if this record
     * does not have a type field.
     */
    public byte[] getType() {
        return mType.clone();
    }

    /**
     * Returns the variable length ID.
     * <p>
     * Returns an empty byte array if this record
     * does not have an id field.
     */
    public byte[] getId() {
        return mId.clone();
    }

    /**
     * Returns the variable length payload.
     * <p>
     * Returns an empty byte array if this record
     * does not have a payload field.
     */
    public byte[] getPayload() {
        return mPayload.clone();
    }

    /**
     * Return this NDEF Record as a byte array.<p>
     * This method is deprecated, use {@link NdefMessage#toByteArray}
     * instead. This is because the NDEF binary format is not defined for
     * a record outside of the context of a message: the MB and ME flags
     * cannot be set without knowing the location inside a message.<p>
     * This implementation will attempt to serialize a single record by
     * always setting the MB and ME flags (in other words, assume this
     * is a single-record NDEF Message).<p>
     *
     * @deprecated use {@link NdefMessage#toByteArray()} instead
     */
    @Deprecated
    public byte[] toByteArray() {
        ByteBuffer buffer = ByteBuffer.allocate(getByteLength());
        writeToByteBuffer(buffer, true, true);
        return buffer.array();
    }

    /**
     * Map this record to a MIME type, or return null if it cannot be mapped.<p>
     * Currently this method considers all {@link #TNF_MIME_MEDIA} records to
     * be MIME records, as well as some {@link #TNF_WELL_KNOWN} records such as
     * {@link #RTD_TEXT}. If this is a MIME record then the MIME type as string
     * is returned, otherwise null is returned.<p>
     * This method does not perform validation that the MIME type is
     * actually valid. It always attempts to
     * return a string containing the type if this is a MIME record.<p>
     * The returned MIME type will by normalized to lower-case using
     * {@link Intent#normalizeMimeType}.<p>
     * The MIME payload can be obtained using {@link #getPayload}.
     *
     * @return MIME type as a string, or null if this is not a MIME record
     */
    public String toMimeType() {
        switch (mTnf) {
            case NdefRecord.TNF_WELL_KNOWN:
                if (Arrays.equals(mType, NdefRecord.RTD_TEXT)) {
                    return "text/plain";
                }
                break;
            case NdefRecord.TNF_MIME_MEDIA:
                String mimeType = new String(mType, StandardCharsets.US_ASCII);
                return Intent.normalizeMimeType(mimeType);
        }
        return null;
    }

    /**
     * Map this record to a URI, or return null if it cannot be mapped.<p>
     * Currently this method considers the following to be URI records:
     * <ul>
     * <li>{@link #TNF_ABSOLUTE_URI} records.</li>
     * <li>{@link #TNF_WELL_KNOWN} with a type of {@link #RTD_URI}.</li>
     * <li>{@link #TNF_WELL_KNOWN} with a type of {@link #RTD_SMART_POSTER}
     * and containing a URI record in the NDEF message nested in the payload.
     * </li>
     * <li>{@link #TNF_EXTERNAL_TYPE} records.</li>
     * </ul>
     * If this is not a URI record by the above rules, then null is returned.<p>
     * This method does not perform validation that the URI is
     * actually valid: it always attempts to create and return a URI if
     * this record appears to be a URI record by the above rules.<p>
     * The returned URI will be normalized to have a lower case scheme
     * using {@link Uri#normalizeScheme}.<p>
     *
     * @return URI, or null if this is not a URI record
     */
    public Uri toUri() {
        return toUri(false);
    }

    private Uri toUri(boolean inSmartPoster) {
        switch (mTnf) {
            case TNF_WELL_KNOWN:
                if (Arrays.equals(mType, RTD_SMART_POSTER) && !inSmartPoster) {
                    try {
                        // check payload for a nested NDEF Message containing a URI
                        NdefMessage nestedMessage = new NdefMessage(mPayload);
                        for (NdefRecord nestedRecord : nestedMessage.getRecords()) {
                            Uri uri = nestedRecord.toUri(true);
                            if (uri != null) {
                                return uri;
                            }
                        }
                    } catch (FormatException e) {  }
                } else if (Arrays.equals(mType, RTD_URI)) {
                    Uri wktUri = parseWktUri();
                    return (wktUri != null ? wktUri.normalizeScheme() : null);
                }
                break;

            case TNF_ABSOLUTE_URI:
                Uri uri = Uri.parse(new String(mType, StandardCharsets.UTF_8));
                return uri.normalizeScheme();

            case TNF_EXTERNAL_TYPE:
                if (inSmartPoster) {
                    break;
                }
                return Uri.parse("vnd.android.nfc://ext/" + new String(mType, StandardCharsets.US_ASCII));
        }
        return null;
    }

    /**
     * Return complete URI of {@link #TNF_WELL_KNOWN}, {@link #RTD_URI} records.
     * @return complete URI, or null if invalid
     */
    private Uri parseWktUri() {
        if (mPayload.length < 2) {
            return null;
        }

        // payload[0] contains the URI Identifier Code, as per
        // NFC Forum "URI Record Type Definition" section 3.2.2.
        int prefixIndex = (mPayload[0] & (byte)0xFF);
        if (prefixIndex < 0 || prefixIndex >= URI_PREFIX_MAP.length) {
            return null;
        }
        String prefix = URI_PREFIX_MAP[prefixIndex];
        String suffix = new String(Arrays.copyOfRange(mPayload, 1, mPayload.length),
                StandardCharsets.UTF_8);
        return Uri.parse(prefix + suffix);
    }

    /**
     * Main record parsing method.<p>
     * Expects NdefMessage to begin immediately, allows trailing data.<p>
     * Currently has strict validation of all fields as per NDEF 1.0
     * specification section 2.5. We will attempt to keep this as strict as
     * possible to encourage well-formatted NDEF.<p>
     * Always returns 1 or more NdefRecord's, or throws FormatException.
     *
     * @param buffer ByteBuffer to read from
     * @param ignoreMbMe ignore MB and ME flags, and read only 1 complete record
     * @return one or more records
     * @throws FormatException on any parsing error
     */
    static NdefRecord[] parse(ByteBuffer buffer, boolean ignoreMbMe) throws FormatException {
        List<NdefRecord> records = new ArrayList<NdefRecord>();

        try {
            byte[] type = null;
            byte[] id = null;
            byte[] payload = null;
            ArrayList<byte[]> chunks = new ArrayList<byte[]>();
            boolean inChunk = false;
            short chunkTnf = -1;
            boolean me = false;

            while (!me) {
                byte flag = buffer.get();

                boolean mb = (flag & NdefRecord.FLAG_MB) != 0;
                me = (flag & NdefRecord.FLAG_ME) != 0;
                boolean cf = (flag & NdefRecord.FLAG_CF) != 0;
                boolean sr = (flag & NdefRecord.FLAG_SR) != 0;
                boolean il = (flag & NdefRecord.FLAG_IL) != 0;
                short tnf = (short)(flag & 0x07);

                if (!mb && records.size() == 0 && !inChunk && !ignoreMbMe) {
                    throw new FormatException("expected MB flag");
                } else if (mb && (records.size() != 0 || inChunk) && !ignoreMbMe) {
                    throw new FormatException("unexpected MB flag");
                } else if (inChunk && il) {
                    throw new FormatException("unexpected IL flag in non-leading chunk");
                } else if (cf && me) {
                    throw new FormatException("unexpected ME flag in non-trailing chunk");
                } else if (inChunk && tnf != NdefRecord.TNF_UNCHANGED) {
                    throw new FormatException("expected TNF_UNCHANGED in non-leading chunk");
                } else if (!inChunk && tnf == NdefRecord.TNF_UNCHANGED) {
                    throw new FormatException("" +
                            "unexpected TNF_UNCHANGED in first chunk or unchunked record");
                }

                int typeLength = buffer.get() & 0xFF;
                long payloadLength = sr ? (buffer.get() & 0xFF) : (buffer.getInt() & 0xFFFFFFFFL);
                int idLength = il ? (buffer.get() & 0xFF) : 0;

                if (inChunk && typeLength != 0) {
                    throw new FormatException("expected zero-length type in non-leading chunk");
                }

                if (!inChunk) {
                    type = (typeLength > 0 ? new byte[typeLength] : EMPTY_BYTE_ARRAY);
                    id = (idLength > 0 ? new byte[idLength] : EMPTY_BYTE_ARRAY);
                    buffer.get(type);
                    buffer.get(id);
                }

                ensureSanePayloadSize(payloadLength);
                payload = (payloadLength > 0 ? new byte[(int)payloadLength] : EMPTY_BYTE_ARRAY);
                buffer.get(payload);

                if (cf && !inChunk) {
                    // first chunk
                    if (typeLength == 0 && tnf != NdefRecord.TNF_UNKNOWN) {
                        throw new FormatException("expected non-zero type length in first chunk");
                    }
                    chunks.clear();
                    chunkTnf = tnf;
                }
                if (cf || inChunk) {
                    // any chunk
                    chunks.add(payload);
                }
                if (!cf && inChunk) {
                    // last chunk, flatten the payload
                    payloadLength = 0;
                    for (byte[] p : chunks) {
                        payloadLength += p.length;
                    }
                    ensureSanePayloadSize(payloadLength);
                    payload = new byte[(int)payloadLength];
                    int i = 0;
                    for (byte[] p : chunks) {
                        System.arraycopy(p, 0, payload, i, p.length);
                        i += p.length;
                    }
                    tnf = chunkTnf;
                }
                if (cf) {
                    // more chunks to come
                    inChunk = true;
                    continue;
                } else {
                    inChunk = false;
                }

                String error = validateTnf(tnf, type, id, payload);
                if (error != null) {
                    throw new FormatException(error);
                }
                records.add(new NdefRecord(tnf, type, id, payload));
                if (ignoreMbMe) {  // for parsing a single NdefRecord
                    break;
                }
            }
        } catch (BufferUnderflowException e) {
            throw new FormatException("expected more data", e);
        }
        return records.toArray(new NdefRecord[records.size()]);
    }

    private static void ensureSanePayloadSize(long size) throws FormatException {
        if (size > MAX_PAYLOAD_SIZE) {
            throw new FormatException(
                    "payload above max limit: " + size + " > " + MAX_PAYLOAD_SIZE);
        }
    }

    /**
     * Perform simple validation that the tnf is valid.<p>
     * Validates the requirements of NFCForum-TS-NDEF_1.0 section
     * 3.2.6 (Type Name Format). This just validates that the tnf
     * is valid, and that the relevant type, id and payload
     * fields are present (or empty) for this tnf. It does not
     * perform any deep inspection of the type, id and payload fields.<p>
     * Also does not allow TNF_UNCHANGED since this class is only used
     * to present logical (unchunked) records.
     *
     * @return null if valid, or a string error if invalid.
     */
    static String validateTnf(short tnf, byte[] type, byte[] id, byte[] payload) {
        switch (tnf) {
            case TNF_EMPTY:
                if (type.length != 0 || id.length != 0 || payload.length != 0) {
                    return "unexpected data in TNF_EMPTY record";
                }
                return null;
            case TNF_WELL_KNOWN:
            case TNF_MIME_MEDIA:
            case TNF_ABSOLUTE_URI:
            case TNF_EXTERNAL_TYPE:
                return null;
            case TNF_UNKNOWN:
            case TNF_RESERVED:
                if (type.length != 0) {
                    return "unexpected type field in TNF_UNKNOWN or TNF_RESERVEd record";
                }
                return null;
            case TNF_UNCHANGED:
                return "unexpected TNF_UNCHANGED in first chunk or logical record";
            default:
                return String.format("unexpected tnf value: 0x%02x", tnf);
        }
    }

    /**
     * Serialize record for network transmission.<p>
     * Uses specified MB and ME flags.<p>
     * Does not chunk records.
     */
    void writeToByteBuffer(ByteBuffer buffer, boolean mb, boolean me) {
        boolean sr = mPayload.length < 256;
        boolean il = mTnf == TNF_EMPTY ? true : mId.length > 0;

        byte flags = (byte)((mb ? FLAG_MB : 0) | (me ? FLAG_ME : 0) |
                (sr ? FLAG_SR : 0) | (il ? FLAG_IL : 0) | mTnf);
        buffer.put(flags);

        buffer.put((byte)mType.length);
        if (sr) {
            buffer.put((byte)mPayload.length);
        } else {
            buffer.putInt(mPayload.length);
        }
        if (il) {
            buffer.put((byte)mId.length);
        }

        buffer.put(mType);
        buffer.put(mId);
        buffer.put(mPayload);
    }

    /**
     * Get byte length of serialized record.
     */
    int getByteLength() {
        int length = 3 + mType.length + mId.length + mPayload.length;

        boolean sr = mPayload.length < 256;
        boolean il = mTnf == TNF_EMPTY ? true : mId.length > 0;

        if (!sr) length += 3;
        if (il) length += 1;

        return length;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mTnf);
        dest.writeInt(mType.length);
        dest.writeByteArray(mType);
        dest.writeInt(mId.length);
        dest.writeByteArray(mId);
        dest.writeInt(mPayload.length);
        dest.writeByteArray(mPayload);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<NdefRecord> CREATOR =
            new Parcelable.Creator<NdefRecord>() {
        @Override
        public NdefRecord createFromParcel(Parcel in) {
            short tnf = (short)in.readInt();
            int typeLength = in.readInt();
            byte[] type = new byte[typeLength];
            in.readByteArray(type);
            int idLength = in.readInt();
            byte[] id = new byte[idLength];
            in.readByteArray(id);
            int payloadLength = in.readInt();
            byte[] payload = new byte[payloadLength];
            in.readByteArray(payload);

            return new NdefRecord(tnf, type, id, payload);
        }
        @Override
        public NdefRecord[] newArray(int size) {
            return new NdefRecord[size];
        }
    };

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(mId);
        result = prime * result + Arrays.hashCode(mPayload);
        result = prime * result + mTnf;
        result = prime * result + Arrays.hashCode(mType);
        return result;
    }

    /**
     * Returns true if the specified NDEF Record contains
     * identical tnf, type, id and payload fields.
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        NdefRecord other = (NdefRecord) obj;
        if (!Arrays.equals(mId, other.mId)) return false;
        if (!Arrays.equals(mPayload, other.mPayload)) return false;
        if (mTnf != other.mTnf) return false;
        return Arrays.equals(mType, other.mType);
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder(String.format("NdefRecord tnf=%X", mTnf));
        if (mType.length > 0) b.append(" type=").append(bytesToString(mType));
        if (mId.length > 0) b.append(" id=").append(bytesToString(mId));
        if (mPayload.length > 0) b.append(" payload=").append(bytesToString(mPayload));
        return b.toString();
    }

    /**
     * Dump debugging information as a NdefRecordProto
     * @hide
     *
     * Note:
     * See proto definition in frameworks/base/core/proto/android/nfc/ndef.proto
     * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
     * {@link ProtoOutputStream#end(long)} after.
     * Never reuse a proto field number. When removing a field, mark it as reserved.
     */
    public void dumpDebug(ProtoOutputStream proto) {
        proto.write(NdefRecordProto.TYPE, mType);
        proto.write(NdefRecordProto.ID, mId);
        proto.write(NdefRecordProto.PAYLOAD_BYTES, mPayload.length);
    }

    private static StringBuilder bytesToString(byte[] bs) {
        StringBuilder s = new StringBuilder();
        for (byte b : bs) {
            s.append(String.format("%02X", b));
        }
        return s;
    }
}
