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.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.IntRange; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SdkConstant; 28 import android.annotation.SdkConstant.SdkConstantType; 29 import android.annotation.SuppressLint; 30 import android.annotation.SystemApi; 31 import android.annotation.TestApi; 32 import android.annotation.UserIdInt; 33 import android.app.Activity; 34 import android.app.PendingIntent; 35 import android.compat.annotation.UnsupportedAppUsage; 36 import android.content.Context; 37 import android.content.IntentFilter; 38 import android.content.pm.PackageManager; 39 import android.content.pm.ResolveInfo; 40 import android.net.Uri; 41 import android.nfc.cardemulation.PollingFrame; 42 import android.nfc.tech.MifareClassic; 43 import android.nfc.tech.Ndef; 44 import android.nfc.tech.NfcA; 45 import android.nfc.tech.NfcF; 46 import android.os.Binder; 47 import android.os.Build; 48 import android.os.Bundle; 49 import android.os.Handler; 50 import android.os.IBinder; 51 import android.os.RemoteException; 52 import android.util.Log; 53 54 import java.io.IOException; 55 import java.lang.annotation.Retention; 56 import java.lang.annotation.RetentionPolicy; 57 import java.util.ArrayList; 58 import java.util.Collections; 59 import java.util.HashMap; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.Objects; 63 import java.util.concurrent.Executor; 64 65 /** 66 * Represents the local NFC adapter. 67 * <p> 68 * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC 69 * adapter for this Android device. 70 * 71 * <div class="special reference"> 72 * <h3>Developer Guides</h3> 73 * <p>For more information about using NFC, read the 74 * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p> 75 * <p>To perform basic file sharing between devices, read 76 * <a href="{@docRoot}training/beam-files/index.html">Sharing Files with NFC</a>. 77 * </div> 78 */ 79 public final class NfcAdapter { 80 static final String TAG = "NFC"; 81 82 private final NfcControllerAlwaysOnListener mControllerAlwaysOnListener; 83 private final NfcWlcStateListener mNfcWlcStateListener; 84 private final NfcVendorNciCallbackListener mNfcVendorNciCallbackListener; 85 86 /** 87 * Intent to start an activity when a tag with NDEF payload is discovered. 88 * 89 * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and 90 * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the 91 * intent will contain the URI in its data field. If a MIME record is found the intent will 92 * contain the MIME type in its type field. This allows activities to register 93 * {@link IntentFilter}s targeting specific content on tags. Activities should register the 94 * most specific intent filters possible to avoid the activity chooser dialog, which can 95 * disrupt the interaction with the tag as the user interacts with the screen. 96 * 97 * <p>If the tag has an NDEF payload this intent is started before 98 * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither 99 * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started. 100 * 101 * <p>The MIME type or data URI of this intent are normalized before dispatch - 102 * so that MIME, URI scheme and URI host are always lower-case. 103 */ 104 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 105 public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; 106 107 /** 108 * Intent to start an activity when a tag is discovered and activities are registered for the 109 * specific technologies on the tag. 110 * 111 * <p>To receive this intent an activity must include an intent filter 112 * for this action and specify the desired tech types in a 113 * manifest <code>meta-data</code> entry. Here is an example manfiest entry: 114 * <pre> 115 * <activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"> 116 * <!-- Add a technology filter --> 117 * <intent-filter> 118 * <action android:name="android.nfc.action.TECH_DISCOVERED" /> 119 * </intent-filter> 120 * 121 * <meta-data android:name="android.nfc.action.TECH_DISCOVERED" 122 * android:resource="@xml/filter_nfc" 123 * /> 124 * </activity></pre> 125 * 126 * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries 127 * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer 128 * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA". 129 * 130 * <p>A tag matches if any of the 131 * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each 132 * of the <code>tech-list</code>s is considered independently and the 133 * activity is considered a match is any single <code>tech-list</code> matches the tag that was 134 * discovered. This provides AND and OR semantics for filtering desired techs. Here is an 135 * example that will match any tag using {@link NfcF} or any tag using {@link NfcA}, 136 * {@link MifareClassic}, and {@link Ndef}: 137 * 138 * <pre> 139 * <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 140 * <!-- capture anything using NfcF --> 141 * <tech-list> 142 * <tech>android.nfc.tech.NfcF</tech> 143 * </tech-list> 144 * 145 * <!-- OR --> 146 * 147 * <!-- capture all MIFARE Classics with NDEF payloads --> 148 * <tech-list> 149 * <tech>android.nfc.tech.NfcA</tech> 150 * <tech>android.nfc.tech.MifareClassic</tech> 151 * <tech>android.nfc.tech.Ndef</tech> 152 * </tech-list> 153 * </resources></pre> 154 * 155 * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before 156 * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED} 157 * this intent will not be started. If any activities respond to this intent 158 * {@link #ACTION_TAG_DISCOVERED} will not be started. 159 */ 160 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 161 public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; 162 163 /** 164 * Intent to start an activity when a tag is discovered. 165 * 166 * <p>This intent will not be started when a tag is discovered if any activities respond to 167 * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag. 168 */ 169 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 170 public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; 171 172 /** 173 * Broadcast Action: Intent to notify an application that a transaction event has occurred 174 * on the Secure Element. 175 * 176 * <p>This intent will only be sent if the application has requested permission for 177 * {@link android.Manifest.permission#NFC_TRANSACTION_EVENT} and if the application has the 178 * necessary access to Secure Element which witnessed the particular event. 179 */ 180 @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) 181 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 182 public static final String ACTION_TRANSACTION_DETECTED = 183 "android.nfc.action.TRANSACTION_DETECTED"; 184 185 /** 186 * Broadcast Action: Intent to notify if the preferred payment service changed. 187 * 188 * <p>This intent will only be sent to the application has requested permission for 189 * {@link android.Manifest.permission#NFC_PREFERRED_PAYMENT_INFO} and if the application 190 * has the necessary access to Secure Element which witnessed the particular event. 191 */ 192 @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) 193 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 194 public static final String ACTION_PREFERRED_PAYMENT_CHANGED = 195 "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; 196 197 /** 198 * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED 199 * @hide 200 */ 201 public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST"; 202 203 /** 204 * Mandatory extra containing the {@link Tag} that was discovered for the 205 * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 206 * {@link #ACTION_TAG_DISCOVERED} intents. 207 */ 208 public static final String EXTRA_TAG = "android.nfc.extra.TAG"; 209 210 /** 211 * Extra containing an array of {@link NdefMessage} present on the discovered tag.<p> 212 * This extra is mandatory for {@link #ACTION_NDEF_DISCOVERED} intents, 213 * and optional for {@link #ACTION_TECH_DISCOVERED}, and 214 * {@link #ACTION_TAG_DISCOVERED} intents.<p> 215 * When this extra is present there will always be at least one 216 * {@link NdefMessage} element. Most NDEF tags have only one NDEF message, 217 * but we use an array for future compatibility. 218 */ 219 public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; 220 221 /** 222 * Optional extra containing a byte array containing the ID of the discovered tag for 223 * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 224 * {@link #ACTION_TAG_DISCOVERED} intents. 225 */ 226 public static final String EXTRA_ID = "android.nfc.extra.ID"; 227 228 /** 229 * Broadcast Action: The state of the local NFC adapter has been 230 * changed. 231 * <p>For example, NFC has been turned on or off. 232 * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE} 233 */ 234 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 235 public static final String ACTION_ADAPTER_STATE_CHANGED = 236 "android.nfc.action.ADAPTER_STATE_CHANGED"; 237 238 /** 239 * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED} 240 * intents to request the current power state. Possible values are: 241 * {@link #STATE_OFF}, 242 * {@link #STATE_TURNING_ON}, 243 * {@link #STATE_ON}, 244 * {@link #STATE_TURNING_OFF}, 245 */ 246 public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE"; 247 248 /** 249 * Mandatory byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED} 250 */ 251 public static final String EXTRA_AID = "android.nfc.extra.AID"; 252 253 /** 254 * Optional byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED} 255 */ 256 public static final String EXTRA_DATA = "android.nfc.extra.DATA"; 257 258 /** 259 * Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED} 260 * Indicates the Secure Element on which the transaction occurred. 261 * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc. 262 */ 263 public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME"; 264 265 /** 266 * Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED} 267 * Indicates the condition when trigger this event. Possible values are: 268 * {@link #PREFERRED_PAYMENT_LOADED}, 269 * {@link #PREFERRED_PAYMENT_CHANGED}, 270 * {@link #PREFERRED_PAYMENT_UPDATED}, 271 */ 272 public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = 273 "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON"; 274 /** 275 * Nfc is enabled and the preferred payment aids are registered. 276 */ 277 public static final int PREFERRED_PAYMENT_LOADED = 1; 278 /** 279 * User selected another payment application as the preferred payment. 280 */ 281 public static final int PREFERRED_PAYMENT_CHANGED = 2; 282 /** 283 * Current preferred payment has issued an update (registered/unregistered new aids or has been 284 * updated itself). 285 */ 286 public static final int PREFERRED_PAYMENT_UPDATED = 3; 287 288 public static final int STATE_OFF = 1; 289 public static final int STATE_TURNING_ON = 2; 290 public static final int STATE_ON = 3; 291 public static final int STATE_TURNING_OFF = 4; 292 293 /** 294 * Possible states from {@link #getAdapterState}. 295 * 296 * @hide 297 */ 298 @IntDef(prefix = { "STATE_" }, value = { 299 STATE_OFF, 300 STATE_TURNING_ON, 301 STATE_ON, 302 STATE_TURNING_OFF 303 }) 304 @Retention(RetentionPolicy.SOURCE) 305 public @interface AdapterState{} 306 307 /** 308 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 309 * <p> 310 * Setting this flag enables polling for Nfc-A technology. 311 */ 312 public static final int FLAG_READER_NFC_A = 0x1; 313 314 /** 315 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 316 * <p> 317 * Setting this flag enables polling for Nfc-B technology. 318 */ 319 public static final int FLAG_READER_NFC_B = 0x2; 320 321 /** 322 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 323 * <p> 324 * Setting this flag enables polling for Nfc-F technology. 325 */ 326 public static final int FLAG_READER_NFC_F = 0x4; 327 328 /** 329 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 330 * <p> 331 * Setting this flag enables polling for Nfc-V (ISO15693) technology. 332 */ 333 public static final int FLAG_READER_NFC_V = 0x8; 334 335 /** 336 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 337 * <p> 338 * Setting this flag enables polling for NfcBarcode technology. 339 */ 340 public static final int FLAG_READER_NFC_BARCODE = 0x10; 341 342 /** @hide */ 343 @IntDef(flag = true, value = { 344 FLAG_SET_DEFAULT_TECH, 345 FLAG_READER_KEEP, 346 FLAG_READER_DISABLE, 347 FLAG_READER_NFC_A, 348 FLAG_READER_NFC_B, 349 FLAG_READER_NFC_F, 350 FLAG_READER_NFC_V, 351 FLAG_READER_NFC_BARCODE 352 }) 353 @Retention(RetentionPolicy.SOURCE) 354 public @interface PollTechnology {} 355 356 /** 357 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 358 * <p> 359 * Setting this flag allows the caller to prevent the 360 * platform from performing an NDEF check on the tags it 361 * finds. 362 */ 363 public static final int FLAG_READER_SKIP_NDEF_CHECK = 0x80; 364 365 /** 366 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 367 * <p> 368 * Setting this flag allows the caller to prevent the 369 * platform from playing sounds when it discovers a tag. 370 */ 371 public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 0x100; 372 373 /** 374 * Int Extra for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 375 * <p> 376 * Setting this integer extra allows the calling application to specify 377 * the delay that the platform will use for performing presence checks 378 * on any discovered tag. 379 */ 380 public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; 381 382 /** 383 * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 384 * <p> 385 * Setting this flag enables listening for Nfc-A technology. 386 */ 387 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 388 public static final int FLAG_LISTEN_NFC_PASSIVE_A = 0x1; 389 390 /** 391 * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 392 * <p> 393 * Setting this flag enables listening for Nfc-B technology. 394 */ 395 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 396 public static final int FLAG_LISTEN_NFC_PASSIVE_B = 1 << 1; 397 398 /** 399 * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 400 * <p> 401 * Setting this flag enables listening for Nfc-F technology. 402 */ 403 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 404 public static final int FLAG_LISTEN_NFC_PASSIVE_F = 1 << 2; 405 406 /** 407 * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 408 * <p> 409 * Setting this flag disables listening. 410 */ 411 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 412 public static final int FLAG_LISTEN_DISABLE = 0x0; 413 414 /** 415 * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 416 * <p> 417 * Setting this flag disables polling. 418 */ 419 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 420 public static final int FLAG_READER_DISABLE = 0x0; 421 422 /** 423 * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 424 * <p> 425 * Setting this flag makes listening to keep the current technology configuration. 426 */ 427 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 428 public static final int FLAG_LISTEN_KEEP = 0x80000000; 429 430 /** 431 * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}. 432 * <p> 433 * Setting this flag makes polling to keep the current technology configuration. 434 */ 435 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) 436 public static final int FLAG_READER_KEEP = 0x80000000; 437 438 /** @hide */ 439 public static final int FLAG_USE_ALL_TECH = 0xff; 440 441 /** @hide */ 442 @IntDef(flag = true, value = { 443 FLAG_SET_DEFAULT_TECH, 444 FLAG_LISTEN_KEEP, 445 FLAG_LISTEN_DISABLE, 446 FLAG_LISTEN_NFC_PASSIVE_A, 447 FLAG_LISTEN_NFC_PASSIVE_B, 448 FLAG_LISTEN_NFC_PASSIVE_F 449 }) 450 @Retention(RetentionPolicy.SOURCE) 451 public @interface ListenTechnology {} 452 453 /** 454 * Flag used in {@link #setDiscoveryTechnology(Activity, int, int)}. 455 * <p> 456 * Setting this flag changes the default listen or poll tech. 457 * Only available to privileged apps. 458 * @hide 459 */ 460 @SystemApi 461 @FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) 462 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) 463 public static final int FLAG_SET_DEFAULT_TECH = 0x40000000; 464 465 /** 466 * @hide 467 * @removed 468 */ 469 @SystemApi 470 @UnsupportedAppUsage 471 public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1; 472 473 /** @hide */ 474 public static final String ACTION_HANDOVER_TRANSFER_STARTED = 475 "android.nfc.action.HANDOVER_TRANSFER_STARTED"; 476 477 /** @hide */ 478 public static final String ACTION_HANDOVER_TRANSFER_DONE = 479 "android.nfc.action.HANDOVER_TRANSFER_DONE"; 480 481 /** @hide */ 482 public static final String EXTRA_HANDOVER_TRANSFER_STATUS = 483 "android.nfc.extra.HANDOVER_TRANSFER_STATUS"; 484 485 /** @hide */ 486 public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0; 487 /** @hide */ 488 public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1; 489 490 /** @hide */ 491 public static final String EXTRA_HANDOVER_TRANSFER_URI = 492 "android.nfc.extra.HANDOVER_TRANSFER_URI"; 493 494 /** 495 * Broadcast Action: Notify possible NFC transaction blocked because device is locked. 496 * <p>An external NFC field detected when device locked and SecureNfc enabled. 497 * @hide 498 */ 499 @SystemApi 500 @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) 501 public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = 502 "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC"; 503 504 /** 505 * Intent action to start a NFC resolver activity in a customized share session with list of 506 * {@link ResolveInfo}. 507 * @hide 508 */ 509 @SystemApi 510 @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) 511 @RequiresPermission(Manifest.permission.SHOW_CUSTOMIZED_RESOLVER) 512 public static final String ACTION_SHOW_NFC_RESOLVER = "android.nfc.action.SHOW_NFC_RESOLVER"; 513 514 /** 515 * "Extras" key for an ArrayList of {@link ResolveInfo} records which are to be shown as the 516 * targets in the customized share session. 517 * @hide 518 */ 519 @SystemApi 520 @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) 521 public static final String EXTRA_RESOLVE_INFOS = "android.nfc.extra.RESOLVE_INFOS"; 522 523 /** 524 * The requested app is correctly added to the Tag intent app preference. 525 * 526 * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow) 527 * @hide 528 */ 529 @SystemApi 530 public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; 531 532 /** 533 * The requested app is not installed on the device. 534 * 535 * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow) 536 * @hide 537 */ 538 @SystemApi 539 public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; 540 541 /** 542 * The NfcService is not available. 543 * 544 * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow) 545 * @hide 546 */ 547 @SystemApi 548 public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; 549 550 /** 551 * Possible response codes from {@link #setTagIntentAppPreferenceForUser}. 552 * 553 * @hide 554 */ 555 @IntDef(prefix = { "TAG_INTENT_APP_PREF_RESULT" }, value = { 556 TAG_INTENT_APP_PREF_RESULT_SUCCESS, 557 TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND, 558 TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE}) 559 @Retention(RetentionPolicy.SOURCE) 560 public @interface TagIntentAppPreferenceResult {} 561 562 // Guarded by sLock 563 static boolean sIsInitialized = false; 564 static boolean sHasNfcFeature; 565 static boolean sHasCeFeature; 566 static boolean sHasNfcWlcFeature; 567 568 static Object sLock = new Object(); 569 570 // Final after first constructor, except for 571 // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort 572 // recovery 573 @UnsupportedAppUsage 574 static INfcAdapter sService; 575 static NfcServiceManager.ServiceRegisterer sServiceRegisterer; 576 static INfcTag sTagService; 577 static INfcCardEmulation sCardEmulationService; 578 static INfcFCardEmulation sNfcFCardEmulationService; 579 580 /** 581 * The NfcAdapter object for each application context. 582 * There is a 1-1 relationship between application context and 583 * NfcAdapter object. 584 */ 585 static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class 586 587 /** 588 * NfcAdapter used with a null context. This ctor was deprecated but we have 589 * to support it for backwards compatibility. New methods that require context 590 * might throw when called on the null-context NfcAdapter. 591 */ 592 static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class 593 594 final NfcActivityManager mNfcActivityManager; 595 final Context mContext; 596 final HashMap<NfcUnlockHandler, INfcUnlockHandler> mNfcUnlockHandlers; 597 final Object mLock; 598 final NfcOemExtension mNfcOemExtension; 599 600 ITagRemovedCallback mTagRemovedListener; // protected by mLock 601 602 /** 603 * A callback to be invoked when the system finds a tag while the foreground activity is 604 * operating in reader mode. 605 * <p>Register your {@code ReaderCallback} implementation with {@link 606 * NfcAdapter#enableReaderMode} and disable it with {@link 607 * NfcAdapter#disableReaderMode}. 608 * @see NfcAdapter#enableReaderMode 609 */ 610 public interface ReaderCallback { onTagDiscovered(Tag tag)611 public void onTagDiscovered(Tag tag); 612 } 613 614 /** 615 * A listener to be invoked when NFC controller always on state changes. 616 * <p>Register your {@code ControllerAlwaysOnListener} implementation with {@link 617 * NfcAdapter#registerControllerAlwaysOnListener} and disable it with {@link 618 * NfcAdapter#unregisterControllerAlwaysOnListener}. 619 * @see #registerControllerAlwaysOnListener 620 * @hide 621 */ 622 @SystemApi 623 public interface ControllerAlwaysOnListener { 624 /** 625 * Called on NFC controller always on state changes 626 */ onControllerAlwaysOnChanged(boolean isEnabled)627 void onControllerAlwaysOnChanged(boolean isEnabled); 628 } 629 630 /** 631 * A callback to be invoked when the system successfully delivers your {@link NdefMessage} 632 * to another device. 633 * @deprecated this feature is removed. File sharing can work using other technology like 634 * Bluetooth. 635 */ 636 @java.lang.Deprecated 637 public interface OnNdefPushCompleteCallback { 638 /** 639 * Called on successful NDEF push. 640 * 641 * <p>This callback is usually made on a binder thread (not the UI thread). 642 * 643 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set 644 */ onNdefPushComplete(NfcEvent event)645 public void onNdefPushComplete(NfcEvent event); 646 } 647 648 /** 649 * A callback to be invoked when another NFC device capable of NDEF push (Android Beam) 650 * is within range. 651 * <p>Implement this interface and pass it to {@code 652 * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an 653 * {@link NdefMessage} at the moment that another device is within range for NFC. Using this 654 * callback allows you to create a message with data that might vary based on the 655 * content currently visible to the user. Alternatively, you can call {@code 656 * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the 657 * same data. 658 * @deprecated this feature is removed. File sharing can work using other technology like 659 * Bluetooth. 660 */ 661 @java.lang.Deprecated 662 public interface CreateNdefMessageCallback { 663 /** 664 * Called to provide a {@link NdefMessage} to push. 665 * 666 * <p>This callback is usually made on a binder thread (not the UI thread). 667 * 668 * <p>Called when this device is in range of another device 669 * that might support NDEF push. It allows the application to 670 * create the NDEF message only when it is required. 671 * 672 * <p>NDEF push cannot occur until this method returns, so do not 673 * block for too long. 674 * 675 * <p>The Android operating system will usually show a system UI 676 * on top of your activity during this time, so do not try to request 677 * input from the user to complete the callback, or provide custom NDEF 678 * push UI. The user probably will not see it. 679 * 680 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set 681 * @return NDEF message to push, or null to not provide a message 682 */ createNdefMessage(NfcEvent event)683 public NdefMessage createNdefMessage(NfcEvent event); 684 } 685 686 687 /** 688 * @deprecated this feature is removed. File sharing can work using other technology like 689 * Bluetooth. 690 */ 691 @java.lang.Deprecated 692 public interface CreateBeamUrisCallback { createBeamUris(NfcEvent event)693 public Uri[] createBeamUris(NfcEvent event); 694 } 695 696 /** 697 * A callback that is invoked when a tag is removed from the field. 698 * @see NfcAdapter#ignore 699 */ 700 public interface OnTagRemovedListener { onTagRemoved()701 void onTagRemoved(); 702 } 703 704 /** 705 * A callback to be invoked when an application has registered as a 706 * handler to unlock the device given an NFC tag at the lockscreen. 707 * @hide 708 */ 709 @SystemApi 710 public interface NfcUnlockHandler { 711 /** 712 * Called at the lock screen to attempt to unlock the device with the given tag. 713 * @param tag the detected tag, to be used to unlock the device 714 * @return true if the device was successfully unlocked 715 */ onUnlockAttempted(Tag tag)716 public boolean onUnlockAttempted(Tag tag); 717 } 718 719 /** 720 * Return list of Secure Elements which support off host card emulation. 721 * 722 * @return List<String> containing secure elements on the device which supports 723 * off host card emulation. eSE for Embedded secure element, 724 * SIM for UICC and so on. 725 * @hide 726 */ getSupportedOffHostSecureElements()727 public @NonNull List<String> getSupportedOffHostSecureElements() { 728 if (mContext == null) { 729 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 730 + " getSupportedOffHostSecureElements APIs"); 731 } 732 List<String> offHostSE = new ArrayList<String>(); 733 PackageManager pm = mContext.getPackageManager(); 734 if (pm == null) { 735 Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature"); 736 return offHostSE; 737 } 738 if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)) { 739 offHostSE.add("SIM"); 740 } 741 if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE)) { 742 offHostSE.add("eSE"); 743 } 744 return offHostSE; 745 } 746 retrieveServiceRegisterer()747 private static void retrieveServiceRegisterer() { 748 if (sServiceRegisterer == null) { 749 NfcServiceManager manager = NfcFrameworkInitializer.getNfcServiceManager(); 750 if (manager == null) { 751 Log.e(TAG, "NfcServiceManager is null"); 752 throw new UnsupportedOperationException(); 753 } 754 sServiceRegisterer = manager.getNfcManagerServiceRegisterer(); 755 } 756 } 757 758 /** 759 * Returns the NfcAdapter for application context, 760 * or throws if NFC is not available. 761 * @hide 762 */ 763 @UnsupportedAppUsage getNfcAdapter(Context context)764 public static synchronized NfcAdapter getNfcAdapter(Context context) { 765 if (context == null) { 766 if (sNullContextNfcAdapter == null) { 767 sNullContextNfcAdapter = new NfcAdapter(null); 768 } 769 return sNullContextNfcAdapter; 770 } 771 if (!sIsInitialized) { 772 PackageManager pm; 773 pm = context.getPackageManager(); 774 sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC); 775 sHasCeFeature = 776 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) 777 || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF) 778 || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC) 779 || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE); 780 sHasNfcWlcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_CHARGING); 781 /* is this device meant to have NFC */ 782 if (!sHasNfcFeature && !sHasCeFeature && !sHasNfcWlcFeature) { 783 Log.v(TAG, "this device does not have NFC support"); 784 throw new UnsupportedOperationException(); 785 } 786 retrieveServiceRegisterer(); 787 sService = getServiceInterface(); 788 if (sService == null) { 789 Log.e(TAG, "could not retrieve NFC service"); 790 throw new UnsupportedOperationException(); 791 } 792 if (sHasNfcFeature) { 793 try { 794 sTagService = sService.getNfcTagInterface(); 795 } catch (RemoteException e) { 796 sTagService = null; 797 Log.e(TAG, "could not retrieve NFC Tag service"); 798 throw new UnsupportedOperationException(); 799 } 800 } 801 if (sHasCeFeature) { 802 try { 803 sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface(); 804 } catch (RemoteException e) { 805 sNfcFCardEmulationService = null; 806 Log.e(TAG, "could not retrieve NFC-F card emulation service"); 807 throw new UnsupportedOperationException(); 808 } 809 try { 810 sCardEmulationService = sService.getNfcCardEmulationInterface(); 811 } catch (RemoteException e) { 812 sCardEmulationService = null; 813 Log.e(TAG, "could not retrieve card emulation service"); 814 throw new UnsupportedOperationException(); 815 } 816 } 817 818 sIsInitialized = true; 819 } 820 NfcAdapter adapter = sNfcAdapters.get(context); 821 if (adapter == null) { 822 adapter = new NfcAdapter(context); 823 sNfcAdapters.put(context, adapter); 824 } 825 return adapter; 826 } 827 828 /** get handle to NFC service interface */ getServiceInterface()829 private static INfcAdapter getServiceInterface() { 830 /* get a handle to NFC service */ 831 IBinder b = sServiceRegisterer.get(); 832 if (b == null) { 833 return null; 834 } 835 return INfcAdapter.Stub.asInterface(b); 836 } 837 838 /** 839 * Helper to get the default NFC Adapter. 840 * <p> 841 * Most Android devices will only have one NFC Adapter (NFC Controller). 842 * <p> 843 * This helper is the equivalent of: 844 * <pre> 845 * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 846 * NfcAdapter adapter = manager.getDefaultAdapter();</pre> 847 * @param context the calling application's context 848 * 849 * @return the default NFC adapter, or null if no NFC adapter exists 850 */ getDefaultAdapter(Context context)851 public static NfcAdapter getDefaultAdapter(Context context) { 852 if (context == null) { 853 throw new IllegalArgumentException("context cannot be null"); 854 } 855 context = context.getApplicationContext(); 856 if (context == null) { 857 throw new IllegalArgumentException( 858 "context not associated with any application (using a mock context?)"); 859 } 860 retrieveServiceRegisterer(); 861 if (sServiceRegisterer.tryGet() == null) { 862 if (sIsInitialized) { 863 synchronized (NfcAdapter.class) { 864 /* Stale sService pointer */ 865 if (sIsInitialized) sIsInitialized = false; 866 } 867 } 868 return null; 869 } 870 /* Try to initialize the service */ 871 NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 872 if (manager == null) { 873 // NFC not available 874 return null; 875 } 876 return manager.getDefaultAdapter(); 877 } 878 879 /** 880 * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p> 881 * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required 882 * for many NFC API methods. Those methods will fail when called on an NfcAdapter 883 * object created from this method.<p> 884 * @deprecated use {@link #getDefaultAdapter(Context)} 885 * @hide 886 */ 887 @Deprecated 888 @UnsupportedAppUsage getDefaultAdapter()889 public static NfcAdapter getDefaultAdapter() { 890 // introduced in API version 9 (GB 2.3) 891 // deprecated in API version 10 (GB 2.3.3) 892 // removed from public API in version 16 (ICS MR2) 893 // should maintain as a hidden API for binary compatibility for a little longer 894 Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " + 895 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception()); 896 897 return NfcAdapter.getNfcAdapter(null); 898 } 899 NfcAdapter(Context context)900 NfcAdapter(Context context) { 901 mContext = context; 902 mNfcActivityManager = new NfcActivityManager(this); 903 mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>(); 904 mTagRemovedListener = null; 905 mLock = new Object(); 906 mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener(getService()); 907 mNfcWlcStateListener = new NfcWlcStateListener(getService()); 908 mNfcVendorNciCallbackListener = new NfcVendorNciCallbackListener(getService()); 909 mNfcOemExtension = new NfcOemExtension(mContext, this); 910 } 911 912 /** 913 * @hide 914 */ 915 @UnsupportedAppUsage getContext()916 public Context getContext() { 917 return mContext; 918 } 919 920 /** 921 * Returns the binder interface to the service. 922 * @hide 923 */ 924 @UnsupportedAppUsage getService()925 public INfcAdapter getService() { 926 isEnabled(); // NOP call to recover sService if it is stale 927 return sService; 928 } 929 930 /** 931 * Returns the binder interface to the tag service. 932 * @hide 933 */ getTagService()934 public INfcTag getTagService() { 935 isEnabled(); // NOP call to recover sTagService if it is stale 936 return sTagService; 937 } 938 939 /** 940 * Returns the binder interface to the card emulation service. 941 * @hide 942 */ getCardEmulationService()943 public INfcCardEmulation getCardEmulationService() { 944 isEnabled(); 945 return sCardEmulationService; 946 } 947 948 /** 949 * Returns the binder interface to the NFC-F card emulation service. 950 * @hide 951 */ getNfcFCardEmulationService()952 public INfcFCardEmulation getNfcFCardEmulationService() { 953 isEnabled(); 954 return sNfcFCardEmulationService; 955 } 956 957 /** 958 * Returns the binder interface to the NFC-DTA test interface. 959 * @hide 960 */ getNfcDtaInterface()961 public INfcDta getNfcDtaInterface() { 962 if (mContext == null) { 963 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 964 + " NFC extras APIs"); 965 } 966 try { 967 return sService.getNfcDtaInterface(mContext.getPackageName()); 968 } catch (RemoteException e) { 969 attemptDeadServiceRecovery(e); 970 // Try one more time 971 if (sService == null) { 972 Log.e(TAG, "Failed to recover NFC Service."); 973 return null; 974 } 975 try { 976 return sService.getNfcDtaInterface(mContext.getPackageName()); 977 } catch (RemoteException ee) { 978 Log.e(TAG, "Failed to recover NFC Service."); 979 } 980 return null; 981 } 982 } 983 984 /** 985 * NFC service dead - attempt best effort recovery 986 * @hide 987 */ 988 @UnsupportedAppUsage attemptDeadServiceRecovery(Exception e)989 public void attemptDeadServiceRecovery(Exception e) { 990 Log.e(TAG, "NFC service dead - attempting to recover", e); 991 INfcAdapter service = getServiceInterface(); 992 if (service == null) { 993 Log.e(TAG, "could not retrieve NFC service during service recovery"); 994 // nothing more can be done now, sService is still stale, we'll hit 995 // this recovery path again later 996 return; 997 } 998 // assigning to sService is not thread-safe, but this is best-effort code 999 // and on a well-behaved system should never happen 1000 sService = service; 1001 if (sHasNfcFeature) { 1002 try { 1003 sTagService = service.getNfcTagInterface(); 1004 } catch (RemoteException ee) { 1005 sTagService = null; 1006 Log.e(TAG, "could not retrieve NFC tag service during service recovery"); 1007 // nothing more can be done now, sService is still stale, we'll hit 1008 // this recovery path again later 1009 return; 1010 } 1011 } 1012 1013 if (sHasCeFeature) { 1014 try { 1015 sCardEmulationService = service.getNfcCardEmulationInterface(); 1016 } catch (RemoteException ee) { 1017 sCardEmulationService = null; 1018 Log.e(TAG, 1019 "could not retrieve NFC card emulation service during service recovery"); 1020 } 1021 1022 try { 1023 sNfcFCardEmulationService = service.getNfcFCardEmulationInterface(); 1024 } catch (RemoteException ee) { 1025 sNfcFCardEmulationService = null; 1026 Log.e(TAG, 1027 "could not retrieve NFC-F card emulation service during service recovery"); 1028 } 1029 } 1030 1031 return; 1032 } 1033 isCardEmulationEnabled()1034 private boolean isCardEmulationEnabled() { 1035 if (sHasCeFeature) { 1036 return (sCardEmulationService != null || sNfcFCardEmulationService != null); 1037 } 1038 return false; 1039 } 1040 isTagReadingEnabled()1041 private boolean isTagReadingEnabled() { 1042 if (sHasNfcFeature) { 1043 return sTagService != null; 1044 } 1045 return false; 1046 } 1047 1048 1049 /** 1050 * Return true if this NFC Adapter has any features enabled. 1051 * 1052 * <p>If this method returns false, the NFC hardware is guaranteed not to 1053 * generate or respond to any NFC communication over its NFC radio. 1054 * <p>Applications can use this to check if NFC is enabled. Applications 1055 * can request Settings UI allowing the user to toggle NFC using: 1056 * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre> 1057 * 1058 * @see android.provider.Settings#ACTION_NFC_SETTINGS 1059 * @return true if this NFC Adapter has any features enabled 1060 */ isEnabled()1061 public boolean isEnabled() { 1062 boolean serviceState = false; 1063 try { 1064 serviceState = sService.getState() == STATE_ON; 1065 } catch (RemoteException e) { 1066 attemptDeadServiceRecovery(e); 1067 // Try one more time 1068 if (sService == null) { 1069 Log.e(TAG, "Failed to recover NFC Service."); 1070 return false; 1071 } 1072 try { 1073 serviceState = sService.getState() == STATE_ON; 1074 } catch (RemoteException ee) { 1075 Log.e(TAG, "Failed to recover NFC Service."); 1076 } 1077 } 1078 return serviceState 1079 && (isTagReadingEnabled() || isCardEmulationEnabled() || sHasNfcWlcFeature); 1080 } 1081 1082 /** 1083 * Return the state of this NFC Adapter. 1084 * 1085 * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON}, 1086 * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}. 1087 * 1088 * <p>{@link #isEnabled()} is equivalent to 1089 * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code> 1090 * 1091 * @return the current state of this NFC adapter 1092 * 1093 * @hide 1094 */ 1095 @SystemApi 1096 @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) getAdapterState()1097 public @AdapterState int getAdapterState() { 1098 try { 1099 return sService.getState(); 1100 } catch (RemoteException e) { 1101 attemptDeadServiceRecovery(e); 1102 // Try one more time 1103 if (sService == null) { 1104 Log.e(TAG, "Failed to recover NFC Service."); 1105 return NfcAdapter.STATE_OFF; 1106 } 1107 try { 1108 return sService.getState(); 1109 } catch (RemoteException ee) { 1110 Log.e(TAG, "Failed to recover NFC Service."); 1111 } 1112 return NfcAdapter.STATE_OFF; 1113 } 1114 } 1115 1116 /** 1117 * Enable NFC hardware. 1118 * 1119 * <p>This call is asynchronous. Listen for 1120 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 1121 * operation is complete. 1122 * 1123 * <p>This API is only allowed to be called by system apps 1124 * or apps which are Device Owner or Profile Owner. 1125 * 1126 * <p>If this returns true, then either NFC is already on, or 1127 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 1128 * to indicate a state transition. If this returns false, then 1129 * there is some problem that prevents an attempt to turn 1130 * NFC on (for example we are in airplane mode and NFC is not 1131 * toggleable in airplane mode on this platform). 1132 * 1133 */ 1134 @FlaggedApi(Flags.FLAG_NFC_STATE_CHANGE) 1135 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enable()1136 public boolean enable() { 1137 try { 1138 return sService.enable(mContext.getPackageName()); 1139 } catch (RemoteException e) { 1140 attemptDeadServiceRecovery(e); 1141 // Try one more time 1142 if (sService == null) { 1143 Log.e(TAG, "Failed to recover NFC Service."); 1144 return false; 1145 } 1146 try { 1147 return sService.enable(mContext.getPackageName()); 1148 } catch (RemoteException ee) { 1149 Log.e(TAG, "Failed to recover NFC Service."); 1150 } 1151 return false; 1152 } 1153 } 1154 1155 /** 1156 * Disable NFC hardware. 1157 * 1158 * <p>No NFC features will work after this call, and the hardware 1159 * will not perform or respond to any NFC communication. 1160 * 1161 * <p>This call is asynchronous. Listen for 1162 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 1163 * operation is complete. 1164 * 1165 * <p>This API is only allowed to be called by system apps 1166 * or apps which are Device Owner or Profile Owner. 1167 * 1168 * <p>If this returns true, then either NFC is already off, or 1169 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 1170 * to indicate a state transition. If this returns false, then 1171 * there is some problem that prevents an attempt to turn 1172 * NFC off. 1173 * 1174 */ 1175 @FlaggedApi(Flags.FLAG_NFC_STATE_CHANGE) 1176 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disable()1177 public boolean disable() { 1178 try { 1179 return sService.disable(true, mContext.getPackageName()); 1180 } catch (RemoteException e) { 1181 attemptDeadServiceRecovery(e); 1182 // Try one more time 1183 if (sService == null) { 1184 Log.e(TAG, "Failed to recover NFC Service."); 1185 return false; 1186 } 1187 try { 1188 return sService.disable(true, mContext.getPackageName()); 1189 } catch (RemoteException ee) { 1190 Log.e(TAG, "Failed to recover NFC Service."); 1191 } 1192 return false; 1193 } 1194 } 1195 1196 /** 1197 * Disable NFC hardware. 1198 * @hide 1199 */ 1200 @SystemApi 1201 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disable(boolean persist)1202 public boolean disable(boolean persist) { 1203 try { 1204 return sService.disable(persist, mContext.getPackageName()); 1205 } catch (RemoteException e) { 1206 attemptDeadServiceRecovery(e); 1207 // Try one more time 1208 if (sService == null) { 1209 Log.e(TAG, "Failed to recover NFC Service."); 1210 return false; 1211 } 1212 try { 1213 return sService.disable(persist, mContext.getPackageName()); 1214 } catch (RemoteException ee) { 1215 Log.e(TAG, "Failed to recover NFC Service."); 1216 } 1217 return false; 1218 } 1219 } 1220 1221 /** 1222 * Pauses polling for a {@code timeoutInMs} millis. If polling must be resumed before timeout, 1223 * use {@link #resumePolling()}. 1224 * @hide 1225 */ pausePolling(int timeoutInMs)1226 public void pausePolling(int timeoutInMs) { 1227 try { 1228 sService.pausePolling(timeoutInMs); 1229 } catch (RemoteException e) { 1230 attemptDeadServiceRecovery(e); 1231 } 1232 } 1233 1234 1235 /** 1236 * Returns whether the device supports observer mode or not. When observe 1237 * mode is enabled, the NFC hardware will listen for NFC readers, but not 1238 * respond to them. When observe mode is disabled, the NFC hardware will 1239 * resoond to the reader and proceed with the transaction. 1240 * @return true if the mode is supported, false otherwise. 1241 */ 1242 @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) isObserveModeSupported()1243 public boolean isObserveModeSupported() { 1244 try { 1245 return sService.isObserveModeSupported(); 1246 } catch (RemoteException e) { 1247 attemptDeadServiceRecovery(e); 1248 return false; 1249 } 1250 } 1251 1252 /** 1253 * Returns whether Observe Mode is currently enabled or not. 1254 * 1255 * @return true if observe mode is enabled, false otherwise. 1256 */ 1257 1258 @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) isObserveModeEnabled()1259 public boolean isObserveModeEnabled() { 1260 try { 1261 return sService.isObserveModeEnabled(); 1262 } catch (RemoteException e) { 1263 attemptDeadServiceRecovery(e); 1264 return false; 1265 } 1266 } 1267 1268 /** 1269 * Controls whether the NFC adapter will allow transactions to proceed or be in observe mode 1270 * and simply observe and notify the APDU service of polling loop frames. See 1271 * {@link #isObserveModeSupported()} for a description of observe mode. Only the package of the 1272 * currently preferred service (the service set as preferred by the current foreground 1273 * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the 1274 * current Default Wallet Role Holder {@link android.app.role.RoleManager#ROLE_WALLET}), 1275 * otherwise a call to this method will fail and return false. 1276 * 1277 * @param enabled false disables observe mode to allow the transaction to proceed while true 1278 * enables observe mode and does not allow transactions to proceed. 1279 * 1280 * @return boolean indicating success or failure. 1281 */ 1282 1283 @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) setObserveModeEnabled(boolean enabled)1284 public boolean setObserveModeEnabled(boolean enabled) { 1285 if (mContext == null) { 1286 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 1287 + " observe mode APIs"); 1288 } 1289 try { 1290 return sService.setObserveMode(enabled, mContext.getPackageName()); 1291 } catch (RemoteException e) { 1292 attemptDeadServiceRecovery(e); 1293 return false; 1294 } 1295 } 1296 1297 /** 1298 * Resumes default polling for the current device state if polling is paused. Calling 1299 * this while polling is not paused is a no-op. 1300 * 1301 * @hide 1302 */ resumePolling()1303 public void resumePolling() { 1304 try { 1305 sService.resumePolling(); 1306 } catch (RemoteException e) { 1307 attemptDeadServiceRecovery(e); 1308 } 1309 } 1310 1311 /** 1312 * Set one or more {@link Uri}s to send using Android Beam (TM). Every 1313 * Uri you provide must have either scheme 'file' or scheme 'content'. 1314 * 1315 * <p>For the data provided through this method, Android Beam tries to 1316 * switch to alternate transports such as Bluetooth to achieve a fast 1317 * transfer speed. Hence this method is very suitable 1318 * for transferring large files such as pictures or songs. 1319 * 1320 * <p>The receiving side will store the content of each Uri in 1321 * a file and present a notification to the user to open the file 1322 * with a {@link android.content.Intent} with action 1323 * {@link android.content.Intent#ACTION_VIEW}. 1324 * If multiple URIs are sent, the {@link android.content.Intent} will refer 1325 * to the first of the stored files. 1326 * 1327 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1328 * but the URI(s) are only made available for Android Beam when the 1329 * specified activity(s) are in resumed (foreground) state. The recommended 1330 * approach is to call this method during your Activity's 1331 * {@link Activity#onCreate} - see sample 1332 * code below. This method does not immediately perform any I/O or blocking work, 1333 * so is safe to call on your main thread. 1334 * 1335 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 1336 * have priority over both {@link #setNdefPushMessage} and 1337 * {@link #setNdefPushMessageCallback}. 1338 * 1339 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 1340 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 1341 * then the Uri push will be completely disabled for the specified activity(s). 1342 * 1343 * <p>Code example: 1344 * <pre> 1345 * protected void onCreate(Bundle savedInstanceState) { 1346 * super.onCreate(savedInstanceState); 1347 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1348 * if (nfcAdapter == null) return; // NFC not available on this device 1349 * nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this); 1350 * }</pre> 1351 * And that is it. Only one call per activity is necessary. The Android 1352 * OS will automatically release its references to the Uri(s) and the 1353 * Activity object when it is destroyed if you follow this pattern. 1354 * 1355 * <p>If your Activity wants to dynamically supply Uri(s), 1356 * then set a callback using {@link #setBeamPushUrisCallback} instead 1357 * of using this method. 1358 * 1359 * <p class="note">Do not pass in an Activity that has already been through 1360 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1361 * during {@link Activity#onCreate}. 1362 * 1363 * <p class="note">If this device does not support alternate transports 1364 * such as Bluetooth or WiFI, calling this method does nothing. 1365 * 1366 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1367 * 1368 * @param uris an array of Uri(s) to push over Android Beam 1369 * @param activity activity for which the Uri(s) will be pushed 1370 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1371 * @removed this feature is removed. File sharing can work using other technology like 1372 * Bluetooth. 1373 */ 1374 @java.lang.Deprecated 1375 @UnsupportedAppUsage setBeamPushUris(Uri[] uris, Activity activity)1376 public void setBeamPushUris(Uri[] uris, Activity activity) { 1377 synchronized (sLock) { 1378 if (!sHasNfcFeature) { 1379 throw new UnsupportedOperationException(); 1380 } 1381 } 1382 } 1383 1384 /** 1385 * Set a callback that will dynamically generate one or more {@link Uri}s 1386 * to send using Android Beam (TM). Every Uri the callback provides 1387 * must have either scheme 'file' or scheme 'content'. 1388 * 1389 * <p>For the data provided through this callback, Android Beam tries to 1390 * switch to alternate transports such as Bluetooth to achieve a fast 1391 * transfer speed. Hence this method is very suitable 1392 * for transferring large files such as pictures or songs. 1393 * 1394 * <p>The receiving side will store the content of each Uri in 1395 * a file and present a notification to the user to open the file 1396 * with a {@link android.content.Intent} with action 1397 * {@link android.content.Intent#ACTION_VIEW}. 1398 * If multiple URIs are sent, the {@link android.content.Intent} will refer 1399 * to the first of the stored files. 1400 * 1401 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1402 * but the URI(s) are only made available for Android Beam when the 1403 * specified activity(s) are in resumed (foreground) state. The recommended 1404 * approach is to call this method during your Activity's 1405 * {@link Activity#onCreate} - see sample 1406 * code below. This method does not immediately perform any I/O or blocking work, 1407 * so is safe to call on your main thread. 1408 * 1409 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 1410 * have priority over both {@link #setNdefPushMessage} and 1411 * {@link #setNdefPushMessageCallback}. 1412 * 1413 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 1414 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 1415 * then the Uri push will be completely disabled for the specified activity(s). 1416 * 1417 * <p>Code example: 1418 * <pre> 1419 * protected void onCreate(Bundle savedInstanceState) { 1420 * super.onCreate(savedInstanceState); 1421 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1422 * if (nfcAdapter == null) return; // NFC not available on this device 1423 * nfcAdapter.setBeamPushUrisCallback(callback, this); 1424 * }</pre> 1425 * And that is it. Only one call per activity is necessary. The Android 1426 * OS will automatically release its references to the Uri(s) and the 1427 * Activity object when it is destroyed if you follow this pattern. 1428 * 1429 * <p class="note">Do not pass in an Activity that has already been through 1430 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1431 * during {@link Activity#onCreate}. 1432 * 1433 * <p class="note">If this device does not support alternate transports 1434 * such as Bluetooth or WiFI, calling this method does nothing. 1435 * 1436 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1437 * 1438 * @param callback callback, or null to disable 1439 * @param activity activity for which the Uri(s) will be pushed 1440 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1441 * @removed this feature is removed. File sharing can work using other technology like 1442 * Bluetooth. 1443 */ 1444 @java.lang.Deprecated 1445 @UnsupportedAppUsage setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity)1446 public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { 1447 synchronized (sLock) { 1448 if (!sHasNfcFeature) { 1449 throw new UnsupportedOperationException(); 1450 } 1451 } 1452 } 1453 1454 /** 1455 * Set a static {@link NdefMessage} to send using Android Beam (TM). 1456 * 1457 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1458 * but the NDEF message is only made available for NDEF push when the 1459 * specified activity(s) are in resumed (foreground) state. The recommended 1460 * approach is to call this method during your Activity's 1461 * {@link Activity#onCreate} - see sample 1462 * code below. This method does not immediately perform any I/O or blocking work, 1463 * so is safe to call on your main thread. 1464 * 1465 * <p>Only one NDEF message can be pushed by the currently resumed activity. 1466 * If both {@link #setNdefPushMessage} and 1467 * {@link #setNdefPushMessageCallback} are set, then 1468 * the callback will take priority. 1469 * 1470 * <p>If neither {@link #setNdefPushMessage} or 1471 * {@link #setNdefPushMessageCallback} have been called for your activity, then 1472 * the Android OS may choose to send a default NDEF message on your behalf, 1473 * such as a URI for your application. 1474 * 1475 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 1476 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 1477 * then NDEF push will be completely disabled for the specified activity(s). 1478 * This also disables any default NDEF message the Android OS would have 1479 * otherwise sent on your behalf for those activity(s). 1480 * 1481 * <p>If you want to prevent the Android OS from sending default NDEF 1482 * messages completely (for all activities), you can include a 1483 * {@code <meta-data>} element inside the {@code <application>} 1484 * element of your AndroidManifest.xml file, like this: 1485 * <pre> 1486 * <application ...> 1487 * <meta-data android:name="android.nfc.disable_beam_default" 1488 * android:value="true" /> 1489 * </application></pre> 1490 * 1491 * <p>The API allows for multiple activities to be specified at a time, 1492 * but it is strongly recommended to just register one at a time, 1493 * and to do so during the activity's {@link Activity#onCreate}. For example: 1494 * <pre> 1495 * protected void onCreate(Bundle savedInstanceState) { 1496 * super.onCreate(savedInstanceState); 1497 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1498 * if (nfcAdapter == null) return; // NFC not available on this device 1499 * nfcAdapter.setNdefPushMessage(ndefMessage, this); 1500 * }</pre> 1501 * And that is it. Only one call per activity is necessary. The Android 1502 * OS will automatically release its references to the NDEF message and the 1503 * Activity object when it is destroyed if you follow this pattern. 1504 * 1505 * <p>If your Activity wants to dynamically generate an NDEF message, 1506 * then set a callback using {@link #setNdefPushMessageCallback} instead 1507 * of a static message. 1508 * 1509 * <p class="note">Do not pass in an Activity that has already been through 1510 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1511 * during {@link Activity#onCreate}. 1512 * 1513 * <p class="note">For sending large content such as pictures and songs, 1514 * consider using {@link #setBeamPushUris}, which switches to alternate transports 1515 * such as Bluetooth to achieve a fast transfer rate. 1516 * 1517 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1518 * 1519 * @param message NDEF message to push over NFC, or null to disable 1520 * @param activity activity for which the NDEF message will be pushed 1521 * @param activities optional additional activities, however we strongly recommend 1522 * to only register one at a time, and to do so in that activity's 1523 * {@link Activity#onCreate} 1524 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1525 * @removed this feature is removed. File sharing can work using other technology like 1526 * Bluetooth. 1527 */ 1528 @java.lang.Deprecated 1529 @UnsupportedAppUsage setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities)1530 public void setNdefPushMessage(NdefMessage message, Activity activity, 1531 Activity ... activities) { 1532 synchronized (sLock) { 1533 if (!sHasNfcFeature) { 1534 throw new UnsupportedOperationException(); 1535 } 1536 } 1537 } 1538 1539 /** 1540 * @hide 1541 * @removed 1542 */ 1543 @SystemApi 1544 @UnsupportedAppUsage setNdefPushMessage(NdefMessage message, Activity activity, int flags)1545 public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { 1546 synchronized (sLock) { 1547 if (!sHasNfcFeature) { 1548 throw new UnsupportedOperationException(); 1549 } 1550 } 1551 } 1552 1553 /** 1554 * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM). 1555 * 1556 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1557 * but the NDEF message callback can only occur when the 1558 * specified activity(s) are in resumed (foreground) state. The recommended 1559 * approach is to call this method during your Activity's 1560 * {@link Activity#onCreate} - see sample 1561 * code below. This method does not immediately perform any I/O or blocking work, 1562 * so is safe to call on your main thread. 1563 * 1564 * <p>Only one NDEF message can be pushed by the currently resumed activity. 1565 * If both {@link #setNdefPushMessage} and 1566 * {@link #setNdefPushMessageCallback} are set, then 1567 * the callback will take priority. 1568 * 1569 * <p>If neither {@link #setNdefPushMessage} or 1570 * {@link #setNdefPushMessageCallback} have been called for your activity, then 1571 * the Android OS may choose to send a default NDEF message on your behalf, 1572 * such as a URI for your application. 1573 * 1574 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 1575 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 1576 * then NDEF push will be completely disabled for the specified activity(s). 1577 * This also disables any default NDEF message the Android OS would have 1578 * otherwise sent on your behalf for those activity(s). 1579 * 1580 * <p>If you want to prevent the Android OS from sending default NDEF 1581 * messages completely (for all activities), you can include a 1582 * {@code <meta-data>} element inside the {@code <application>} 1583 * element of your AndroidManifest.xml file, like this: 1584 * <pre> 1585 * <application ...> 1586 * <meta-data android:name="android.nfc.disable_beam_default" 1587 * android:value="true" /> 1588 * </application></pre> 1589 * 1590 * <p>The API allows for multiple activities to be specified at a time, 1591 * but it is strongly recommended to just register one at a time, 1592 * and to do so during the activity's {@link Activity#onCreate}. For example: 1593 * <pre> 1594 * protected void onCreate(Bundle savedInstanceState) { 1595 * super.onCreate(savedInstanceState); 1596 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1597 * if (nfcAdapter == null) return; // NFC not available on this device 1598 * nfcAdapter.setNdefPushMessageCallback(callback, this); 1599 * }</pre> 1600 * And that is it. Only one call per activity is necessary. The Android 1601 * OS will automatically release its references to the callback and the 1602 * Activity object when it is destroyed if you follow this pattern. 1603 * 1604 * <p class="note">Do not pass in an Activity that has already been through 1605 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1606 * during {@link Activity#onCreate}. 1607 * <p class="note">For sending large content such as pictures and songs, 1608 * consider using {@link #setBeamPushUris}, which switches to alternate transports 1609 * such as Bluetooth to achieve a fast transfer rate. 1610 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1611 * 1612 * @param callback callback, or null to disable 1613 * @param activity activity for which the NDEF message will be pushed 1614 * @param activities optional additional activities, however we strongly recommend 1615 * to only register one at a time, and to do so in that activity's 1616 * {@link Activity#onCreate} 1617 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1618 * @removed this feature is removed. File sharing can work using other technology like 1619 * Bluetooth. 1620 */ 1621 @java.lang.Deprecated 1622 @UnsupportedAppUsage setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities)1623 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 1624 Activity ... activities) { 1625 synchronized (sLock) { 1626 if (!sHasNfcFeature) { 1627 throw new UnsupportedOperationException(); 1628 } 1629 } 1630 } 1631 1632 /** 1633 * Set a callback on successful Android Beam (TM). 1634 * 1635 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1636 * but the callback can only occur when the 1637 * specified activity(s) are in resumed (foreground) state. The recommended 1638 * approach is to call this method during your Activity's 1639 * {@link Activity#onCreate} - see sample 1640 * code below. This method does not immediately perform any I/O or blocking work, 1641 * so is safe to call on your main thread. 1642 * 1643 * <p>The API allows for multiple activities to be specified at a time, 1644 * but it is strongly recommended to just register one at a time, 1645 * and to do so during the activity's {@link Activity#onCreate}. For example: 1646 * <pre> 1647 * protected void onCreate(Bundle savedInstanceState) { 1648 * super.onCreate(savedInstanceState); 1649 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1650 * if (nfcAdapter == null) return; // NFC not available on this device 1651 * nfcAdapter.setOnNdefPushCompleteCallback(callback, this); 1652 * }</pre> 1653 * And that is it. Only one call per activity is necessary. The Android 1654 * OS will automatically release its references to the callback and the 1655 * Activity object when it is destroyed if you follow this pattern. 1656 * 1657 * <p class="note">Do not pass in an Activity that has already been through 1658 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1659 * during {@link Activity#onCreate}. 1660 * 1661 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1662 * 1663 * @param callback callback, or null to disable 1664 * @param activity activity for which the NDEF message will be pushed 1665 * @param activities optional additional activities, however we strongly recommend 1666 * to only register one at a time, and to do so in that activity's 1667 * {@link Activity#onCreate} 1668 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1669 * @removed this feature is removed. File sharing can work using other technology like 1670 * Bluetooth. 1671 */ 1672 @java.lang.Deprecated 1673 @UnsupportedAppUsage setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, Activity activity, Activity ... activities)1674 public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, 1675 Activity activity, Activity ... activities) { 1676 synchronized (sLock) { 1677 if (!sHasNfcFeature) { 1678 throw new UnsupportedOperationException(); 1679 } 1680 } 1681 } 1682 1683 /** 1684 * Enable foreground dispatch to the given Activity. 1685 * 1686 * <p>This will give priority to the foreground activity when 1687 * dispatching a discovered {@link Tag} to an application. 1688 * 1689 * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents 1690 * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and 1691 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED} 1692 * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled 1693 * by passing in the tech lists separately. Each first level entry in the tech list represents 1694 * an array of technologies that must all be present to match. If any of the first level sets 1695 * match then the dispatch is routed through the given PendingIntent. In other words, the second 1696 * level is ANDed together and the first level entries are ORed together. 1697 * 1698 * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters 1699 * that acts a wild card and will cause the foreground activity to receive all tags via the 1700 * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent. 1701 * 1702 * <p>This method must be called from the main thread, and only when the activity is in the 1703 * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before 1704 * the completion of their {@link Activity#onPause} callback to disable foreground dispatch 1705 * after it has been enabled. 1706 * 1707 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1708 * 1709 * @param activity the Activity to dispatch to 1710 * @param intent the PendingIntent to start for the dispatch 1711 * @param filters the IntentFilters to override dispatching for, or null to always dispatch 1712 * @param techLists the tech lists used to perform matching for dispatching of the 1713 * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent 1714 * @throws IllegalStateException if the Activity is not currently in the foreground 1715 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1716 */ enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists)1717 public void enableForegroundDispatch(Activity activity, PendingIntent intent, 1718 IntentFilter[] filters, String[][] techLists) { 1719 synchronized (sLock) { 1720 if (!sHasNfcFeature) { 1721 throw new UnsupportedOperationException(); 1722 } 1723 } 1724 if (activity == null || intent == null) { 1725 throw new NullPointerException(); 1726 } 1727 try { 1728 TechListParcel parcel = null; 1729 if (techLists != null && techLists.length > 0) { 1730 parcel = new TechListParcel(techLists); 1731 } 1732 sService.setForegroundDispatch(intent, filters, parcel); 1733 } catch (RemoteException e) { 1734 attemptDeadServiceRecovery(e); 1735 } 1736 } 1737 1738 /** 1739 * Disable foreground dispatch to the given activity. 1740 * 1741 * <p>After calling {@link #enableForegroundDispatch}, an activity 1742 * must call this method before its {@link Activity#onPause} callback 1743 * completes. 1744 * 1745 * <p>This method must be called from the main thread. 1746 * 1747 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1748 * 1749 * @param activity the Activity to disable dispatch to 1750 * @throws IllegalStateException if the Activity has already been paused 1751 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1752 */ disableForegroundDispatch(Activity activity)1753 public void disableForegroundDispatch(Activity activity) { 1754 synchronized (sLock) { 1755 if (!sHasNfcFeature) { 1756 throw new UnsupportedOperationException(); 1757 } 1758 } 1759 try { 1760 sService.setForegroundDispatch(null, null, null); 1761 } catch (RemoteException e) { 1762 attemptDeadServiceRecovery(e); 1763 } 1764 } 1765 1766 /** 1767 * Limit the NFC controller to reader mode while this Activity is in the foreground. 1768 * 1769 * <p>In this mode the NFC controller will only act as an NFC tag reader/writer, 1770 * thus disabling any peer-to-peer (Android Beam) and card-emulation modes of 1771 * the NFC adapter on this device. 1772 * 1773 * <p>Use {@link #FLAG_READER_SKIP_NDEF_CHECK} to prevent the platform from 1774 * performing any NDEF checks in reader mode. Note that this will prevent the 1775 * {@link Ndef} tag technology from being enumerated on the tag, and that 1776 * NDEF-based tag dispatch will not be functional. 1777 * 1778 * <p>For interacting with tags that are emulated on another Android device 1779 * using Android's host-based card-emulation, the recommended flags are 1780 * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}. 1781 * 1782 * @param activity the Activity that requests the adapter to be in reader mode 1783 * @param callback the callback to be called when a tag is discovered 1784 * @param flags Flags indicating poll technologies and other optional parameters 1785 * @param extras Additional extras for configuring reader mode. 1786 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1787 */ enableReaderMode(Activity activity, ReaderCallback callback, int flags, Bundle extras)1788 public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, 1789 Bundle extras) { 1790 synchronized (sLock) { 1791 if (!sHasNfcFeature) { 1792 throw new UnsupportedOperationException(); 1793 } 1794 } 1795 mNfcActivityManager.enableReaderMode(activity, callback, flags, extras); 1796 } 1797 1798 /** 1799 * Restore the NFC adapter to normal mode of operation: supporting 1800 * peer-to-peer (Android Beam), card emulation, and polling for 1801 * all supported tag technologies. 1802 * 1803 * @param activity the Activity that currently has reader mode enabled 1804 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1805 */ disableReaderMode(Activity activity)1806 public void disableReaderMode(Activity activity) { 1807 synchronized (sLock) { 1808 if (!sHasNfcFeature) { 1809 throw new UnsupportedOperationException(); 1810 } 1811 } 1812 mNfcActivityManager.disableReaderMode(activity); 1813 } 1814 1815 // Flags arguments to NFC adapter to enable/disable NFC 1816 private static final int DISABLE_POLLING_FLAGS = 0x1000; 1817 private static final int ENABLE_POLLING_FLAGS = 0x0000; 1818 1819 /** 1820 * Privileged API to enable or disable reader polling. 1821 * Unlike {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}, this API does not 1822 * need a foreground activity to control reader mode parameters 1823 * Note: Use with caution! The app is responsible for ensuring that the polling state is 1824 * returned to normal. 1825 * 1826 * @see #enableReaderMode(Activity, ReaderCallback, int, Bundle) for more detailed 1827 * documentation. 1828 * 1829 * @param enablePolling whether to enable or disable polling. 1830 * @hide 1831 */ 1832 @SystemApi 1833 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 1834 @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) 1835 @SuppressLint("VisiblySynchronized") setReaderModePollingEnabled(boolean enable)1836 public void setReaderModePollingEnabled(boolean enable) { 1837 synchronized (sLock) { 1838 if (!sHasNfcFeature) { 1839 throw new UnsupportedOperationException(); 1840 } 1841 } 1842 Binder token = new Binder(); 1843 int flags = enable ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS; 1844 try { 1845 NfcAdapter.sService.setReaderMode(token, null, flags, null); 1846 } catch (RemoteException e) { 1847 attemptDeadServiceRecovery(e); 1848 } 1849 } 1850 1851 /** 1852 * Set the NFC controller to enable specific poll/listen technologies, 1853 * as specified in parameters, while this Activity is in the foreground. 1854 * 1855 * Use {@link #FLAG_READER_KEEP} to keep current polling technology. 1856 * Use {@link #FLAG_LISTEN_KEEP} to keep current listenig technology. 1857 * (if the _KEEP flag is specified the other technology flags shouldn't be set 1858 * and are quietly ignored otherwise). 1859 * Use {@link #FLAG_READER_DISABLE} to disable polling. 1860 * Use {@link #FLAG_LISTEN_DISABLE} to disable listening. 1861 * Also refer to {@link #resetDiscoveryTechnology(Activity)} to restore these changes. 1862 * </p> 1863 * The pollTechnology, listenTechnology parameters can be one or several of below list. 1864 * <pre> 1865 * Poll Listen 1866 * Passive A 0x01 (NFC_A) 0x01 (NFC_PASSIVE_A) 1867 * Passive B 0x02 (NFC_B) 0x02 (NFC_PASSIVE_B) 1868 * Passive F 0x04 (NFC_F) 0x04 (NFC_PASSIVE_F) 1869 * ISO 15693 0x08 (NFC_V) - 1870 * Kovio 0x10 (NFC_BARCODE) - 1871 * </pre> 1872 * <p>Example usage in an Activity that requires to disable poll, 1873 * keep current listen technologies: 1874 * <pre> 1875 * protected void onResume() { 1876 * mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext()); 1877 * mNfcAdapter.setDiscoveryTechnology(this, 1878 * NfcAdapter.FLAG_READER_DISABLE, NfcAdapter.FLAG_LISTEN_KEEP); 1879 * }</pre></p> 1880 * @param activity The Activity that requests NFC controller to enable specific technologies. 1881 * @param pollTechnology Flags indicating poll technologies. 1882 * @param listenTechnology Flags indicating listen technologies. 1883 * @throws UnsupportedOperationException if FEATURE_NFC, 1884 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable. 1885 */ 1886 1887 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) setDiscoveryTechnology(@onNull Activity activity, @PollTechnology int pollTechnology, @ListenTechnology int listenTechnology)1888 public void setDiscoveryTechnology(@NonNull Activity activity, 1889 @PollTechnology int pollTechnology, @ListenTechnology int listenTechnology) { 1890 1891 if (listenTechnology == FLAG_LISTEN_DISABLE) { 1892 synchronized (sLock) { 1893 if (!sHasNfcFeature) { 1894 throw new UnsupportedOperationException(); 1895 } 1896 } 1897 } else if (pollTechnology == FLAG_READER_DISABLE) { 1898 synchronized (sLock) { 1899 if (!sHasCeFeature) { 1900 throw new UnsupportedOperationException(); 1901 } 1902 } 1903 } else { 1904 synchronized (sLock) { 1905 if (!sHasNfcFeature || !sHasCeFeature) { 1906 throw new UnsupportedOperationException(); 1907 } 1908 } 1909 } 1910 /* 1911 * Privileged FLAG to set technology mask for all data processed by NFC controller 1912 * Note: Use with caution! The app is responsible for ensuring that the discovery 1913 * technology mask is returned to default. 1914 * Note: FLAG_USE_ALL_TECH used with _KEEP flags will reset the technolody to android default 1915 */ 1916 if (Flags.nfcSetDefaultDiscTech() 1917 && ((pollTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH 1918 || (listenTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH)) { 1919 Binder token = new Binder(); 1920 try { 1921 NfcAdapter.sService.updateDiscoveryTechnology(token, 1922 pollTechnology, listenTechnology); 1923 } catch (RemoteException e) { 1924 attemptDeadServiceRecovery(e); 1925 } 1926 } else { 1927 mNfcActivityManager.setDiscoveryTech(activity, pollTechnology, listenTechnology); 1928 } 1929 } 1930 1931 /** 1932 * Restore the poll/listen technologies of NFC controller to its default state, 1933 * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)} 1934 * 1935 * @param activity The Activity that requested to change technologies. 1936 */ 1937 1938 @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH) resetDiscoveryTechnology(@onNull Activity activity)1939 public void resetDiscoveryTechnology(@NonNull Activity activity) { 1940 mNfcActivityManager.resetDiscoveryTech(activity); 1941 } 1942 1943 /** 1944 * Manually invoke Android Beam to share data. 1945 * 1946 * <p>The Android Beam animation is normally only shown when two NFC-capable 1947 * devices come into range. 1948 * By calling this method, an Activity can invoke the Beam animation directly 1949 * even if no other NFC device is in range yet. The Beam animation will then 1950 * prompt the user to tap another NFC-capable device to complete the data 1951 * transfer. 1952 * 1953 * <p>The main advantage of using this method is that it avoids the need for the 1954 * user to tap the screen to complete the transfer, as this method already 1955 * establishes the direction of the transfer and the consent of the user to 1956 * share data. Callers are responsible for making sure that the user has 1957 * consented to sharing data on NFC tap. 1958 * 1959 * <p>Note that to use this method, the passed in Activity must have already 1960 * set data to share over Beam by using method calls such as 1961 * {@link #setNdefPushMessageCallback} or 1962 * {@link #setBeamPushUrisCallback}. 1963 * 1964 * @param activity the current foreground Activity that has registered data to share 1965 * @return whether the Beam animation was successfully invoked 1966 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1967 * @removed this feature is removed. File sharing can work using other technology like 1968 * Bluetooth. 1969 */ 1970 @java.lang.Deprecated 1971 @UnsupportedAppUsage invokeBeam(Activity activity)1972 public boolean invokeBeam(Activity activity) { 1973 synchronized (sLock) { 1974 if (!sHasNfcFeature) { 1975 throw new UnsupportedOperationException(); 1976 } 1977 } 1978 return false; 1979 } 1980 1981 /** 1982 * Enable NDEF message push over NFC while this Activity is in the foreground. 1983 * 1984 * <p>You must explicitly call this method every time the activity is 1985 * resumed, and you must call {@link #disableForegroundNdefPush} before 1986 * your activity completes {@link Activity#onPause}. 1987 * 1988 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1989 * instead: it automatically hooks into your activity life-cycle, 1990 * so you do not need to call enable/disable in your onResume/onPause. 1991 * 1992 * <p>For NDEF push to function properly the other NFC device must 1993 * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or 1994 * Android's "com.android.npp" (Ndef Push Protocol). This was optional 1995 * on Gingerbread level Android NFC devices, but SNEP is mandatory on 1996 * Ice-Cream-Sandwich and beyond. 1997 * 1998 * <p>This method must be called from the main thread. 1999 * 2000 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 2001 * 2002 * @param activity foreground activity 2003 * @param message a NDEF Message to push over NFC 2004 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable 2005 * @removed this feature is removed. File sharing can work using other technology like 2006 * Bluetooth. 2007 */ 2008 @Deprecated 2009 @UnsupportedAppUsage enableForegroundNdefPush(Activity activity, NdefMessage message)2010 public void enableForegroundNdefPush(Activity activity, NdefMessage message) { 2011 synchronized (sLock) { 2012 if (!sHasNfcFeature) { 2013 throw new UnsupportedOperationException(); 2014 } 2015 } 2016 } 2017 2018 /** 2019 * Disable NDEF message push over P2P. 2020 * 2021 * <p>After calling {@link #enableForegroundNdefPush}, an activity 2022 * must call this method before its {@link Activity#onPause} callback 2023 * completes. 2024 * 2025 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 2026 * instead: it automatically hooks into your activity life-cycle, 2027 * so you do not need to call enable/disable in your onResume/onPause. 2028 * 2029 * <p>This method must be called from the main thread. 2030 * 2031 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 2032 * 2033 * @param activity the Foreground activity 2034 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable 2035 * @removed this feature is removed. File sharing can work using other technology like 2036 * Bluetooth. 2037 */ 2038 @Deprecated 2039 @UnsupportedAppUsage disableForegroundNdefPush(Activity activity)2040 public void disableForegroundNdefPush(Activity activity) { 2041 synchronized (sLock) { 2042 if (!sHasNfcFeature) { 2043 throw new UnsupportedOperationException(); 2044 } 2045 } 2046 } 2047 2048 /** 2049 * Sets Secure NFC feature. 2050 * <p>This API is for the Settings application. 2051 * @return True if successful 2052 * @hide 2053 */ 2054 @SystemApi 2055 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enableSecureNfc(boolean enable)2056 public boolean enableSecureNfc(boolean enable) { 2057 if (!sHasNfcFeature && !sHasCeFeature) { 2058 throw new UnsupportedOperationException(); 2059 } 2060 try { 2061 return sService.setNfcSecure(enable); 2062 } catch (RemoteException e) { 2063 attemptDeadServiceRecovery(e); 2064 // Try one more time 2065 if (sService == null) { 2066 Log.e(TAG, "Failed to recover NFC Service."); 2067 return false; 2068 } 2069 try { 2070 return sService.setNfcSecure(enable); 2071 } catch (RemoteException ee) { 2072 Log.e(TAG, "Failed to recover NFC Service."); 2073 } 2074 return false; 2075 } 2076 } 2077 2078 /** 2079 * Checks if the device supports Secure NFC functionality. 2080 * 2081 * @return True if device supports Secure NFC, false otherwise 2082 * @throws UnsupportedOperationException if FEATURE_NFC, 2083 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 2084 * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE 2085 * are unavailable 2086 */ isSecureNfcSupported()2087 public boolean isSecureNfcSupported() { 2088 if (!sHasNfcFeature && !sHasCeFeature) { 2089 throw new UnsupportedOperationException(); 2090 } 2091 try { 2092 return sService.deviceSupportsNfcSecure(); 2093 } catch (RemoteException e) { 2094 attemptDeadServiceRecovery(e); 2095 // Try one more time 2096 if (sService == null) { 2097 Log.e(TAG, "Failed to recover NFC Service."); 2098 return false; 2099 } 2100 try { 2101 return sService.deviceSupportsNfcSecure(); 2102 } catch (RemoteException ee) { 2103 Log.e(TAG, "Failed to recover NFC Service."); 2104 } 2105 return false; 2106 } 2107 } 2108 2109 /** 2110 * Returns information regarding Nfc antennas on the device 2111 * such as their relative positioning on the device. 2112 * 2113 * @return Information on the nfc antenna(s) on the device. 2114 * @throws UnsupportedOperationException if FEATURE_NFC, 2115 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 2116 * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE 2117 * are unavailable 2118 */ 2119 @Nullable getNfcAntennaInfo()2120 public NfcAntennaInfo getNfcAntennaInfo() { 2121 if (!sHasNfcFeature && !sHasCeFeature) { 2122 throw new UnsupportedOperationException(); 2123 } 2124 try { 2125 return sService.getNfcAntennaInfo(); 2126 } catch (RemoteException e) { 2127 attemptDeadServiceRecovery(e); 2128 // Try one more time 2129 if (sService == null) { 2130 Log.e(TAG, "Failed to recover NFC Service."); 2131 return null; 2132 } 2133 try { 2134 return sService.getNfcAntennaInfo(); 2135 } catch (RemoteException ee) { 2136 Log.e(TAG, "Failed to recover NFC Service."); 2137 } 2138 return null; 2139 } 2140 } 2141 2142 /** 2143 * Checks Secure NFC feature is enabled. 2144 * 2145 * @return True if Secure NFC is enabled, false otherwise 2146 * @throws UnsupportedOperationException if FEATURE_NFC, 2147 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 2148 * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE 2149 * are unavailable 2150 * @throws UnsupportedOperationException if device doesn't support 2151 * Secure NFC functionality. {@link #isSecureNfcSupported} 2152 */ isSecureNfcEnabled()2153 public boolean isSecureNfcEnabled() { 2154 if (!sHasNfcFeature && !sHasCeFeature) { 2155 throw new UnsupportedOperationException(); 2156 } 2157 try { 2158 return sService.isNfcSecureEnabled(); 2159 } catch (RemoteException e) { 2160 attemptDeadServiceRecovery(e); 2161 // Try one more time 2162 if (sService == null) { 2163 Log.e(TAG, "Failed to recover NFC Service."); 2164 return false; 2165 } 2166 try { 2167 return sService.isNfcSecureEnabled(); 2168 } catch (RemoteException ee) { 2169 Log.e(TAG, "Failed to recover NFC Service."); 2170 } 2171 return false; 2172 } 2173 } 2174 2175 /** 2176 * Sets NFC Reader option feature. 2177 * <p>This API is for the Settings application. 2178 * @return True if successful 2179 * @hide 2180 */ 2181 @SystemApi 2182 @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION) 2183 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enableReaderOption(boolean enable)2184 public boolean enableReaderOption(boolean enable) { 2185 if (!sHasNfcFeature) { 2186 throw new UnsupportedOperationException(); 2187 } 2188 try { 2189 return sService.enableReaderOption(enable); 2190 } catch (RemoteException e) { 2191 attemptDeadServiceRecovery(e); 2192 // Try one more time 2193 if (sService == null) { 2194 Log.e(TAG, "Failed to recover NFC Service."); 2195 return false; 2196 } 2197 try { 2198 return sService.enableReaderOption(enable); 2199 } catch (RemoteException ee) { 2200 Log.e(TAG, "Failed to recover NFC Service."); 2201 } 2202 return false; 2203 } 2204 } 2205 2206 /** 2207 * Checks if the device supports NFC Reader option functionality. 2208 * 2209 * @return True if device supports NFC Reader option, false otherwise 2210 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 2211 */ 2212 @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION) isReaderOptionSupported()2213 public boolean isReaderOptionSupported() { 2214 if (!sHasNfcFeature) { 2215 throw new UnsupportedOperationException(); 2216 } 2217 try { 2218 return sService.isReaderOptionSupported(); 2219 } catch (RemoteException e) { 2220 attemptDeadServiceRecovery(e); 2221 // Try one more time 2222 if (sService == null) { 2223 Log.e(TAG, "Failed to recover NFC Service."); 2224 return false; 2225 } 2226 try { 2227 return sService.isReaderOptionSupported(); 2228 } catch (RemoteException ee) { 2229 Log.e(TAG, "Failed to recover NFC Service."); 2230 } 2231 return false; 2232 } 2233 } 2234 2235 /** 2236 * Checks NFC Reader option feature is enabled. 2237 * 2238 * @return True if NFC Reader option is enabled, false otherwise 2239 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 2240 * @throws UnsupportedOperationException if device doesn't support 2241 * NFC Reader option functionality. {@link #isReaderOptionSupported} 2242 */ 2243 @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION) isReaderOptionEnabled()2244 public boolean isReaderOptionEnabled() { 2245 if (!sHasNfcFeature) { 2246 throw new UnsupportedOperationException(); 2247 } 2248 try { 2249 return sService.isReaderOptionEnabled(); 2250 } catch (RemoteException e) { 2251 attemptDeadServiceRecovery(e); 2252 // Try one more time 2253 if (sService == null) { 2254 Log.e(TAG, "Failed to recover NFC Service."); 2255 return false; 2256 } 2257 try { 2258 return sService.isReaderOptionEnabled(); 2259 } catch (RemoteException ee) { 2260 Log.e(TAG, "Failed to recover NFC Service."); 2261 } 2262 return false; 2263 } 2264 } 2265 2266 /** 2267 * Enable NDEF Push feature. 2268 * <p>This API is for the Settings application. 2269 * @hide 2270 * @removed 2271 */ 2272 @SystemApi 2273 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 2274 @UnsupportedAppUsage enableNdefPush()2275 public boolean enableNdefPush() { 2276 return false; 2277 } 2278 2279 /** 2280 * Disable NDEF Push feature. 2281 * <p>This API is for the Settings application. 2282 * @hide 2283 * @removed 2284 */ 2285 @SystemApi 2286 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 2287 @UnsupportedAppUsage disableNdefPush()2288 public boolean disableNdefPush() { 2289 return false; 2290 } 2291 2292 /** 2293 * Return true if the NDEF Push (Android Beam) feature is enabled. 2294 * <p>This function will return true only if both NFC is enabled, and the 2295 * NDEF Push feature is enabled. 2296 * <p>Note that if NFC is enabled but NDEF Push is disabled then this 2297 * device can still <i>receive</i> NDEF messages, it just cannot send them. 2298 * <p>Applications cannot directly toggle the NDEF Push feature, but they 2299 * can request Settings UI allowing the user to toggle NDEF Push using 2300 * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code> 2301 * <p>Example usage in an Activity that requires NDEF Push: 2302 * <p><pre> 2303 * protected void onResume() { 2304 * super.onResume(); 2305 * if (!nfcAdapter.isEnabled()) { 2306 * startActivity(new Intent(Settings.ACTION_NFC_SETTINGS)); 2307 * } else if (!nfcAdapter.isNdefPushEnabled()) { 2308 * startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS)); 2309 * } 2310 * }</pre> 2311 * 2312 * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS 2313 * @return true if NDEF Push feature is enabled 2314 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 2315 * @removed this feature is removed. File sharing can work using other technology like 2316 * Bluetooth. 2317 */ 2318 @java.lang.Deprecated 2319 @UnsupportedAppUsage isNdefPushEnabled()2320 public boolean isNdefPushEnabled() { 2321 synchronized (sLock) { 2322 if (!sHasNfcFeature) { 2323 throw new UnsupportedOperationException(); 2324 } 2325 } 2326 return false; 2327 } 2328 2329 /** 2330 * Signals that you are no longer interested in communicating with an NFC tag 2331 * for as long as it remains in range. 2332 * 2333 * All future attempted communication to this tag will fail with {@link IOException}. 2334 * The NFC controller will be put in a low-power polling mode, allowing the device 2335 * to save power in cases where it's "attached" to a tag all the time (e.g. a tag in 2336 * car dock). 2337 * 2338 * Additionally the debounceMs parameter allows you to specify for how long the tag needs 2339 * to have gone out of range, before it will be dispatched again. 2340 * 2341 * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms). 2342 * This means that if the tag repeatedly goes in and out of range (for example, in 2343 * case of a flaky connection), and the controller happens to poll every time the 2344 * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag 2345 * having been "in range" during the interval. 2346 * 2347 * Note 2: if a tag with another UID is detected after this API is called, its effect 2348 * will be cancelled; if this tag shows up before the amount of time specified in 2349 * debounceMs, it will be dispatched again. 2350 * 2351 * Note 3: some tags have a random UID, in which case this API won't work reliably. 2352 * 2353 * @param tag the {@link android.nfc.Tag Tag} to ignore. 2354 * @param debounceMs minimum amount of time the tag needs to be out of range before being 2355 * dispatched again. 2356 * @param tagRemovedListener listener to be called when the tag is removed from the field. 2357 * Note that this will only be called if the tag has been out of range 2358 * for at least debounceMs, or if another tag came into range before 2359 * debounceMs. May be null in case you don't want a callback. 2360 * @param handler the {@link android.os.Handler Handler} that will be used for delivering 2361 * the callback. if the handler is null, then the thread used for delivering 2362 * the callback is unspecified. 2363 * @return false if the tag couldn't be found (or has already gone out of range), true otherwise 2364 */ ignore(final Tag tag, int debounceMs, final OnTagRemovedListener tagRemovedListener, final Handler handler)2365 public boolean ignore(final Tag tag, int debounceMs, 2366 final OnTagRemovedListener tagRemovedListener, final Handler handler) { 2367 ITagRemovedCallback.Stub iListener = null; 2368 if (tagRemovedListener != null) { 2369 iListener = new ITagRemovedCallback.Stub() { 2370 @Override 2371 public void onTagRemoved() throws RemoteException { 2372 if (handler != null) { 2373 handler.post(new Runnable() { 2374 @Override 2375 public void run() { 2376 tagRemovedListener.onTagRemoved(); 2377 } 2378 }); 2379 } else { 2380 tagRemovedListener.onTagRemoved(); 2381 } 2382 synchronized (mLock) { 2383 mTagRemovedListener = null; 2384 } 2385 } 2386 }; 2387 } 2388 synchronized (mLock) { 2389 mTagRemovedListener = iListener; 2390 } 2391 try { 2392 return sService.ignore(tag.getServiceHandle(), debounceMs, iListener); 2393 } catch (RemoteException e) { 2394 return false; 2395 } 2396 } 2397 2398 /** 2399 * Inject a mock NFC tag.<p> 2400 * Used for testing purposes. 2401 * <p class="note">Requires the 2402 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. 2403 * @hide 2404 */ dispatch(Tag tag)2405 public void dispatch(Tag tag) { 2406 if (tag == null) { 2407 throw new NullPointerException("tag cannot be null"); 2408 } 2409 try { 2410 sService.dispatch(tag); 2411 } catch (RemoteException e) { 2412 attemptDeadServiceRecovery(e); 2413 } 2414 } 2415 2416 /** 2417 * Registers a new NFC unlock handler with the NFC service. 2418 * 2419 * <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted 2420 * NFC device. The handler should return true if it successfully authenticates the user and 2421 * unlocks the keyguard. 2422 * 2423 * <p /> The parameter {@code tagTechnologies} determines which Tag technologies will be polled for 2424 * at the lockscreen. Polling for less tag technologies reduces latency, and so it is 2425 * strongly recommended to only provide the Tag technologies that the handler is expected to 2426 * receive. There must be at least one tag technology provided, otherwise the unlock handler 2427 * is ignored. 2428 * 2429 * @hide 2430 */ 2431 @SystemApi 2432 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, String[] tagTechnologies)2433 public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, 2434 String[] tagTechnologies) { 2435 synchronized (sLock) { 2436 if (!sHasNfcFeature) { 2437 throw new UnsupportedOperationException(); 2438 } 2439 } 2440 // If there are no tag technologies, don't bother adding unlock handler 2441 if (tagTechnologies.length == 0) { 2442 return false; 2443 } 2444 2445 try { 2446 synchronized (mLock) { 2447 if (mNfcUnlockHandlers.containsKey(unlockHandler)) { 2448 // update the tag technologies 2449 sService.removeNfcUnlockHandler(mNfcUnlockHandlers.get(unlockHandler)); 2450 mNfcUnlockHandlers.remove(unlockHandler); 2451 } 2452 2453 INfcUnlockHandler.Stub iHandler = new INfcUnlockHandler.Stub() { 2454 @Override 2455 public boolean onUnlockAttempted(Tag tag) throws RemoteException { 2456 return unlockHandler.onUnlockAttempted(tag); 2457 } 2458 }; 2459 2460 sService.addNfcUnlockHandler(iHandler, 2461 Tag.getTechCodesFromStrings(tagTechnologies)); 2462 mNfcUnlockHandlers.put(unlockHandler, iHandler); 2463 } 2464 } catch (RemoteException e) { 2465 attemptDeadServiceRecovery(e); 2466 return false; 2467 } catch (IllegalArgumentException e) { 2468 Log.e(TAG, "Unable to register LockscreenDispatch", e); 2469 return false; 2470 } 2471 2472 return true; 2473 } 2474 2475 /** 2476 * Removes a previously registered unlock handler. Also removes the tag technologies 2477 * associated with the removed unlock handler. 2478 * 2479 * @hide 2480 */ 2481 @SystemApi 2482 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) removeNfcUnlockHandler(NfcUnlockHandler unlockHandler)2483 public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) { 2484 synchronized (sLock) { 2485 if (!sHasNfcFeature) { 2486 throw new UnsupportedOperationException(); 2487 } 2488 } 2489 try { 2490 synchronized (mLock) { 2491 if (mNfcUnlockHandlers.containsKey(unlockHandler)) { 2492 sService.removeNfcUnlockHandler(mNfcUnlockHandlers.remove(unlockHandler)); 2493 } 2494 2495 return true; 2496 } 2497 } catch (RemoteException e) { 2498 attemptDeadServiceRecovery(e); 2499 return false; 2500 } 2501 } 2502 2503 /** 2504 * @hide 2505 */ 2506 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getNfcAdapterExtrasInterface()2507 public INfcAdapterExtras getNfcAdapterExtrasInterface() { 2508 if (mContext == null) { 2509 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 2510 + " NFC extras APIs"); 2511 } 2512 try { 2513 return sService.getNfcAdapterExtrasInterface(mContext.getPackageName()); 2514 } catch (RemoteException e) { 2515 attemptDeadServiceRecovery(e); 2516 // Try one more time 2517 if (sService == null) { 2518 Log.e(TAG, "Failed to recover NFC Service."); 2519 return null; 2520 } 2521 try { 2522 return sService.getNfcAdapterExtrasInterface(mContext.getPackageName()); 2523 } catch (RemoteException ee) { 2524 Log.e(TAG, "Failed to recover NFC Service."); 2525 } 2526 return null; 2527 } 2528 } 2529 enforceResumed(Activity activity)2530 void enforceResumed(Activity activity) { 2531 if (!activity.isResumed()) { 2532 throw new IllegalStateException("API cannot be called while activity is paused"); 2533 } 2534 } 2535 getSdkVersion()2536 int getSdkVersion() { 2537 if (mContext == null) { 2538 return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess 2539 } else { 2540 return mContext.getApplicationInfo().targetSdkVersion; 2541 } 2542 } 2543 2544 /** 2545 * Sets NFC controller always on feature. 2546 * <p>This API is for the NFCC internal state management. It allows to discriminate 2547 * the controller function from the NFC function by keeping the NFC controller on without 2548 * any NFC RF enabled if necessary. 2549 * <p>This call is asynchronous. Register a listener {@link #ControllerAlwaysOnListener} 2550 * by {@link #registerControllerAlwaysOnListener} to find out when the operation is 2551 * complete. 2552 * <p>If this returns true, then either NFCC always on state has been set based on the value, 2553 * or a {@link ControllerAlwaysOnListener#onControllerAlwaysOnChanged(boolean)} will be invoked 2554 * to indicate the state change. 2555 * If this returns false, then there is some problem that prevents an attempt to turn NFCC 2556 * always on. 2557 * @param value if true the NFCC will be kept on (with no RF enabled if NFC adapter is 2558 * disabled), if false the NFCC will follow completely the Nfc adapter state. 2559 * @throws UnsupportedOperationException if FEATURE_NFC, 2560 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 2561 * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE 2562 * are unavailable 2563 * @return void 2564 * @hide 2565 */ 2566 @SystemApi 2567 @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) setControllerAlwaysOn(boolean value)2568 public boolean setControllerAlwaysOn(boolean value) { 2569 if (!sHasNfcFeature && !sHasCeFeature) { 2570 throw new UnsupportedOperationException(); 2571 } 2572 try { 2573 return sService.setControllerAlwaysOn(value); 2574 } catch (RemoteException e) { 2575 attemptDeadServiceRecovery(e); 2576 // Try one more time 2577 if (sService == null) { 2578 Log.e(TAG, "Failed to recover NFC Service."); 2579 return false; 2580 } 2581 try { 2582 return sService.setControllerAlwaysOn(value); 2583 } catch (RemoteException ee) { 2584 Log.e(TAG, "Failed to recover NFC Service."); 2585 } 2586 return false; 2587 } 2588 } 2589 2590 /** 2591 * Checks NFC controller always on feature is enabled. 2592 * 2593 * @return True if NFC controller always on is enabled, false otherwise 2594 * @throws UnsupportedOperationException if FEATURE_NFC, 2595 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 2596 * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE 2597 * are unavailable 2598 * @hide 2599 */ 2600 @SystemApi 2601 @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) isControllerAlwaysOn()2602 public boolean isControllerAlwaysOn() { 2603 try { 2604 return sService.isControllerAlwaysOn(); 2605 } catch (RemoteException e) { 2606 attemptDeadServiceRecovery(e); 2607 // Try one more time 2608 if (sService == null) { 2609 Log.e(TAG, "Failed to recover NFC Service."); 2610 return false; 2611 } 2612 try { 2613 return sService.isControllerAlwaysOn(); 2614 } catch (RemoteException ee) { 2615 Log.e(TAG, "Failed to recover NFC Service."); 2616 } 2617 return false; 2618 } 2619 } 2620 2621 /** 2622 * Checks if the device supports NFC controller always on functionality. 2623 * 2624 * @return True if device supports NFC controller always on, false otherwise 2625 * @throws UnsupportedOperationException if FEATURE_NFC, 2626 * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 2627 * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE 2628 * are unavailable 2629 * @hide 2630 */ 2631 @SystemApi 2632 @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) isControllerAlwaysOnSupported()2633 public boolean isControllerAlwaysOnSupported() { 2634 if (!sHasNfcFeature && !sHasCeFeature) { 2635 throw new UnsupportedOperationException(); 2636 } 2637 try { 2638 return sService.isControllerAlwaysOnSupported(); 2639 } catch (RemoteException e) { 2640 attemptDeadServiceRecovery(e); 2641 // Try one more time 2642 if (sService == null) { 2643 Log.e(TAG, "Failed to recover NFC Service."); 2644 return false; 2645 } 2646 try { 2647 return sService.isControllerAlwaysOnSupported(); 2648 } catch (RemoteException ee) { 2649 Log.e(TAG, "Failed to recover NFC Service."); 2650 } 2651 return false; 2652 } 2653 } 2654 2655 /** 2656 * Register a {@link ControllerAlwaysOnListener} to listen for NFC controller always on 2657 * state changes 2658 * <p>The provided listener will be invoked by the given {@link Executor}. 2659 * 2660 * @param executor an {@link Executor} to execute given listener 2661 * @param listener user implementation of the {@link ControllerAlwaysOnListener} 2662 * @hide 2663 */ 2664 @SystemApi 2665 @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) registerControllerAlwaysOnListener( @onNull @allbackExecutor Executor executor, @NonNull ControllerAlwaysOnListener listener)2666 public void registerControllerAlwaysOnListener( 2667 @NonNull @CallbackExecutor Executor executor, 2668 @NonNull ControllerAlwaysOnListener listener) { 2669 mControllerAlwaysOnListener.register(executor, listener); 2670 } 2671 2672 /** 2673 * Unregister the specified {@link ControllerAlwaysOnListener} 2674 * <p>The same {@link ControllerAlwaysOnListener} object used when calling 2675 * {@link #registerControllerAlwaysOnListener(Executor, ControllerAlwaysOnListener)} 2676 * must be used. 2677 * 2678 * <p>Listeners are automatically unregistered when application process goes away 2679 * 2680 * @param listener user implementation of the {@link ControllerAlwaysOnListener} 2681 * @hide 2682 */ 2683 @SystemApi 2684 @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) unregisterControllerAlwaysOnListener( @onNull ControllerAlwaysOnListener listener)2685 public void unregisterControllerAlwaysOnListener( 2686 @NonNull ControllerAlwaysOnListener listener) { 2687 mControllerAlwaysOnListener.unregister(listener); 2688 } 2689 2690 2691 /** 2692 * Sets whether we dispatch NFC Tag intents to the package. 2693 * 2694 * <p>{@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or 2695 * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is 2696 * disallowed. 2697 * <p>An app is added to the preference list with the allowed flag set to {@code true} 2698 * when a Tag intent is dispatched to the package for the first time. This API is called 2699 * by settings to note that the user wants to change this default preference. 2700 * 2701 * @param userId the user to whom this package name will belong to 2702 * @param pkg the full name (i.e. com.google.android.tag) of the package that will be added to 2703 * the preference list 2704 * @param allow {@code true} to allow dispatching Tag intents to the package's activity, 2705 * {@code false} otherwise 2706 * @return the {@link #TagIntentAppPreferenceResult} value 2707 * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns 2708 * {@code false} 2709 * 2710 * @hide 2711 */ 2712 @SystemApi 2713 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 2714 @TagIntentAppPreferenceResult setTagIntentAppPreferenceForUser(@serIdInt int userId, @NonNull String pkg, boolean allow)2715 public int setTagIntentAppPreferenceForUser(@UserIdInt int userId, 2716 @NonNull String pkg, boolean allow) { 2717 Objects.requireNonNull(pkg, "pkg cannot be null"); 2718 if (!isTagIntentAppPreferenceSupported()) { 2719 Log.e(TAG, "TagIntentAppPreference is not supported"); 2720 throw new UnsupportedOperationException(); 2721 } 2722 try { 2723 return sService.setTagIntentAppPreferenceForUser(userId, pkg, allow); 2724 } catch (RemoteException e) { 2725 attemptDeadServiceRecovery(e); 2726 // Try one more time 2727 if (sService == null) { 2728 Log.e(TAG, "Failed to recover NFC Service."); 2729 } 2730 try { 2731 return sService.setTagIntentAppPreferenceForUser(userId, pkg, allow); 2732 } catch (RemoteException ee) { 2733 Log.e(TAG, "Failed to recover NFC Service."); 2734 } 2735 return TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE; 2736 } 2737 } 2738 2739 2740 /** 2741 * Get the Tag dispatch preference list of the UserId. 2742 * 2743 * <p>This returns a mapping of package names for this user id to whether we dispatch Tag 2744 * intents to the package. {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or 2745 * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is 2746 * mapped to {@code false}. 2747 * <p>There are three different possible cases: 2748 * <p>A package not being in the preference list. 2749 * It does not contain any Tag intent filters or the user never triggers a Tag detection that 2750 * matches the intent filter of the package. 2751 * <p>A package being mapped to {@code true}. 2752 * When a package has been launched by a tag detection for the first time, the package name is 2753 * put to the map and by default mapped to {@code true}. The package will receive Tag intents as 2754 * usual. 2755 * <p>A package being mapped to {@code false}. 2756 * The user chooses to disable this package and it will not receive any Tag intents anymore. 2757 * 2758 * @param userId the user to whom this preference list will belong to 2759 * @return a map of the UserId which indicates the mapping from package name to 2760 * boolean(allow status), otherwise return an empty map 2761 * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns 2762 * {@code false} 2763 * 2764 * @hide 2765 */ 2766 @SystemApi 2767 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 2768 @NonNull getTagIntentAppPreferenceForUser(@serIdInt int userId)2769 public Map<String, Boolean> getTagIntentAppPreferenceForUser(@UserIdInt int userId) { 2770 if (!isTagIntentAppPreferenceSupported()) { 2771 Log.e(TAG, "TagIntentAppPreference is not supported"); 2772 throw new UnsupportedOperationException(); 2773 } 2774 try { 2775 Map<String, Boolean> result = (Map<String, Boolean>) sService 2776 .getTagIntentAppPreferenceForUser(userId); 2777 return result; 2778 } catch (RemoteException e) { 2779 attemptDeadServiceRecovery(e); 2780 // Try one more time 2781 if (sService == null) { 2782 Log.e(TAG, "Failed to recover NFC Service."); 2783 return Collections.emptyMap(); 2784 } 2785 try { 2786 Map<String, Boolean> result = (Map<String, Boolean>) sService 2787 .getTagIntentAppPreferenceForUser(userId); 2788 return result; 2789 } catch (RemoteException ee) { 2790 Log.e(TAG, "Failed to recover NFC Service."); 2791 } 2792 return Collections.emptyMap(); 2793 } 2794 } 2795 2796 /** 2797 * Checks if the device supports Tag application preference. 2798 * 2799 * @return {@code true} if the device supports Tag application preference, {@code false} 2800 * otherwise 2801 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable 2802 * 2803 * @hide 2804 */ 2805 @SystemApi 2806 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) isTagIntentAppPreferenceSupported()2807 public boolean isTagIntentAppPreferenceSupported() { 2808 if (!sHasNfcFeature) { 2809 throw new UnsupportedOperationException(); 2810 } 2811 try { 2812 return sService.isTagIntentAppPreferenceSupported(); 2813 } catch (RemoteException e) { 2814 attemptDeadServiceRecovery(e); 2815 // Try one more time 2816 if (sService == null) { 2817 Log.e(TAG, "Failed to recover NFC Service."); 2818 return false; 2819 } 2820 try { 2821 return sService.isTagIntentAppPreferenceSupported(); 2822 } catch (RemoteException ee) { 2823 Log.e(TAG, "Failed to recover NFC Service."); 2824 } 2825 return false; 2826 } 2827 } 2828 2829 /** 2830 * Notifies the system of a new polling loop. 2831 * 2832 * @param frame is the new frame. 2833 * 2834 * @hide 2835 */ 2836 @TestApi 2837 @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) notifyPollingLoop(@onNull PollingFrame pollingFrame)2838 public void notifyPollingLoop(@NonNull PollingFrame pollingFrame) { 2839 try { 2840 if (sService == null) { 2841 attemptDeadServiceRecovery(null); 2842 } 2843 sService.notifyPollingLoop(pollingFrame); 2844 } catch (RemoteException e) { 2845 attemptDeadServiceRecovery(e); 2846 // Try one more time 2847 if (sService == null) { 2848 Log.e(TAG, "Failed to recover NFC Service."); 2849 return; 2850 } 2851 try { 2852 sService.notifyPollingLoop(pollingFrame); 2853 } catch (RemoteException ee) { 2854 Log.e(TAG, "Failed to recover NFC Service."); 2855 } 2856 } 2857 } 2858 2859 /** 2860 * Notifies the system of a an HCE session being deactivated. 2861 * * 2862 * @hide 2863 */ 2864 @TestApi 2865 @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) notifyHceDeactivated()2866 public void notifyHceDeactivated() { 2867 try { 2868 if (sService == null) { 2869 attemptDeadServiceRecovery(null); 2870 } 2871 sService.notifyHceDeactivated(); 2872 } catch (RemoteException e) { 2873 attemptDeadServiceRecovery(e); 2874 // Try one more time 2875 if (sService == null) { 2876 Log.e(TAG, "Failed to recover NFC Service."); 2877 return; 2878 } 2879 try { 2880 sService.notifyHceDeactivated(); 2881 } catch (RemoteException ee) { 2882 Log.e(TAG, "Failed to recover NFC Service."); 2883 } 2884 } 2885 } 2886 2887 /** 2888 * Sets NFC charging feature. 2889 * <p>This API is for the Settings application. 2890 * @return True if successful 2891 * @hide 2892 */ 2893 @SystemApi 2894 @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) 2895 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) setWlcEnabled(boolean enable)2896 public boolean setWlcEnabled(boolean enable) { 2897 if (!sHasNfcWlcFeature) { 2898 throw new UnsupportedOperationException(); 2899 } 2900 try { 2901 return sService.setWlcEnabled(enable); 2902 } catch (RemoteException e) { 2903 attemptDeadServiceRecovery(e); 2904 // Try one more time 2905 if (sService == null) { 2906 Log.e(TAG, "Failed to recover NFC Service."); 2907 return false; 2908 } 2909 try { 2910 return sService.setWlcEnabled(enable); 2911 } catch (RemoteException ee) { 2912 Log.e(TAG, "Failed to recover NFC Service."); 2913 } 2914 return false; 2915 } 2916 } 2917 2918 /** 2919 * Checks NFC charging feature is enabled. 2920 * 2921 * @return True if NFC charging is enabled, false otherwise 2922 * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING 2923 * is unavailable 2924 */ 2925 @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) isWlcEnabled()2926 public boolean isWlcEnabled() { 2927 if (!sHasNfcWlcFeature) { 2928 throw new UnsupportedOperationException(); 2929 } 2930 try { 2931 return sService.isWlcEnabled(); 2932 } catch (RemoteException e) { 2933 attemptDeadServiceRecovery(e); 2934 // Try one more time 2935 if (sService == null) { 2936 Log.e(TAG, "Failed to recover NFC Service."); 2937 return false; 2938 } 2939 try { 2940 return sService.isWlcEnabled(); 2941 } catch (RemoteException ee) { 2942 Log.e(TAG, "Failed to recover NFC Service."); 2943 } 2944 return false; 2945 } 2946 } 2947 2948 /** 2949 * A listener to be invoked when NFC controller always on state changes. 2950 * <p>Register your {@code ControllerAlwaysOnListener} implementation with {@link 2951 * NfcAdapter#registerWlcStateListener} and disable it with {@link 2952 * NfcAdapter#unregisterWlcStateListenerListener}. 2953 * @see #registerWlcStateListener 2954 * @hide 2955 */ 2956 @SystemApi 2957 @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) 2958 public interface WlcStateListener { 2959 /** 2960 * Called on NFC WLC state changes 2961 */ onWlcStateChanged(@onNull WlcListenerDeviceInfo wlcListenerDeviceInfo)2962 void onWlcStateChanged(@NonNull WlcListenerDeviceInfo wlcListenerDeviceInfo); 2963 } 2964 2965 /** 2966 * Register a {@link WlcStateListener} to listen for NFC WLC state changes 2967 * <p>The provided listener will be invoked by the given {@link Executor}. 2968 * 2969 * @param executor an {@link Executor} to execute given listener 2970 * @param listener user implementation of the {@link WlcStateListener} 2971 * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING 2972 * is unavailable 2973 * 2974 * @hide 2975 */ 2976 @SystemApi 2977 @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) registerWlcStateListener( @onNull @allbackExecutor Executor executor, @NonNull WlcStateListener listener)2978 public void registerWlcStateListener( 2979 @NonNull @CallbackExecutor Executor executor, 2980 @NonNull WlcStateListener listener) { 2981 if (!sHasNfcWlcFeature) { 2982 throw new UnsupportedOperationException(); 2983 } 2984 mNfcWlcStateListener.register(executor, listener); 2985 } 2986 2987 /** 2988 * Unregister the specified {@link WlcStateListener} 2989 * <p>The same {@link WlcStateListener} object used when calling 2990 * {@link #registerWlcStateListener(Executor, WlcStateListener)} 2991 * must be used. 2992 * 2993 * <p>Listeners are automatically unregistered when application process goes away 2994 * 2995 * @param listener user implementation of the {@link WlcStateListener}a 2996 * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING 2997 * is unavailable 2998 * 2999 * @hide 3000 */ 3001 @SystemApi 3002 @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) unregisterWlcStateListener( @onNull WlcStateListener listener)3003 public void unregisterWlcStateListener( 3004 @NonNull WlcStateListener listener) { 3005 if (!sHasNfcWlcFeature) { 3006 throw new UnsupportedOperationException(); 3007 } 3008 mNfcWlcStateListener.unregister(listener); 3009 } 3010 3011 /** 3012 * Returns information on the NFC charging listener device 3013 * 3014 * @return Information on the NFC charging listener device 3015 * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING 3016 * is unavailable 3017 */ 3018 @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) 3019 @Nullable getWlcListenerDeviceInfo()3020 public WlcListenerDeviceInfo getWlcListenerDeviceInfo() { 3021 if (!sHasNfcWlcFeature) { 3022 throw new UnsupportedOperationException(); 3023 } 3024 try { 3025 return sService.getWlcListenerDeviceInfo(); 3026 } catch (RemoteException e) { 3027 attemptDeadServiceRecovery(e); 3028 // Try one more time 3029 if (sService == null) { 3030 Log.e(TAG, "Failed to recover NFC Service."); 3031 return null; 3032 } 3033 try { 3034 return sService.getWlcListenerDeviceInfo(); 3035 } catch (RemoteException ee) { 3036 Log.e(TAG, "Failed to recover NFC Service."); 3037 } 3038 return null; 3039 } 3040 } 3041 3042 /** 3043 * Vendor NCI command success. 3044 * @hide 3045 */ 3046 @SystemApi 3047 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3048 public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0; 3049 /** 3050 * Vendor NCI command rejected. 3051 * @hide 3052 */ 3053 @SystemApi 3054 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3055 public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1; 3056 /** 3057 * Vendor NCI command corrupted. 3058 * @hide 3059 */ 3060 @SystemApi 3061 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3062 public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2; 3063 /** 3064 * Vendor NCI command failed with unknown reason. 3065 * @hide 3066 */ 3067 @SystemApi 3068 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3069 public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3; 3070 3071 /** 3072 * @hide 3073 */ 3074 @Retention(RetentionPolicy.SOURCE) 3075 @IntDef(value = { 3076 SEND_VENDOR_NCI_STATUS_SUCCESS, 3077 SEND_VENDOR_NCI_STATUS_REJECTED, 3078 SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED, 3079 SEND_VENDOR_NCI_STATUS_FAILED, 3080 }) 3081 @interface SendVendorNciStatus {} 3082 3083 /** 3084 * Message Type for NCI Command. 3085 * @hide 3086 */ 3087 @SystemApi 3088 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3089 public static final int MESSAGE_TYPE_COMMAND = 1; 3090 3091 /** 3092 * @hide 3093 */ 3094 @Retention(RetentionPolicy.SOURCE) 3095 @IntDef(value = { 3096 MESSAGE_TYPE_COMMAND, 3097 }) 3098 @interface MessageType {} 3099 3100 /** 3101 * Send Vendor specific Nci Messages with custom message type. 3102 * 3103 * The format of the NCI messages are defined in the NCI specification. The platform is 3104 * responsible for fragmenting the payload if necessary. 3105 * 3106 * Note that mt (message type) is added at the beginning of method parameters as it is more 3107 * distinctive than other parameters and was requested from vendor. 3108 * 3109 * @param mt message Type of the command 3110 * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from 3111 * the NCI specification 3112 * @param oid opcode ID of the command. This is left to the OEM / vendor to decide 3113 * @param payload containing vendor Nci message payload 3114 * @return message send status 3115 * @hide 3116 */ 3117 @SystemApi 3118 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3119 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) sendVendorNciMessage(@essageType int mt, @IntRange(from = 0, to = 15) int gid, @IntRange(from = 0) int oid, @NonNull byte[] payload)3120 public @SendVendorNciStatus int sendVendorNciMessage(@MessageType int mt, 3121 @IntRange(from = 0, to = 15) int gid, @IntRange(from = 0) int oid, 3122 @NonNull byte[] payload) { 3123 Objects.requireNonNull(payload, "Payload must not be null"); 3124 try { 3125 return sService.sendVendorNciMessage(mt, gid, oid, payload); 3126 } catch (RemoteException e) { 3127 throw e.rethrowFromSystemServer(); 3128 } 3129 } 3130 3131 /** 3132 * Register an {@link NfcVendorNciCallback} to listen for Nfc vendor responses and notifications 3133 * <p>The provided callback will be invoked by the given {@link Executor}. 3134 * 3135 * <p>When first registering a callback, the callbacks's 3136 * {@link NfcVendorNciCallback#onVendorNciCallBack(byte[])} is immediately invoked to 3137 * notify the vendor notification. 3138 * 3139 * @param executor an {@link Executor} to execute given callback 3140 * @param callback user implementation of the {@link NfcVendorNciCallback} 3141 * @hide 3142 */ 3143 @SystemApi 3144 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3145 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) registerNfcVendorNciCallback(@onNull @allbackExecutor Executor executor, @NonNull NfcVendorNciCallback callback)3146 public void registerNfcVendorNciCallback(@NonNull @CallbackExecutor Executor executor, 3147 @NonNull NfcVendorNciCallback callback) { 3148 mNfcVendorNciCallbackListener.register(executor, callback); 3149 } 3150 3151 /** 3152 * Unregister the specified {@link NfcVendorNciCallback} 3153 * 3154 * <p>The same {@link NfcVendorNciCallback} object used when calling 3155 * {@link #registerNfcVendorNciCallback(Executor, NfcVendorNciCallback)} must be used. 3156 * 3157 * <p>Callbacks are automatically unregistered when application process goes away 3158 * 3159 * @param callback user implementation of the {@link NfcVendorNciCallback} 3160 * @hide 3161 */ 3162 @SystemApi 3163 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3164 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) unregisterNfcVendorNciCallback(@onNull NfcVendorNciCallback callback)3165 public void unregisterNfcVendorNciCallback(@NonNull NfcVendorNciCallback callback) { 3166 mNfcVendorNciCallbackListener.unregister(callback); 3167 } 3168 3169 /** 3170 * Interface for receiving vendor NCI responses and notifications. 3171 * @hide 3172 */ 3173 @SystemApi 3174 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) 3175 public interface NfcVendorNciCallback { 3176 /** 3177 * Invoked when a vendor specific NCI response is received. 3178 * 3179 * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from 3180 * the NCI specification. 3181 * @param oid opcode ID of the command. This is left to the OEM / vendor to decide. 3182 * @param payload containing vendor Nci message payload. 3183 */ 3184 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) onVendorNciResponse( @ntRangefrom = 0, to = 15) int gid, int oid, @NonNull byte[] payload)3185 void onVendorNciResponse( 3186 @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload); 3187 3188 /** 3189 * Invoked when a vendor specific NCI notification is received. 3190 * 3191 * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from 3192 * the NCI specification. 3193 * @param oid opcode ID of the command. This is left to the OEM / vendor to decide. 3194 * @param payload containing vendor Nci message payload. 3195 */ 3196 @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) onVendorNciNotification( @ntRangefrom = 9, to = 15) int gid, int oid, @NonNull byte[] payload)3197 void onVendorNciNotification( 3198 @IntRange(from = 9, to = 15) int gid, int oid, @NonNull byte[] payload); 3199 } 3200 3201 /** 3202 * Returns an instance of {@link NfcOemExtension} associated with {@link NfcAdapter} instance. 3203 * @hide 3204 */ 3205 @SystemApi 3206 @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) getNfcOemExtension()3207 @NonNull public NfcOemExtension getNfcOemExtension() { 3208 synchronized (sLock) { 3209 if (!sHasNfcFeature) { 3210 throw new UnsupportedOperationException(); 3211 } 3212 } 3213 return mNfcOemExtension; 3214 } 3215 } 3216