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