Home | History | Annotate | Download | only in nfc
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.nfc;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.RequiresPermission;
     21 import android.annotation.SdkConstant;
     22 import android.annotation.SdkConstant.SdkConstantType;
     23 import android.annotation.SystemApi;
     24 import android.annotation.UnsupportedAppUsage;
     25 import android.app.Activity;
     26 import android.app.ActivityThread;
     27 import android.app.OnActivityPausedListener;
     28 import android.app.PendingIntent;
     29 import android.content.Context;
     30 import android.content.IntentFilter;
     31 import android.content.pm.IPackageManager;
     32 import android.content.pm.PackageManager;
     33 import android.net.Uri;
     34 import android.nfc.tech.MifareClassic;
     35 import android.nfc.tech.Ndef;
     36 import android.nfc.tech.NfcA;
     37 import android.nfc.tech.NfcF;
     38 import android.os.Bundle;
     39 import android.os.Handler;
     40 import android.os.IBinder;
     41 import android.os.RemoteException;
     42 import android.os.ServiceManager;
     43 import android.util.Log;
     44 
     45 import java.io.IOException;
     46 import java.util.ArrayList;
     47 import java.util.HashMap;
     48 import java.util.List;
     49 
     50 /**
     51  * Represents the local NFC adapter.
     52  * <p>
     53  * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC
     54  * adapter for this Android device.
     55  *
     56  * <div class="special reference">
     57  * <h3>Developer Guides</h3>
     58  * <p>For more information about using NFC, read the
     59  * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
     60  * <p>To perform basic file sharing between devices, read
     61  * <a href="{@docRoot}training/beam-files/index.html">Sharing Files with NFC</a>.
     62  * </div>
     63  */
     64 public final class NfcAdapter {
     65     static final String TAG = "NFC";
     66 
     67     /**
     68      * Intent to start an activity when a tag with NDEF payload is discovered.
     69      *
     70      * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and
     71      * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the
     72      * intent will contain the URI in its data field. If a MIME record is found the intent will
     73      * contain the MIME type in its type field. This allows activities to register
     74      * {@link IntentFilter}s targeting specific content on tags. Activities should register the
     75      * most specific intent filters possible to avoid the activity chooser dialog, which can
     76      * disrupt the interaction with the tag as the user interacts with the screen.
     77      *
     78      * <p>If the tag has an NDEF payload this intent is started before
     79      * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither
     80      * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
     81      *
     82      * <p>The MIME type or data URI of this intent are normalized before dispatch -
     83      * so that MIME, URI scheme and URI host are always lower-case.
     84      */
     85     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     86     public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
     87 
     88     /**
     89      * Intent to start an activity when a tag is discovered and activities are registered for the
     90      * specific technologies on the tag.
     91      *
     92      * <p>To receive this intent an activity must include an intent filter
     93      * for this action and specify the desired tech types in a
     94      * manifest <code>meta-data</code> entry. Here is an example manfiest entry:
     95      * <pre>
     96      * &lt;activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"&gt;
     97      *     &lt;!-- Add a technology filter --&gt;
     98      *     &lt;intent-filter&gt;
     99      *         &lt;action android:name="android.nfc.action.TECH_DISCOVERED" /&gt;
    100      *     &lt;/intent-filter&gt;
    101      *
    102      *     &lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    103      *         android:resource="@xml/filter_nfc"
    104      *     /&gt;
    105      * &lt;/activity&gt;</pre>
    106      *
    107      * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries
    108      * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer
    109      * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA".
    110      *
    111      * <p>A tag matches if any of the
    112      * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each
    113      * of the <code>tech-list</code>s is considered independently and the
    114      * activity is considered a match is any single <code>tech-list</code> matches the tag that was
    115      * discovered. This provides AND and OR semantics for filtering desired techs. Here is an
    116      * example that will match any tag using {@link NfcF} or any tag using {@link NfcA},
    117      * {@link MifareClassic}, and {@link Ndef}:
    118      *
    119      * <pre>
    120      * &lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
    121      *     &lt;!-- capture anything using NfcF --&gt;
    122      *     &lt;tech-list&gt;
    123      *         &lt;tech&gt;android.nfc.tech.NfcF&lt;/tech&gt;
    124      *     &lt;/tech-list&gt;
    125      *
    126      *     &lt;!-- OR --&gt;
    127      *
    128      *     &lt;!-- capture all MIFARE Classics with NDEF payloads --&gt;
    129      *     &lt;tech-list&gt;
    130      *         &lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
    131      *         &lt;tech&gt;android.nfc.tech.MifareClassic&lt;/tech&gt;
    132      *         &lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
    133      *     &lt;/tech-list&gt;
    134      * &lt;/resources&gt;</pre>
    135      *
    136      * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before
    137      * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED}
    138      * this intent will not be started. If any activities respond to this intent
    139      * {@link #ACTION_TAG_DISCOVERED} will not be started.
    140      */
    141     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    142     public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
    143 
    144     /**
    145      * Intent to start an activity when a tag is discovered.
    146      *
    147      * <p>This intent will not be started when a tag is discovered if any activities respond to
    148      * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag.
    149      */
    150     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    151     public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
    152 
    153     /**
    154      * Broadcast Action: Intent to notify an application that an transaction event has occurred
    155      * on the Secure Element.
    156      *
    157      * <p>This intent will only be sent if the application has requested permission for
    158      * {@link android.Manifest.permission#NFC_TRANSACTION_EVENT} and if the application has the
    159      * necessary access to Secure Element which witnessed the particular event.
    160      */
    161     @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT)
    162     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    163     public static final String ACTION_TRANSACTION_DETECTED =
    164             "android.nfc.action.TRANSACTION_DETECTED";
    165 
    166     /**
    167      * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
    168      * @hide
    169      */
    170     public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST";
    171 
    172     /**
    173      * Mandatory extra containing the {@link Tag} that was discovered for the
    174      * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and
    175      * {@link #ACTION_TAG_DISCOVERED} intents.
    176      */
    177     public static final String EXTRA_TAG = "android.nfc.extra.TAG";
    178 
    179     /**
    180      * Extra containing an array of {@link NdefMessage} present on the discovered tag.<p>
    181      * This extra is mandatory for {@link #ACTION_NDEF_DISCOVERED} intents,
    182      * and optional for {@link #ACTION_TECH_DISCOVERED}, and
    183      * {@link #ACTION_TAG_DISCOVERED} intents.<p>
    184      * When this extra is present there will always be at least one
    185      * {@link NdefMessage} element. Most NDEF tags have only one NDEF message,
    186      * but we use an array for future compatibility.
    187      */
    188     public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
    189 
    190     /**
    191      * Optional extra containing a byte array containing the ID of the discovered tag for
    192      * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and
    193      * {@link #ACTION_TAG_DISCOVERED} intents.
    194      */
    195     public static final String EXTRA_ID = "android.nfc.extra.ID";
    196 
    197     /**
    198      * Broadcast Action: The state of the local NFC adapter has been
    199      * changed.
    200      * <p>For example, NFC has been turned on or off.
    201      * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE}
    202      */
    203     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    204     public static final String ACTION_ADAPTER_STATE_CHANGED =
    205             "android.nfc.action.ADAPTER_STATE_CHANGED";
    206 
    207     /**
    208      * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED}
    209      * intents to request the current power state. Possible values are:
    210      * {@link #STATE_OFF},
    211      * {@link #STATE_TURNING_ON},
    212      * {@link #STATE_ON},
    213      * {@link #STATE_TURNING_OFF},
    214      */
    215     public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
    216 
    217     /**
    218      * Mandatory byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED}
    219      */
    220     public static final String EXTRA_AID = "android.nfc.extra.AID";
    221 
    222     /**
    223      * Optional byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED}
    224      */
    225     public static final String EXTRA_DATA = "android.nfc.extra.DATA";
    226 
    227     /**
    228      * Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED}
    229      * Indicates the Secure Element on which the transaction occurred.
    230      * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc.
    231      */
    232     public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
    233 
    234     public static final int STATE_OFF = 1;
    235     public static final int STATE_TURNING_ON = 2;
    236     public static final int STATE_ON = 3;
    237     public static final int STATE_TURNING_OFF = 4;
    238 
    239     /**
    240      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    241      * <p>
    242      * Setting this flag enables polling for Nfc-A technology.
    243      */
    244     public static final int FLAG_READER_NFC_A = 0x1;
    245 
    246     /**
    247      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    248      * <p>
    249      * Setting this flag enables polling for Nfc-B technology.
    250      */
    251     public static final int FLAG_READER_NFC_B = 0x2;
    252 
    253     /**
    254      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    255      * <p>
    256      * Setting this flag enables polling for Nfc-F technology.
    257      */
    258     public static final int FLAG_READER_NFC_F = 0x4;
    259 
    260     /**
    261      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    262      * <p>
    263      * Setting this flag enables polling for Nfc-V (ISO15693) technology.
    264      */
    265     public static final int FLAG_READER_NFC_V = 0x8;
    266 
    267     /**
    268      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    269      * <p>
    270      * Setting this flag enables polling for NfcBarcode technology.
    271      */
    272     public static final int FLAG_READER_NFC_BARCODE = 0x10;
    273 
    274     /**
    275      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    276      * <p>
    277      * Setting this flag allows the caller to prevent the
    278      * platform from performing an NDEF check on the tags it
    279      * finds.
    280      */
    281     public static final int FLAG_READER_SKIP_NDEF_CHECK = 0x80;
    282 
    283     /**
    284      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    285      * <p>
    286      * Setting this flag allows the caller to prevent the
    287      * platform from playing sounds when it discovers a tag.
    288      */
    289     public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 0x100;
    290 
    291     /**
    292      * Int Extra for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
    293      * <p>
    294      * Setting this integer extra allows the calling application to specify
    295      * the delay that the platform will use for performing presence checks
    296      * on any discovered tag.
    297      */
    298     public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
    299 
    300     /** @hide */
    301     @SystemApi
    302     public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
    303 
    304     /** @hide */
    305     public static final String ACTION_HANDOVER_TRANSFER_STARTED =
    306             "android.nfc.action.HANDOVER_TRANSFER_STARTED";
    307 
    308     /** @hide */
    309     public static final String ACTION_HANDOVER_TRANSFER_DONE =
    310             "android.nfc.action.HANDOVER_TRANSFER_DONE";
    311 
    312     /** @hide */
    313     public static final String EXTRA_HANDOVER_TRANSFER_STATUS =
    314             "android.nfc.extra.HANDOVER_TRANSFER_STATUS";
    315 
    316     /** @hide */
    317     public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0;
    318     /** @hide */
    319     public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1;
    320 
    321     /** @hide */
    322     public static final String EXTRA_HANDOVER_TRANSFER_URI =
    323             "android.nfc.extra.HANDOVER_TRANSFER_URI";
    324 
    325     // Guarded by NfcAdapter.class
    326     static boolean sIsInitialized = false;
    327     static boolean sHasNfcFeature;
    328     static boolean sHasBeamFeature;
    329 
    330     // Final after first constructor, except for
    331     // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
    332     // recovery
    333     @UnsupportedAppUsage
    334     static INfcAdapter sService;
    335     static INfcTag sTagService;
    336     static INfcCardEmulation sCardEmulationService;
    337     static INfcFCardEmulation sNfcFCardEmulationService;
    338 
    339     /**
    340      * The NfcAdapter object for each application context.
    341      * There is a 1-1 relationship between application context and
    342      * NfcAdapter object.
    343      */
    344     static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class
    345 
    346     /**
    347      * NfcAdapter used with a null context. This ctor was deprecated but we have
    348      * to support it for backwards compatibility. New methods that require context
    349      * might throw when called on the null-context NfcAdapter.
    350      */
    351     static NfcAdapter sNullContextNfcAdapter;  // protected by NfcAdapter.class
    352 
    353     final NfcActivityManager mNfcActivityManager;
    354     final Context mContext;
    355     final HashMap<NfcUnlockHandler, INfcUnlockHandler> mNfcUnlockHandlers;
    356     final Object mLock;
    357 
    358     ITagRemovedCallback mTagRemovedListener; // protected by mLock
    359 
    360     /**
    361      * A callback to be invoked when the system finds a tag while the foreground activity is
    362      * operating in reader mode.
    363      * <p>Register your {@code ReaderCallback} implementation with {@link
    364      * NfcAdapter#enableReaderMode} and disable it with {@link
    365      * NfcAdapter#disableReaderMode}.
    366      * @see NfcAdapter#enableReaderMode
    367      */
    368     public interface ReaderCallback {
    369         public void onTagDiscovered(Tag tag);
    370     }
    371 
    372     /**
    373      * A callback to be invoked when the system successfully delivers your {@link NdefMessage}
    374      * to another device.
    375      * @see #setOnNdefPushCompleteCallback
    376      * @deprecated this feature is deprecated. File sharing can work using other technology like
    377      * Bluetooth.
    378      */
    379     @java.lang.Deprecated
    380     public interface OnNdefPushCompleteCallback {
    381         /**
    382          * Called on successful NDEF push.
    383          *
    384          * <p>This callback is usually made on a binder thread (not the UI thread).
    385          *
    386          * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
    387          * @see #setNdefPushMessageCallback
    388          */
    389         public void onNdefPushComplete(NfcEvent event);
    390     }
    391 
    392     /**
    393      * A callback to be invoked when another NFC device capable of NDEF push (Android Beam)
    394      * is within range.
    395      * <p>Implement this interface and pass it to {@link
    396      * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an
    397      * {@link NdefMessage} at the moment that another device is within range for NFC. Using this
    398      * callback allows you to create a message with data that might vary based on the
    399      * content currently visible to the user. Alternatively, you can call {@link
    400      * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
    401      * same data.
    402      * @deprecated this feature is deprecated. File sharing can work using other technology like
    403      * Bluetooth.
    404      */
    405     @java.lang.Deprecated
    406     public interface CreateNdefMessageCallback {
    407         /**
    408          * Called to provide a {@link NdefMessage} to push.
    409          *
    410          * <p>This callback is usually made on a binder thread (not the UI thread).
    411          *
    412          * <p>Called when this device is in range of another device
    413          * that might support NDEF push. It allows the application to
    414          * create the NDEF message only when it is required.
    415          *
    416          * <p>NDEF push cannot occur until this method returns, so do not
    417          * block for too long.
    418          *
    419          * <p>The Android operating system will usually show a system UI
    420          * on top of your activity during this time, so do not try to request
    421          * input from the user to complete the callback, or provide custom NDEF
    422          * push UI. The user probably will not see it.
    423          *
    424          * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
    425          * @return NDEF message to push, or null to not provide a message
    426          */
    427         public NdefMessage createNdefMessage(NfcEvent event);
    428     }
    429 
    430 
    431      /**
    432      * @deprecated this feature is deprecated. File sharing can work using other technology like
    433      * Bluetooth.
    434      */
    435     @java.lang.Deprecated
    436     public interface CreateBeamUrisCallback {
    437         public Uri[] createBeamUris(NfcEvent event);
    438     }
    439 
    440     /**
    441      * A callback that is invoked when a tag is removed from the field.
    442      * @see NfcAdapter#ignore
    443      */
    444     public interface OnTagRemovedListener {
    445         void onTagRemoved();
    446     }
    447 
    448     /**
    449      * A callback to be invoked when an application has registered as a
    450      * handler to unlock the device given an NFC tag at the lockscreen.
    451      * @hide
    452      */
    453     @SystemApi
    454     public interface NfcUnlockHandler {
    455         /**
    456          * Called at the lock screen to attempt to unlock the device with the given tag.
    457          * @param tag the detected tag, to be used to unlock the device
    458          * @return true if the device was successfully unlocked
    459          */
    460         public boolean onUnlockAttempted(Tag tag);
    461     }
    462 
    463     /**
    464      * Helper to check if this device has FEATURE_NFC_BEAM, but without using
    465      * a context.
    466      * Equivalent to
    467      * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)
    468      */
    469     private static boolean hasBeamFeature() {
    470         IPackageManager pm = ActivityThread.getPackageManager();
    471         if (pm == null) {
    472             Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature");
    473             return false;
    474         }
    475         try {
    476             return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0);
    477         } catch (RemoteException e) {
    478             Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e);
    479             return false;
    480         }
    481     }
    482 
    483     /**
    484      * Helper to check if this device has FEATURE_NFC, but without using
    485      * a context.
    486      * Equivalent to
    487      * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)
    488      */
    489     private static boolean hasNfcFeature() {
    490         IPackageManager pm = ActivityThread.getPackageManager();
    491         if (pm == null) {
    492             Log.e(TAG, "Cannot get package manager, assuming no NFC feature");
    493             return false;
    494         }
    495         try {
    496             return pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0);
    497         } catch (RemoteException e) {
    498             Log.e(TAG, "Package manager query failed, assuming no NFC feature", e);
    499             return false;
    500         }
    501     }
    502 
    503     /**
    504      * Helper to check if this device is NFC HCE capable, by checking for
    505      * FEATURE_NFC_HOST_CARD_EMULATION and/or FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
    506      * but without using a context.
    507      */
    508     private static boolean hasNfcHceFeature() {
    509         IPackageManager pm = ActivityThread.getPackageManager();
    510         if (pm == null) {
    511             Log.e(TAG, "Cannot get package manager, assuming no NFC feature");
    512             return false;
    513         }
    514         try {
    515             return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)
    516                 || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0);
    517         } catch (RemoteException e) {
    518             Log.e(TAG, "Package manager query failed, assuming no NFC feature", e);
    519             return false;
    520         }
    521     }
    522 
    523     /**
    524      * Return list of Secure Elements which support off host card emulation.
    525      *
    526      * @return List<String> containing secure elements on the device which supports
    527      *                      off host card emulation. eSE for Embedded secure element,
    528      *                      SIM for UICC and so on.
    529      * @hide
    530      */
    531     public @NonNull List<String> getSupportedOffHostSecureElements() {
    532         List<String> offHostSE = new ArrayList<String>();
    533         IPackageManager pm = ActivityThread.getPackageManager();
    534         if (pm == null) {
    535             Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature");
    536             return offHostSE;
    537         }
    538         try {
    539             if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC, 0)) {
    540                 offHostSE.add("SIM");
    541             }
    542             if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE, 0)) {
    543                 offHostSE.add("eSE");
    544             }
    545         } catch (RemoteException e) {
    546             Log.e(TAG, "Package manager query failed, assuming no off-host CE feature", e);
    547             offHostSE.clear();
    548             return offHostSE;
    549         }
    550         return offHostSE;
    551     }
    552 
    553     /**
    554      * Returns the NfcAdapter for application context,
    555      * or throws if NFC is not available.
    556      * @hide
    557      */
    558     @UnsupportedAppUsage
    559     public static synchronized NfcAdapter getNfcAdapter(Context context) {
    560         if (!sIsInitialized) {
    561             sHasNfcFeature = hasNfcFeature();
    562             sHasBeamFeature = hasBeamFeature();
    563             boolean hasHceFeature = hasNfcHceFeature();
    564             /* is this device meant to have NFC */
    565             if (!sHasNfcFeature && !hasHceFeature) {
    566                 Log.v(TAG, "this device does not have NFC support");
    567                 throw new UnsupportedOperationException();
    568             }
    569             sService = getServiceInterface();
    570             if (sService == null) {
    571                 Log.e(TAG, "could not retrieve NFC service");
    572                 throw new UnsupportedOperationException();
    573             }
    574             if (sHasNfcFeature) {
    575                 try {
    576                     sTagService = sService.getNfcTagInterface();
    577                 } catch (RemoteException e) {
    578                     Log.e(TAG, "could not retrieve NFC Tag service");
    579                     throw new UnsupportedOperationException();
    580                 }
    581             }
    582             if (hasHceFeature) {
    583                 try {
    584                     sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface();
    585                 } catch (RemoteException e) {
    586                     Log.e(TAG, "could not retrieve NFC-F card emulation service");
    587                     throw new UnsupportedOperationException();
    588                 }
    589                 try {
    590                     sCardEmulationService = sService.getNfcCardEmulationInterface();
    591                 } catch (RemoteException e) {
    592                     Log.e(TAG, "could not retrieve card emulation service");
    593                     throw new UnsupportedOperationException();
    594                 }
    595             }
    596 
    597             sIsInitialized = true;
    598         }
    599         if (context == null) {
    600             if (sNullContextNfcAdapter == null) {
    601                 sNullContextNfcAdapter = new NfcAdapter(null);
    602             }
    603             return sNullContextNfcAdapter;
    604         }
    605         NfcAdapter adapter = sNfcAdapters.get(context);
    606         if (adapter == null) {
    607             adapter = new NfcAdapter(context);
    608             sNfcAdapters.put(context, adapter);
    609         }
    610         return adapter;
    611     }
    612 
    613     /** get handle to NFC service interface */
    614     private static INfcAdapter getServiceInterface() {
    615         /* get a handle to NFC service */
    616         IBinder b = ServiceManager.getService("nfc");
    617         if (b == null) {
    618             return null;
    619         }
    620         return INfcAdapter.Stub.asInterface(b);
    621     }
    622 
    623     /**
    624      * Helper to get the default NFC Adapter.
    625      * <p>
    626      * Most Android devices will only have one NFC Adapter (NFC Controller).
    627      * <p>
    628      * This helper is the equivalent of:
    629      * <pre>
    630      * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
    631      * NfcAdapter adapter = manager.getDefaultAdapter();</pre>
    632      * @param context the calling application's context
    633      *
    634      * @return the default NFC adapter, or null if no NFC adapter exists
    635      */
    636     public static NfcAdapter getDefaultAdapter(Context context) {
    637         if (context == null) {
    638             throw new IllegalArgumentException("context cannot be null");
    639         }
    640         context = context.getApplicationContext();
    641         if (context == null) {
    642             throw new IllegalArgumentException(
    643                     "context not associated with any application (using a mock context?)");
    644         }
    645         /* use getSystemService() for consistency */
    646         NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
    647         if (manager == null) {
    648             // NFC not available
    649             return null;
    650         }
    651         return manager.getDefaultAdapter();
    652     }
    653 
    654     /**
    655      * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p>
    656      * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required
    657      * for many NFC API methods. Those methods will fail when called on an NfcAdapter
    658      * object created from this method.<p>
    659      * @deprecated use {@link #getDefaultAdapter(Context)}
    660      * @hide
    661      */
    662     @Deprecated
    663     @UnsupportedAppUsage
    664     public static NfcAdapter getDefaultAdapter() {
    665         // introduced in API version 9 (GB 2.3)
    666         // deprecated in API version 10 (GB 2.3.3)
    667         // removed from public API in version 16 (ICS MR2)
    668         // should maintain as a hidden API for binary compatibility for a little longer
    669         Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
    670                 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
    671 
    672         return NfcAdapter.getNfcAdapter(null);
    673     }
    674 
    675     NfcAdapter(Context context) {
    676         mContext = context;
    677         mNfcActivityManager = new NfcActivityManager(this);
    678         mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>();
    679         mTagRemovedListener = null;
    680         mLock = new Object();
    681     }
    682 
    683     /**
    684      * @hide
    685      */
    686     @UnsupportedAppUsage
    687     public Context getContext() {
    688         return mContext;
    689     }
    690 
    691     /**
    692      * Returns the binder interface to the service.
    693      * @hide
    694      */
    695     @UnsupportedAppUsage
    696     public INfcAdapter getService() {
    697         isEnabled();  // NOP call to recover sService if it is stale
    698         return sService;
    699     }
    700 
    701     /**
    702      * Returns the binder interface to the tag service.
    703      * @hide
    704      */
    705     public INfcTag getTagService() {
    706         isEnabled();  // NOP call to recover sTagService if it is stale
    707         return sTagService;
    708     }
    709 
    710     /**
    711      * Returns the binder interface to the card emulation service.
    712      * @hide
    713      */
    714     public INfcCardEmulation getCardEmulationService() {
    715         isEnabled();
    716         return sCardEmulationService;
    717     }
    718 
    719     /**
    720      * Returns the binder interface to the NFC-F card emulation service.
    721      * @hide
    722      */
    723     public INfcFCardEmulation getNfcFCardEmulationService() {
    724         isEnabled();
    725         return sNfcFCardEmulationService;
    726     }
    727 
    728     /**
    729      * Returns the binder interface to the NFC-DTA test interface.
    730      * @hide
    731      */
    732     public INfcDta getNfcDtaInterface() {
    733         if (mContext == null) {
    734             throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
    735                     + " NFC extras APIs");
    736         }
    737         try {
    738             return sService.getNfcDtaInterface(mContext.getPackageName());
    739         } catch (RemoteException e) {
    740             attemptDeadServiceRecovery(e);
    741             return null;
    742         }
    743     }
    744 
    745     /**
    746      * NFC service dead - attempt best effort recovery
    747      * @hide
    748      */
    749     @UnsupportedAppUsage
    750     public void attemptDeadServiceRecovery(Exception e) {
    751         Log.e(TAG, "NFC service dead - attempting to recover", e);
    752         INfcAdapter service = getServiceInterface();
    753         if (service == null) {
    754             Log.e(TAG, "could not retrieve NFC service during service recovery");
    755             // nothing more can be done now, sService is still stale, we'll hit
    756             // this recovery path again later
    757             return;
    758         }
    759         // assigning to sService is not thread-safe, but this is best-effort code
    760         // and on a well-behaved system should never happen
    761         sService = service;
    762         try {
    763             sTagService = service.getNfcTagInterface();
    764         } catch (RemoteException ee) {
    765             Log.e(TAG, "could not retrieve NFC tag service during service recovery");
    766             // nothing more can be done now, sService is still stale, we'll hit
    767             // this recovery path again later
    768             return;
    769         }
    770 
    771         try {
    772             sCardEmulationService = service.getNfcCardEmulationInterface();
    773         } catch (RemoteException ee) {
    774             Log.e(TAG, "could not retrieve NFC card emulation service during service recovery");
    775         }
    776 
    777         try {
    778             sNfcFCardEmulationService = service.getNfcFCardEmulationInterface();
    779         } catch (RemoteException ee) {
    780             Log.e(TAG, "could not retrieve NFC-F card emulation service during service recovery");
    781         }
    782 
    783         return;
    784     }
    785 
    786     /**
    787      * Return true if this NFC Adapter has any features enabled.
    788      *
    789      * <p>If this method returns false, the NFC hardware is guaranteed not to
    790      * generate or respond to any NFC communication over its NFC radio.
    791      * <p>Applications can use this to check if NFC is enabled. Applications
    792      * can request Settings UI allowing the user to toggle NFC using:
    793      * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre>
    794      *
    795      * @see android.provider.Settings#ACTION_NFC_SETTINGS
    796      * @return true if this NFC Adapter has any features enabled
    797      */
    798     public boolean isEnabled() {
    799         try {
    800             return sService.getState() == STATE_ON;
    801         } catch (RemoteException e) {
    802             attemptDeadServiceRecovery(e);
    803             return false;
    804         }
    805     }
    806 
    807     /**
    808      * Return the state of this NFC Adapter.
    809      *
    810      * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON},
    811      * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}.
    812      *
    813      * <p>{@link #isEnabled()} is equivalent to
    814      * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code>
    815      *
    816      * @return the current state of this NFC adapter
    817      *
    818      * @hide
    819      */
    820     @UnsupportedAppUsage
    821     public int getAdapterState() {
    822         try {
    823             return sService.getState();
    824         } catch (RemoteException e) {
    825             attemptDeadServiceRecovery(e);
    826             return NfcAdapter.STATE_OFF;
    827         }
    828     }
    829 
    830     /**
    831      * Enable NFC hardware.
    832      *
    833      * <p>This call is asynchronous. Listen for
    834      * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the
    835      * operation is complete.
    836      *
    837      * <p>If this returns true, then either NFC is already on, or
    838      * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent
    839      * to indicate a state transition. If this returns false, then
    840      * there is some problem that prevents an attempt to turn
    841      * NFC on (for example we are in airplane mode and NFC is not
    842      * toggleable in airplane mode on this platform).
    843      *
    844      * @hide
    845      */
    846     @SystemApi
    847     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    848     public boolean enable() {
    849         try {
    850             return sService.enable();
    851         } catch (RemoteException e) {
    852             attemptDeadServiceRecovery(e);
    853             return false;
    854         }
    855     }
    856 
    857     /**
    858      * Disable NFC hardware.
    859      *
    860      * <p>No NFC features will work after this call, and the hardware
    861      * will not perform or respond to any NFC communication.
    862      *
    863      * <p>This call is asynchronous. Listen for
    864      * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the
    865      * operation is complete.
    866      *
    867      * <p>If this returns true, then either NFC is already off, or
    868      * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent
    869      * to indicate a state transition. If this returns false, then
    870      * there is some problem that prevents an attempt to turn
    871      * NFC off.
    872      *
    873      * @hide
    874      */
    875     @SystemApi
    876     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    877     public boolean disable() {
    878         try {
    879             return sService.disable(true);
    880         } catch (RemoteException e) {
    881             attemptDeadServiceRecovery(e);
    882             return false;
    883         }
    884     }
    885 
    886     /**
    887      * Disable NFC hardware.
    888      * @hide
    889     */
    890     @SystemApi
    891     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    892     public boolean disable(boolean persist) {
    893         try {
    894             return sService.disable(persist);
    895         } catch (RemoteException e) {
    896             attemptDeadServiceRecovery(e);
    897             return false;
    898         }
    899     }
    900 
    901     /**
    902      * Pauses polling for a {@code timeoutInMs} millis. If polling must be resumed before timeout,
    903      * use {@link #resumePolling()}.
    904      * @hide
    905      */
    906     public void pausePolling(int timeoutInMs) {
    907         try {
    908             sService.pausePolling(timeoutInMs);
    909         } catch (RemoteException e) {
    910             attemptDeadServiceRecovery(e);
    911         }
    912     }
    913 
    914     /**
    915      * Resumes default polling for the current device state if polling is paused. Calling
    916      * this while polling is not paused is a no-op.
    917      *
    918      * @hide
    919      */
    920     public void resumePolling() {
    921         try {
    922             sService.resumePolling();
    923         } catch (RemoteException e) {
    924             attemptDeadServiceRecovery(e);
    925         }
    926     }
    927 
    928     /**
    929      * Set one or more {@link Uri}s to send using Android Beam (TM). Every
    930      * Uri you provide must have either scheme 'file' or scheme 'content'.
    931      *
    932      * <p>For the data provided through this method, Android Beam tries to
    933      * switch to alternate transports such as Bluetooth to achieve a fast
    934      * transfer speed. Hence this method is very suitable
    935      * for transferring large files such as pictures or songs.
    936      *
    937      * <p>The receiving side will store the content of each Uri in
    938      * a file and present a notification to the user to open the file
    939      * with a {@link android.content.Intent} with action
    940      * {@link android.content.Intent#ACTION_VIEW}.
    941      * If multiple URIs are sent, the {@link android.content.Intent} will refer
    942      * to the first of the stored files.
    943      *
    944      * <p>This method may be called at any time before {@link Activity#onDestroy},
    945      * but the URI(s) are only made available for Android Beam when the
    946      * specified activity(s) are in resumed (foreground) state. The recommended
    947      * approach is to call this method during your Activity's
    948      * {@link Activity#onCreate} - see sample
    949      * code below. This method does not immediately perform any I/O or blocking work,
    950      * so is safe to call on your main thread.
    951      *
    952      * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback}
    953      * have priority over both {@link #setNdefPushMessage} and
    954      * {@link #setNdefPushMessageCallback}.
    955      *
    956      * <p>If {@link #setBeamPushUris} is called with a null Uri array,
    957      * and/or {@link #setBeamPushUrisCallback} is called with a null callback,
    958      * then the Uri push will be completely disabled for the specified activity(s).
    959      *
    960      * <p>Code example:
    961      * <pre>
    962      * protected void onCreate(Bundle savedInstanceState) {
    963      *     super.onCreate(savedInstanceState);
    964      *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    965      *     if (nfcAdapter == null) return;  // NFC not available on this device
    966      *     nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this);
    967      * }</pre>
    968      * And that is it. Only one call per activity is necessary. The Android
    969      * OS will automatically release its references to the Uri(s) and the
    970      * Activity object when it is destroyed if you follow this pattern.
    971      *
    972      * <p>If your Activity wants to dynamically supply Uri(s),
    973      * then set a callback using {@link #setBeamPushUrisCallback} instead
    974      * of using this method.
    975      *
    976      * <p class="note">Do not pass in an Activity that has already been through
    977      * {@link Activity#onDestroy}. This is guaranteed if you call this API
    978      * during {@link Activity#onCreate}.
    979      *
    980      * <p class="note">If this device does not support alternate transports
    981      * such as Bluetooth or WiFI, calling this method does nothing.
    982      *
    983      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
    984      *
    985      * @param uris an array of Uri(s) to push over Android Beam
    986      * @param activity activity for which the Uri(s) will be pushed
    987      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
    988      * @deprecated this feature is deprecated. File sharing can work using other technology like
    989      * Bluetooth.
    990      */
    991     @java.lang.Deprecated
    992     public void setBeamPushUris(Uri[] uris, Activity activity) {
    993         synchronized (NfcAdapter.class) {
    994             if (!sHasNfcFeature) {
    995                 throw new UnsupportedOperationException();
    996             }
    997             if (!sHasBeamFeature) {
    998                 return;
    999             }
   1000         }
   1001         if (activity == null) {
   1002             throw new NullPointerException("activity cannot be null");
   1003         }
   1004         if (uris != null) {
   1005             for (Uri uri : uris) {
   1006                 if (uri == null) throw new NullPointerException("Uri not " +
   1007                         "allowed to be null");
   1008                 String scheme = uri.getScheme();
   1009                 if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
   1010                         !scheme.equalsIgnoreCase("content"))) {
   1011                     throw new IllegalArgumentException("URI needs to have " +
   1012                             "either scheme file or scheme content");
   1013                 }
   1014             }
   1015         }
   1016         mNfcActivityManager.setNdefPushContentUri(activity, uris);
   1017     }
   1018 
   1019     /**
   1020      * Set a callback that will dynamically generate one or more {@link Uri}s
   1021      * to send using Android Beam (TM). Every Uri the callback provides
   1022      * must have either scheme 'file' or scheme 'content'.
   1023      *
   1024      * <p>For the data provided through this callback, Android Beam tries to
   1025      * switch to alternate transports such as Bluetooth to achieve a fast
   1026      * transfer speed. Hence this method is very suitable
   1027      * for transferring large files such as pictures or songs.
   1028      *
   1029      * <p>The receiving side will store the content of each Uri in
   1030      * a file and present a notification to the user to open the file
   1031      * with a {@link android.content.Intent} with action
   1032      * {@link android.content.Intent#ACTION_VIEW}.
   1033      * If multiple URIs are sent, the {@link android.content.Intent} will refer
   1034      * to the first of the stored files.
   1035      *
   1036      * <p>This method may be called at any time before {@link Activity#onDestroy},
   1037      * but the URI(s) are only made available for Android Beam when the
   1038      * specified activity(s) are in resumed (foreground) state. The recommended
   1039      * approach is to call this method during your Activity's
   1040      * {@link Activity#onCreate} - see sample
   1041      * code below. This method does not immediately perform any I/O or blocking work,
   1042      * so is safe to call on your main thread.
   1043      *
   1044      * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback}
   1045      * have priority over both {@link #setNdefPushMessage} and
   1046      * {@link #setNdefPushMessageCallback}.
   1047      *
   1048      * <p>If {@link #setBeamPushUris} is called with a null Uri array,
   1049      * and/or {@link #setBeamPushUrisCallback} is called with a null callback,
   1050      * then the Uri push will be completely disabled for the specified activity(s).
   1051      *
   1052      * <p>Code example:
   1053      * <pre>
   1054      * protected void onCreate(Bundle savedInstanceState) {
   1055      *     super.onCreate(savedInstanceState);
   1056      *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
   1057      *     if (nfcAdapter == null) return;  // NFC not available on this device
   1058      *     nfcAdapter.setBeamPushUrisCallback(callback, this);
   1059      * }</pre>
   1060      * And that is it. Only one call per activity is necessary. The Android
   1061      * OS will automatically release its references to the Uri(s) and the
   1062      * Activity object when it is destroyed if you follow this pattern.
   1063      *
   1064      * <p class="note">Do not pass in an Activity that has already been through
   1065      * {@link Activity#onDestroy}. This is guaranteed if you call this API
   1066      * during {@link Activity#onCreate}.
   1067      *
   1068      * <p class="note">If this device does not support alternate transports
   1069      * such as Bluetooth or WiFI, calling this method does nothing.
   1070      *
   1071      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1072      *
   1073      * @param callback callback, or null to disable
   1074      * @param activity activity for which the Uri(s) will be pushed
   1075      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1076      * @deprecated this feature is deprecated. File sharing can work using other technology like
   1077      * Bluetooth.
   1078      */
   1079     @java.lang.Deprecated
   1080     public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
   1081         synchronized (NfcAdapter.class) {
   1082             if (!sHasNfcFeature) {
   1083                 throw new UnsupportedOperationException();
   1084             }
   1085             if (!sHasBeamFeature) {
   1086                 return;
   1087             }
   1088         }
   1089         if (activity == null) {
   1090             throw new NullPointerException("activity cannot be null");
   1091         }
   1092         mNfcActivityManager.setNdefPushContentUriCallback(activity, callback);
   1093     }
   1094 
   1095     /**
   1096      * Set a static {@link NdefMessage} to send using Android Beam (TM).
   1097      *
   1098      * <p>This method may be called at any time before {@link Activity#onDestroy},
   1099      * but the NDEF message is only made available for NDEF push when the
   1100      * specified activity(s) are in resumed (foreground) state. The recommended
   1101      * approach is to call this method during your Activity's
   1102      * {@link Activity#onCreate} - see sample
   1103      * code below. This method does not immediately perform any I/O or blocking work,
   1104      * so is safe to call on your main thread.
   1105      *
   1106      * <p>Only one NDEF message can be pushed by the currently resumed activity.
   1107      * If both {@link #setNdefPushMessage} and
   1108      * {@link #setNdefPushMessageCallback} are set, then
   1109      * the callback will take priority.
   1110      *
   1111      * <p>If neither {@link #setNdefPushMessage} or
   1112      * {@link #setNdefPushMessageCallback} have been called for your activity, then
   1113      * the Android OS may choose to send a default NDEF message on your behalf,
   1114      * such as a URI for your application.
   1115      *
   1116      * <p>If {@link #setNdefPushMessage} is called with a null NDEF message,
   1117      * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
   1118      * then NDEF push will be completely disabled for the specified activity(s).
   1119      * This also disables any default NDEF message the Android OS would have
   1120      * otherwise sent on your behalf for those activity(s).
   1121      *
   1122      * <p>If you want to prevent the Android OS from sending default NDEF
   1123      * messages completely (for all activities), you can include a
   1124      * {@code <meta-data>} element inside the {@code <application>}
   1125      * element of your AndroidManifest.xml file, like this:
   1126      * <pre>
   1127      * &lt;application ...>
   1128      *     &lt;meta-data android:name="android.nfc.disable_beam_default"
   1129      *         android:value="true" />
   1130      * &lt;/application></pre>
   1131      *
   1132      * <p>The API allows for multiple activities to be specified at a time,
   1133      * but it is strongly recommended to just register one at a time,
   1134      * and to do so during the activity's {@link Activity#onCreate}. For example:
   1135      * <pre>
   1136      * protected void onCreate(Bundle savedInstanceState) {
   1137      *     super.onCreate(savedInstanceState);
   1138      *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
   1139      *     if (nfcAdapter == null) return;  // NFC not available on this device
   1140      *     nfcAdapter.setNdefPushMessage(ndefMessage, this);
   1141      * }</pre>
   1142      * And that is it. Only one call per activity is necessary. The Android
   1143      * OS will automatically release its references to the NDEF message and the
   1144      * Activity object when it is destroyed if you follow this pattern.
   1145      *
   1146      * <p>If your Activity wants to dynamically generate an NDEF message,
   1147      * then set a callback using {@link #setNdefPushMessageCallback} instead
   1148      * of a static message.
   1149      *
   1150      * <p class="note">Do not pass in an Activity that has already been through
   1151      * {@link Activity#onDestroy}. This is guaranteed if you call this API
   1152      * during {@link Activity#onCreate}.
   1153      *
   1154      * <p class="note">For sending large content such as pictures and songs,
   1155      * consider using {@link #setBeamPushUris}, which switches to alternate transports
   1156      * such as Bluetooth to achieve a fast transfer rate.
   1157      *
   1158      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1159      *
   1160      * @param message NDEF message to push over NFC, or null to disable
   1161      * @param activity activity for which the NDEF message will be pushed
   1162      * @param activities optional additional activities, however we strongly recommend
   1163      *        to only register one at a time, and to do so in that activity's
   1164      *        {@link Activity#onCreate}
   1165      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1166      * @deprecated this feature is deprecated. File sharing can work using other technology like
   1167      * Bluetooth.
   1168      */
   1169     @java.lang.Deprecated
   1170     public void setNdefPushMessage(NdefMessage message, Activity activity,
   1171             Activity ... activities) {
   1172         synchronized (NfcAdapter.class) {
   1173             if (!sHasNfcFeature) {
   1174                 throw new UnsupportedOperationException();
   1175             }
   1176             if (!sHasBeamFeature) {
   1177                 return;
   1178             }
   1179         }
   1180         int targetSdkVersion = getSdkVersion();
   1181         try {
   1182             if (activity == null) {
   1183                 throw new NullPointerException("activity cannot be null");
   1184             }
   1185             mNfcActivityManager.setNdefPushMessage(activity, message, 0);
   1186             for (Activity a : activities) {
   1187                 if (a == null) {
   1188                     throw new NullPointerException("activities cannot contain null");
   1189                 }
   1190                 mNfcActivityManager.setNdefPushMessage(a, message, 0);
   1191             }
   1192         } catch (IllegalStateException e) {
   1193             if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
   1194                 // Less strict on old applications - just log the error
   1195                 Log.e(TAG, "Cannot call API with Activity that has already " +
   1196                         "been destroyed", e);
   1197             } else {
   1198                 // Prevent new applications from making this mistake, re-throw
   1199                 throw(e);
   1200             }
   1201         }
   1202     }
   1203 
   1204     /**
   1205      * @hide
   1206      */
   1207     @SystemApi
   1208     public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
   1209         synchronized (NfcAdapter.class) {
   1210             if (!sHasNfcFeature) {
   1211                 throw new UnsupportedOperationException();
   1212             }
   1213         }
   1214         if (activity == null) {
   1215             throw new NullPointerException("activity cannot be null");
   1216         }
   1217         mNfcActivityManager.setNdefPushMessage(activity, message, flags);
   1218     }
   1219 
   1220     /**
   1221      * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM).
   1222      *
   1223      * <p>This method may be called at any time before {@link Activity#onDestroy},
   1224      * but the NDEF message callback can only occur when the
   1225      * specified activity(s) are in resumed (foreground) state. The recommended
   1226      * approach is to call this method during your Activity's
   1227      * {@link Activity#onCreate} - see sample
   1228      * code below. This method does not immediately perform any I/O or blocking work,
   1229      * so is safe to call on your main thread.
   1230      *
   1231      * <p>Only one NDEF message can be pushed by the currently resumed activity.
   1232      * If both {@link #setNdefPushMessage} and
   1233      * {@link #setNdefPushMessageCallback} are set, then
   1234      * the callback will take priority.
   1235      *
   1236      * <p>If neither {@link #setNdefPushMessage} or
   1237      * {@link #setNdefPushMessageCallback} have been called for your activity, then
   1238      * the Android OS may choose to send a default NDEF message on your behalf,
   1239      * such as a URI for your application.
   1240      *
   1241      * <p>If {@link #setNdefPushMessage} is called with a null NDEF message,
   1242      * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
   1243      * then NDEF push will be completely disabled for the specified activity(s).
   1244      * This also disables any default NDEF message the Android OS would have
   1245      * otherwise sent on your behalf for those activity(s).
   1246      *
   1247      * <p>If you want to prevent the Android OS from sending default NDEF
   1248      * messages completely (for all activities), you can include a
   1249      * {@code <meta-data>} element inside the {@code <application>}
   1250      * element of your AndroidManifest.xml file, like this:
   1251      * <pre>
   1252      * &lt;application ...>
   1253      *     &lt;meta-data android:name="android.nfc.disable_beam_default"
   1254      *         android:value="true" />
   1255      * &lt;/application></pre>
   1256      *
   1257      * <p>The API allows for multiple activities to be specified at a time,
   1258      * but it is strongly recommended to just register one at a time,
   1259      * and to do so during the activity's {@link Activity#onCreate}. For example:
   1260      * <pre>
   1261      * protected void onCreate(Bundle savedInstanceState) {
   1262      *     super.onCreate(savedInstanceState);
   1263      *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
   1264      *     if (nfcAdapter == null) return;  // NFC not available on this device
   1265      *     nfcAdapter.setNdefPushMessageCallback(callback, this);
   1266      * }</pre>
   1267      * And that is it. Only one call per activity is necessary. The Android
   1268      * OS will automatically release its references to the callback and the
   1269      * Activity object when it is destroyed if you follow this pattern.
   1270      *
   1271      * <p class="note">Do not pass in an Activity that has already been through
   1272      * {@link Activity#onDestroy}. This is guaranteed if you call this API
   1273      * during {@link Activity#onCreate}.
   1274      * <p class="note">For sending large content such as pictures and songs,
   1275      * consider using {@link #setBeamPushUris}, which switches to alternate transports
   1276      * such as Bluetooth to achieve a fast transfer rate.
   1277      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1278      *
   1279      * @param callback callback, or null to disable
   1280      * @param activity activity for which the NDEF message will be pushed
   1281      * @param activities optional additional activities, however we strongly recommend
   1282      *        to only register one at a time, and to do so in that activity's
   1283      *        {@link Activity#onCreate}
   1284      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1285      * @deprecated this feature is deprecated. File sharing can work using other technology like
   1286      * Bluetooth.
   1287      */
   1288     @java.lang.Deprecated
   1289     public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
   1290             Activity ... activities) {
   1291         synchronized (NfcAdapter.class) {
   1292             if (!sHasNfcFeature) {
   1293                 throw new UnsupportedOperationException();
   1294             }
   1295             if (!sHasBeamFeature) {
   1296                 return;
   1297             }
   1298         }
   1299         int targetSdkVersion = getSdkVersion();
   1300         try {
   1301             if (activity == null) {
   1302                 throw new NullPointerException("activity cannot be null");
   1303             }
   1304             mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0);
   1305             for (Activity a : activities) {
   1306                 if (a == null) {
   1307                     throw new NullPointerException("activities cannot contain null");
   1308                 }
   1309                 mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0);
   1310             }
   1311         } catch (IllegalStateException e) {
   1312             if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
   1313                 // Less strict on old applications - just log the error
   1314                 Log.e(TAG, "Cannot call API with Activity that has already " +
   1315                         "been destroyed", e);
   1316             } else {
   1317                 // Prevent new applications from making this mistake, re-throw
   1318                 throw(e);
   1319             }
   1320         }
   1321     }
   1322 
   1323     /**
   1324      * @hide
   1325      */
   1326     @UnsupportedAppUsage
   1327     public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
   1328             int flags) {
   1329         if (activity == null) {
   1330             throw new NullPointerException("activity cannot be null");
   1331         }
   1332         mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags);
   1333     }
   1334 
   1335     /**
   1336      * Set a callback on successful Android Beam (TM).
   1337      *
   1338      * <p>This method may be called at any time before {@link Activity#onDestroy},
   1339      * but the callback can only occur when the
   1340      * specified activity(s) are in resumed (foreground) state. The recommended
   1341      * approach is to call this method during your Activity's
   1342      * {@link Activity#onCreate} - see sample
   1343      * code below. This method does not immediately perform any I/O or blocking work,
   1344      * so is safe to call on your main thread.
   1345      *
   1346      * <p>The API allows for multiple activities to be specified at a time,
   1347      * but it is strongly recommended to just register one at a time,
   1348      * and to do so during the activity's {@link Activity#onCreate}. For example:
   1349      * <pre>
   1350      * protected void onCreate(Bundle savedInstanceState) {
   1351      *     super.onCreate(savedInstanceState);
   1352      *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
   1353      *     if (nfcAdapter == null) return;  // NFC not available on this device
   1354      *     nfcAdapter.setOnNdefPushCompleteCallback(callback, this);
   1355      * }</pre>
   1356      * And that is it. Only one call per activity is necessary. The Android
   1357      * OS will automatically release its references to the callback and the
   1358      * Activity object when it is destroyed if you follow this pattern.
   1359      *
   1360      * <p class="note">Do not pass in an Activity that has already been through
   1361      * {@link Activity#onDestroy}. This is guaranteed if you call this API
   1362      * during {@link Activity#onCreate}.
   1363      *
   1364      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1365      *
   1366      * @param callback callback, or null to disable
   1367      * @param activity activity for which the NDEF message will be pushed
   1368      * @param activities optional additional activities, however we strongly recommend
   1369      *        to only register one at a time, and to do so in that activity's
   1370      *        {@link Activity#onCreate}
   1371      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1372      * @deprecated this feature is deprecated. File sharing can work using other technology like
   1373      * Bluetooth.
   1374      */
   1375     @java.lang.Deprecated
   1376     public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
   1377             Activity activity, Activity ... activities) {
   1378         synchronized (NfcAdapter.class) {
   1379             if (!sHasNfcFeature) {
   1380                 throw new UnsupportedOperationException();
   1381             }
   1382             if (!sHasBeamFeature) {
   1383                 return;
   1384             }
   1385         }
   1386         int targetSdkVersion = getSdkVersion();
   1387         try {
   1388             if (activity == null) {
   1389                 throw new NullPointerException("activity cannot be null");
   1390             }
   1391             mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback);
   1392             for (Activity a : activities) {
   1393                 if (a == null) {
   1394                     throw new NullPointerException("activities cannot contain null");
   1395                 }
   1396                 mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback);
   1397             }
   1398         } catch (IllegalStateException e) {
   1399             if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
   1400                 // Less strict on old applications - just log the error
   1401                 Log.e(TAG, "Cannot call API with Activity that has already " +
   1402                         "been destroyed", e);
   1403             } else {
   1404                 // Prevent new applications from making this mistake, re-throw
   1405                 throw(e);
   1406             }
   1407         }
   1408     }
   1409 
   1410     /**
   1411      * Enable foreground dispatch to the given Activity.
   1412      *
   1413      * <p>This will give give priority to the foreground activity when
   1414      * dispatching a discovered {@link Tag} to an application.
   1415      *
   1416      * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents
   1417      * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and
   1418      * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED}
   1419      * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled
   1420      * by passing in the tech lists separately. Each first level entry in the tech list represents
   1421      * an array of technologies that must all be present to match. If any of the first level sets
   1422      * match then the dispatch is routed through the given PendingIntent. In other words, the second
   1423      * level is ANDed together and the first level entries are ORed together.
   1424      *
   1425      * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters
   1426      * that acts a wild card and will cause the foreground activity to receive all tags via the
   1427      * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent.
   1428      *
   1429      * <p>This method must be called from the main thread, and only when the activity is in the
   1430      * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before
   1431      * the completion of their {@link Activity#onPause} callback to disable foreground dispatch
   1432      * after it has been enabled.
   1433      *
   1434      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1435      *
   1436      * @param activity the Activity to dispatch to
   1437      * @param intent the PendingIntent to start for the dispatch
   1438      * @param filters the IntentFilters to override dispatching for, or null to always dispatch
   1439      * @param techLists the tech lists used to perform matching for dispatching of the
   1440      *      {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent
   1441      * @throws IllegalStateException if the Activity is not currently in the foreground
   1442      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1443      */
   1444     public void enableForegroundDispatch(Activity activity, PendingIntent intent,
   1445             IntentFilter[] filters, String[][] techLists) {
   1446         synchronized (NfcAdapter.class) {
   1447             if (!sHasNfcFeature) {
   1448                 throw new UnsupportedOperationException();
   1449             }
   1450         }
   1451         if (activity == null || intent == null) {
   1452             throw new NullPointerException();
   1453         }
   1454         if (!activity.isResumed()) {
   1455             throw new IllegalStateException("Foreground dispatch can only be enabled " +
   1456                     "when your activity is resumed");
   1457         }
   1458         try {
   1459             TechListParcel parcel = null;
   1460             if (techLists != null && techLists.length > 0) {
   1461                 parcel = new TechListParcel(techLists);
   1462             }
   1463             ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
   1464                     mForegroundDispatchListener);
   1465             sService.setForegroundDispatch(intent, filters, parcel);
   1466         } catch (RemoteException e) {
   1467             attemptDeadServiceRecovery(e);
   1468         }
   1469     }
   1470 
   1471     /**
   1472      * Disable foreground dispatch to the given activity.
   1473      *
   1474      * <p>After calling {@link #enableForegroundDispatch}, an activity
   1475      * must call this method before its {@link Activity#onPause} callback
   1476      * completes.
   1477      *
   1478      * <p>This method must be called from the main thread.
   1479      *
   1480      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1481      *
   1482      * @param activity the Activity to disable dispatch to
   1483      * @throws IllegalStateException if the Activity has already been paused
   1484      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1485      */
   1486     public void disableForegroundDispatch(Activity activity) {
   1487         synchronized (NfcAdapter.class) {
   1488             if (!sHasNfcFeature) {
   1489                 throw new UnsupportedOperationException();
   1490             }
   1491         }
   1492         ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
   1493                 mForegroundDispatchListener);
   1494         disableForegroundDispatchInternal(activity, false);
   1495     }
   1496 
   1497     OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
   1498         @Override
   1499         public void onPaused(Activity activity) {
   1500             disableForegroundDispatchInternal(activity, true);
   1501         }
   1502     };
   1503 
   1504     void disableForegroundDispatchInternal(Activity activity, boolean force) {
   1505         try {
   1506             sService.setForegroundDispatch(null, null, null);
   1507             if (!force && !activity.isResumed()) {
   1508                 throw new IllegalStateException("You must disable foreground dispatching " +
   1509                         "while your activity is still resumed");
   1510             }
   1511         } catch (RemoteException e) {
   1512             attemptDeadServiceRecovery(e);
   1513         }
   1514     }
   1515 
   1516     /**
   1517      * Limit the NFC controller to reader mode while this Activity is in the foreground.
   1518      *
   1519      * <p>In this mode the NFC controller will only act as an NFC tag reader/writer,
   1520      * thus disabling any peer-to-peer (Android Beam) and card-emulation modes of
   1521      * the NFC adapter on this device.
   1522      *
   1523      * <p>Use {@link #FLAG_READER_SKIP_NDEF_CHECK} to prevent the platform from
   1524      * performing any NDEF checks in reader mode. Note that this will prevent the
   1525      * {@link Ndef} tag technology from being enumerated on the tag, and that
   1526      * NDEF-based tag dispatch will not be functional.
   1527      *
   1528      * <p>For interacting with tags that are emulated on another Android device
   1529      * using Android's host-based card-emulation, the recommended flags are
   1530      * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}.
   1531      *
   1532      * @param activity the Activity that requests the adapter to be in reader mode
   1533      * @param callback the callback to be called when a tag is discovered
   1534      * @param flags Flags indicating poll technologies and other optional parameters
   1535      * @param extras Additional extras for configuring reader mode.
   1536      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1537      */
   1538     public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
   1539             Bundle extras) {
   1540         synchronized (NfcAdapter.class) {
   1541             if (!sHasNfcFeature) {
   1542                 throw new UnsupportedOperationException();
   1543             }
   1544         }
   1545         mNfcActivityManager.enableReaderMode(activity, callback, flags, extras);
   1546     }
   1547 
   1548     /**
   1549      * Restore the NFC adapter to normal mode of operation: supporting
   1550      * peer-to-peer (Android Beam), card emulation, and polling for
   1551      * all supported tag technologies.
   1552      *
   1553      * @param activity the Activity that currently has reader mode enabled
   1554      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1555      */
   1556     public void disableReaderMode(Activity activity) {
   1557         synchronized (NfcAdapter.class) {
   1558             if (!sHasNfcFeature) {
   1559                 throw new UnsupportedOperationException();
   1560             }
   1561         }
   1562         mNfcActivityManager.disableReaderMode(activity);
   1563     }
   1564 
   1565     /**
   1566      * Manually invoke Android Beam to share data.
   1567      *
   1568      * <p>The Android Beam animation is normally only shown when two NFC-capable
   1569      * devices come into range.
   1570      * By calling this method, an Activity can invoke the Beam animation directly
   1571      * even if no other NFC device is in range yet. The Beam animation will then
   1572      * prompt the user to tap another NFC-capable device to complete the data
   1573      * transfer.
   1574      *
   1575      * <p>The main advantage of using this method is that it avoids the need for the
   1576      * user to tap the screen to complete the transfer, as this method already
   1577      * establishes the direction of the transfer and the consent of the user to
   1578      * share data. Callers are responsible for making sure that the user has
   1579      * consented to sharing data on NFC tap.
   1580      *
   1581      * <p>Note that to use this method, the passed in Activity must have already
   1582      * set data to share over Beam by using method calls such as
   1583      * {@link #setNdefPushMessageCallback} or
   1584      * {@link #setBeamPushUrisCallback}.
   1585      *
   1586      * @param activity the current foreground Activity that has registered data to share
   1587      * @return whether the Beam animation was successfully invoked
   1588      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1589      * @deprecated this feature is deprecated. File sharing can work using other technology like
   1590      * Bluetooth.
   1591      */
   1592     @java.lang.Deprecated
   1593     public boolean invokeBeam(Activity activity) {
   1594         synchronized (NfcAdapter.class) {
   1595             if (!sHasNfcFeature) {
   1596                 throw new UnsupportedOperationException();
   1597             }
   1598             if (!sHasBeamFeature) {
   1599                 return false;
   1600             }
   1601         }
   1602         if (activity == null) {
   1603             throw new NullPointerException("activity may not be null.");
   1604         }
   1605         enforceResumed(activity);
   1606         try {
   1607             sService.invokeBeam();
   1608             return true;
   1609         } catch (RemoteException e) {
   1610             Log.e(TAG, "invokeBeam: NFC process has died.");
   1611             attemptDeadServiceRecovery(e);
   1612             return false;
   1613         }
   1614     }
   1615 
   1616     /**
   1617      * @hide
   1618      */
   1619     public boolean invokeBeam(BeamShareData shareData) {
   1620         try {
   1621             Log.e(TAG, "invokeBeamInternal()");
   1622             sService.invokeBeamInternal(shareData);
   1623             return true;
   1624         } catch (RemoteException e) {
   1625             Log.e(TAG, "invokeBeam: NFC process has died.");
   1626             attemptDeadServiceRecovery(e);
   1627             return false;
   1628         }
   1629     }
   1630 
   1631     /**
   1632      * Enable NDEF message push over NFC while this Activity is in the foreground.
   1633      *
   1634      * <p>You must explicitly call this method every time the activity is
   1635      * resumed, and you must call {@link #disableForegroundNdefPush} before
   1636      * your activity completes {@link Activity#onPause}.
   1637      *
   1638      * <p>Strongly recommend to use the new {@link #setNdefPushMessage}
   1639      * instead: it automatically hooks into your activity life-cycle,
   1640      * so you do not need to call enable/disable in your onResume/onPause.
   1641      *
   1642      * <p>For NDEF push to function properly the other NFC device must
   1643      * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or
   1644      * Android's "com.android.npp" (Ndef Push Protocol). This was optional
   1645      * on Gingerbread level Android NFC devices, but SNEP is mandatory on
   1646      * Ice-Cream-Sandwich and beyond.
   1647      *
   1648      * <p>This method must be called from the main thread.
   1649      *
   1650      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1651      *
   1652      * @param activity foreground activity
   1653      * @param message a NDEF Message to push over NFC
   1654      * @throws IllegalStateException if the activity is not currently in the foreground
   1655      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1656      * @deprecated use {@link #setNdefPushMessage} instead
   1657      */
   1658     @Deprecated
   1659     public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
   1660         synchronized (NfcAdapter.class) {
   1661             if (!sHasNfcFeature) {
   1662                 throw new UnsupportedOperationException();
   1663             }
   1664             if (!sHasBeamFeature) {
   1665                 return;
   1666             }
   1667         }
   1668         if (activity == null || message == null) {
   1669             throw new NullPointerException();
   1670         }
   1671         enforceResumed(activity);
   1672         mNfcActivityManager.setNdefPushMessage(activity, message, 0);
   1673     }
   1674 
   1675     /**
   1676      * Disable NDEF message push over P2P.
   1677      *
   1678      * <p>After calling {@link #enableForegroundNdefPush}, an activity
   1679      * must call this method before its {@link Activity#onPause} callback
   1680      * completes.
   1681      *
   1682      * <p>Strongly recommend to use the new {@link #setNdefPushMessage}
   1683      * instead: it automatically hooks into your activity life-cycle,
   1684      * so you do not need to call enable/disable in your onResume/onPause.
   1685      *
   1686      * <p>This method must be called from the main thread.
   1687      *
   1688      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
   1689      *
   1690      * @param activity the Foreground activity
   1691      * @throws IllegalStateException if the Activity has already been paused
   1692      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1693      * @deprecated use {@link #setNdefPushMessage} instead
   1694      */
   1695     @Deprecated
   1696     public void disableForegroundNdefPush(Activity activity) {
   1697         synchronized (NfcAdapter.class) {
   1698             if (!sHasNfcFeature) {
   1699                 throw new UnsupportedOperationException();
   1700             }
   1701             if (!sHasBeamFeature) {
   1702                 return;
   1703             }
   1704         }
   1705         if (activity == null) {
   1706             throw new NullPointerException();
   1707         }
   1708         enforceResumed(activity);
   1709         mNfcActivityManager.setNdefPushMessage(activity, null, 0);
   1710         mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0);
   1711         mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
   1712     }
   1713 
   1714     /**
   1715      * Sets Secure NFC feature.
   1716      * <p>This API is for the Settings application.
   1717      * @return True if successful
   1718      * @hide
   1719      */
   1720     @SystemApi
   1721     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
   1722     public boolean enableSecureNfc(boolean enable) {
   1723         if (!sHasNfcFeature) {
   1724             throw new UnsupportedOperationException();
   1725         }
   1726         try {
   1727             return sService.setNfcSecure(enable);
   1728         } catch (RemoteException e) {
   1729             attemptDeadServiceRecovery(e);
   1730             return false;
   1731         }
   1732     }
   1733 
   1734     /**
   1735      * Checks if the device supports Secure NFC functionality.
   1736      *
   1737      * @return True if device supports Secure NFC, false otherwise
   1738      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1739      */
   1740     public boolean isSecureNfcSupported() {
   1741         if (!sHasNfcFeature) {
   1742             throw new UnsupportedOperationException();
   1743         }
   1744         try {
   1745             return sService.deviceSupportsNfcSecure();
   1746         } catch (RemoteException e) {
   1747             attemptDeadServiceRecovery(e);
   1748             return false;
   1749         }
   1750     }
   1751 
   1752     /**
   1753      * Checks Secure NFC feature is enabled.
   1754      *
   1755      * @return True if Secure NFC is enabled, false otherwise
   1756      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1757      * @throws UnsupportedOperationException if device doesn't support
   1758      *         Secure NFC functionality. {@link #isSecureNfcSupported}
   1759      */
   1760     public boolean isSecureNfcEnabled() {
   1761         if (!sHasNfcFeature) {
   1762             throw new UnsupportedOperationException();
   1763         }
   1764         try {
   1765             return sService.isNfcSecureEnabled();
   1766         } catch (RemoteException e) {
   1767             attemptDeadServiceRecovery(e);
   1768             return false;
   1769         }
   1770     }
   1771 
   1772     /**
   1773      * Enable NDEF Push feature.
   1774      * <p>This API is for the Settings application.
   1775      * @hide
   1776      */
   1777     @SystemApi
   1778     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
   1779     public boolean enableNdefPush() {
   1780         if (!sHasNfcFeature) {
   1781             throw new UnsupportedOperationException();
   1782         }
   1783         try {
   1784             return sService.enableNdefPush();
   1785         } catch (RemoteException e) {
   1786             attemptDeadServiceRecovery(e);
   1787             return false;
   1788         }
   1789     }
   1790 
   1791     /**
   1792      * Disable NDEF Push feature.
   1793      * <p>This API is for the Settings application.
   1794      * @hide
   1795      */
   1796     @SystemApi
   1797     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
   1798     public boolean disableNdefPush() {
   1799         synchronized (NfcAdapter.class) {
   1800             if (!sHasNfcFeature) {
   1801                 throw new UnsupportedOperationException();
   1802             }
   1803         }
   1804         try {
   1805             return sService.disableNdefPush();
   1806         } catch (RemoteException e) {
   1807             attemptDeadServiceRecovery(e);
   1808             return false;
   1809         }
   1810     }
   1811 
   1812     /**
   1813      * Return true if the NDEF Push (Android Beam) feature is enabled.
   1814      * <p>This function will return true only if both NFC is enabled, and the
   1815      * NDEF Push feature is enabled.
   1816      * <p>Note that if NFC is enabled but NDEF Push is disabled then this
   1817      * device can still <i>receive</i> NDEF messages, it just cannot send them.
   1818      * <p>Applications cannot directly toggle the NDEF Push feature, but they
   1819      * can request Settings UI allowing the user to toggle NDEF Push using
   1820      * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code>
   1821      * <p>Example usage in an Activity that requires NDEF Push:
   1822      * <p><pre>
   1823      * protected void onResume() {
   1824      *     super.onResume();
   1825      *     if (!nfcAdapter.isEnabled()) {
   1826      *         startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
   1827      *     } else if (!nfcAdapter.isNdefPushEnabled()) {
   1828      *         startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
   1829      *     }
   1830      * }</pre>
   1831      *
   1832      * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
   1833      * @return true if NDEF Push feature is enabled
   1834      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
   1835      * @deprecated this feature is deprecated. File sharing can work using other technology like
   1836      * Bluetooth.
   1837      */
   1838     @java.lang.Deprecated
   1839 
   1840     public boolean isNdefPushEnabled() {
   1841         synchronized (NfcAdapter.class) {
   1842             if (!sHasNfcFeature) {
   1843                 throw new UnsupportedOperationException();
   1844             }
   1845             if (!sHasBeamFeature) {
   1846                 return false;
   1847             }
   1848         }
   1849         try {
   1850             return sService.isNdefPushEnabled();
   1851         } catch (RemoteException e) {
   1852             attemptDeadServiceRecovery(e);
   1853             return false;
   1854         }
   1855     }
   1856 
   1857     /**
   1858      * Signals that you are no longer interested in communicating with an NFC tag
   1859      * for as long as it remains in range.
   1860      *
   1861      * All future attempted communication to this tag will fail with {@link IOException}.
   1862      * The NFC controller will be put in a low-power polling mode, allowing the device
   1863      * to save power in cases where it's "attached" to a tag all the time (e.g. a tag in
   1864      * car dock).
   1865      *
   1866      * Additionally the debounceMs parameter allows you to specify for how long the tag needs
   1867      * to have gone out of range, before it will be dispatched again.
   1868      *
   1869      * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms).
   1870      * This means that if the tag repeatedly goes in and out of range (for example, in
   1871      * case of a flaky connection), and the controller happens to poll every time the
   1872      * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag
   1873      * having been "in range" during the interval.
   1874      *
   1875      * Note 2: if a tag with another UID is detected after this API is called, its effect
   1876      * will be cancelled; if this tag shows up before the amount of time specified in
   1877      * debounceMs, it will be dispatched again.
   1878      *
   1879      * Note 3: some tags have a random UID, in which case this API won't work reliably.
   1880      *
   1881      * @param tag        the {@link android.nfc.Tag Tag} to ignore.
   1882      * @param debounceMs minimum amount of time the tag needs to be out of range before being
   1883      *                   dispatched again.
   1884      * @param tagRemovedListener listener to be called when the tag is removed from the field.
   1885      *                           Note that this will only be called if the tag has been out of range
   1886      *                           for at least debounceMs, or if another tag came into range before
   1887      *                           debounceMs. May be null in case you don't want a callback.
   1888      * @param handler the {@link android.os.Handler Handler} that will be used for delivering
   1889      *                the callback. if the handler is null, then the thread used for delivering
   1890      *                the callback is unspecified.
   1891      * @return false if the tag couldn't be found (or has already gone out of range), true otherwise
   1892      */
   1893     public boolean ignore(final Tag tag, int debounceMs,
   1894                           final OnTagRemovedListener tagRemovedListener, final Handler handler) {
   1895         ITagRemovedCallback.Stub iListener = null;
   1896         if (tagRemovedListener != null) {
   1897             iListener = new ITagRemovedCallback.Stub() {
   1898                 @Override
   1899                 public void onTagRemoved() throws RemoteException {
   1900                     if (handler != null) {
   1901                         handler.post(new Runnable() {
   1902                             @Override
   1903                             public void run() {
   1904                                 tagRemovedListener.onTagRemoved();
   1905                             }
   1906                         });
   1907                     } else {
   1908                         tagRemovedListener.onTagRemoved();
   1909                     }
   1910                     synchronized (mLock) {
   1911                         mTagRemovedListener = null;
   1912                     }
   1913                 }
   1914             };
   1915         }
   1916         synchronized (mLock) {
   1917             mTagRemovedListener = iListener;
   1918         }
   1919         try {
   1920             return sService.ignore(tag.getServiceHandle(), debounceMs, iListener);
   1921         } catch (RemoteException e) {
   1922             return false;
   1923         }
   1924     }
   1925 
   1926     /**
   1927      * Inject a mock NFC tag.<p>
   1928      * Used for testing purposes.
   1929      * <p class="note">Requires the
   1930      * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
   1931      * @hide
   1932      */
   1933     public void dispatch(Tag tag) {
   1934         if (tag == null) {
   1935             throw new NullPointerException("tag cannot be null");
   1936         }
   1937         try {
   1938             sService.dispatch(tag);
   1939         } catch (RemoteException e) {
   1940             attemptDeadServiceRecovery(e);
   1941         }
   1942     }
   1943 
   1944     /**
   1945      * @hide
   1946      */
   1947     public void setP2pModes(int initiatorModes, int targetModes) {
   1948         try {
   1949             sService.setP2pModes(initiatorModes, targetModes);
   1950         } catch (RemoteException e) {
   1951             attemptDeadServiceRecovery(e);
   1952         }
   1953     }
   1954 
   1955     /**
   1956      * Registers a new NFC unlock handler with the NFC service.
   1957      *
   1958      * <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted
   1959      * NFC device. The handler should return true if it successfully authenticates the user and
   1960      * unlocks the keyguard.
   1961      *
   1962      * <p /> The parameter {@code tagTechnologies} determines which Tag technologies will be polled for
   1963      * at the lockscreen. Polling for less tag technologies reduces latency, and so it is
   1964      * strongly recommended to only provide the Tag technologies that the handler is expected to
   1965      * receive. There must be at least one tag technology provided, otherwise the unlock handler
   1966      * is ignored.
   1967      *
   1968      * @hide
   1969      */
   1970     @SystemApi
   1971     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
   1972     public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
   1973                                        String[] tagTechnologies) {
   1974         synchronized (NfcAdapter.class) {
   1975             if (!sHasNfcFeature) {
   1976                 throw new UnsupportedOperationException();
   1977             }
   1978         }
   1979         // If there are no tag technologies, don't bother adding unlock handler
   1980         if (tagTechnologies.length == 0) {
   1981             return false;
   1982         }
   1983 
   1984         try {
   1985             synchronized (mLock) {
   1986                 if (mNfcUnlockHandlers.containsKey(unlockHandler)) {
   1987                     // update the tag technologies
   1988                     sService.removeNfcUnlockHandler(mNfcUnlockHandlers.get(unlockHandler));
   1989                     mNfcUnlockHandlers.remove(unlockHandler);
   1990                 }
   1991 
   1992                 INfcUnlockHandler.Stub iHandler = new INfcUnlockHandler.Stub() {
   1993                     @Override
   1994                     public boolean onUnlockAttempted(Tag tag) throws RemoteException {
   1995                         return unlockHandler.onUnlockAttempted(tag);
   1996                     }
   1997                 };
   1998 
   1999                 sService.addNfcUnlockHandler(iHandler,
   2000                         Tag.getTechCodesFromStrings(tagTechnologies));
   2001                 mNfcUnlockHandlers.put(unlockHandler, iHandler);
   2002             }
   2003         } catch (RemoteException e) {
   2004             attemptDeadServiceRecovery(e);
   2005             return false;
   2006         } catch (IllegalArgumentException e) {
   2007             Log.e(TAG, "Unable to register LockscreenDispatch", e);
   2008             return false;
   2009         }
   2010 
   2011         return true;
   2012     }
   2013 
   2014     /**
   2015      * Removes a previously registered unlock handler. Also removes the tag technologies
   2016      * associated with the removed unlock handler.
   2017      *
   2018      * @hide
   2019      */
   2020     @SystemApi
   2021     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
   2022     public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
   2023         synchronized (NfcAdapter.class) {
   2024             if (!sHasNfcFeature) {
   2025                 throw new UnsupportedOperationException();
   2026             }
   2027         }
   2028         try {
   2029             synchronized (mLock) {
   2030                 if (mNfcUnlockHandlers.containsKey(unlockHandler)) {
   2031                     sService.removeNfcUnlockHandler(mNfcUnlockHandlers.remove(unlockHandler));
   2032                 }
   2033 
   2034                 return true;
   2035             }
   2036         } catch (RemoteException e) {
   2037             attemptDeadServiceRecovery(e);
   2038             return false;
   2039         }
   2040     }
   2041 
   2042     /**
   2043      * @hide
   2044      */
   2045     @UnsupportedAppUsage
   2046     public INfcAdapterExtras getNfcAdapterExtrasInterface() {
   2047         if (mContext == null) {
   2048             throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
   2049                     + " NFC extras APIs");
   2050         }
   2051         try {
   2052             return sService.getNfcAdapterExtrasInterface(mContext.getPackageName());
   2053         } catch (RemoteException e) {
   2054             attemptDeadServiceRecovery(e);
   2055             return null;
   2056         }
   2057     }
   2058 
   2059     void enforceResumed(Activity activity) {
   2060         if (!activity.isResumed()) {
   2061             throw new IllegalStateException("API cannot be called while activity is paused");
   2062         }
   2063     }
   2064 
   2065     int getSdkVersion() {
   2066         if (mContext == null) {
   2067             return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess
   2068         } else {
   2069             return mContext.getApplicationInfo().targetSdkVersion;
   2070         }
   2071     }
   2072 }
   2073