diff --git a/core/api/current.txt b/core/api/current.txt index 63ac7f7844b6e..198446e86323b 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -28411,15 +28411,24 @@ package android.nfc { public final class NfcAdapter { method public void disableForegroundDispatch(android.app.Activity); + method @Deprecated public void disableForegroundNdefPush(android.app.Activity); method public void disableReaderMode(android.app.Activity); method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]); + method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo(); method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler); + method @Deprecated public boolean invokeBeam(android.app.Activity); method public boolean isEnabled(); + method @Deprecated public boolean isNdefPushEnabled(); method public boolean isSecureNfcEnabled(); method public boolean isSecureNfcSupported(); + method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity); + method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity); + method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...); + method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...); + method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...); field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED"; field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; @@ -28451,6 +28460,18 @@ package android.nfc { field public static final int STATE_TURNING_ON = 2; // 0x2 } + @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback { + method @Deprecated public android.net.Uri[] createBeamUris(android.nfc.NfcEvent); + } + + @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback { + method @Deprecated public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent); + } + + @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback { + method @Deprecated public void onNdefPushComplete(android.nfc.NfcEvent); + } + public static interface NfcAdapter.OnTagRemovedListener { method public void onTagRemoved(); } diff --git a/core/api/removed.txt b/core/api/removed.txt index 5c4fd10fc05b9..1fa1e89fb46eb 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -252,34 +252,6 @@ package android.net { } -package android.nfc { - - public final class NfcAdapter { - method @Deprecated public void disableForegroundNdefPush(android.app.Activity); - method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); - method @Deprecated public boolean invokeBeam(android.app.Activity); - method @Deprecated public boolean isNdefPushEnabled(); - method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity); - method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity); - method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...); - method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...); - method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...); - } - - @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback { - method public android.net.Uri[] createBeamUris(android.nfc.NfcEvent); - } - - @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback { - method public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent); - } - - @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback { - method public void onNdefPushComplete(android.nfc.NfcEvent); - } - -} - package android.os { public class BatteryManager { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 5183a828b8c75..d953e3342df4b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9692,7 +9692,9 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush(); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable(); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush(); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map getTagIntentAppPreferenceForUser(int); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn(); @@ -9701,8 +9703,10 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean); + method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); + field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1 field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0 field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt index 1c10356c6b038..2c5acf182d51f 100644 --- a/core/api/system-removed.txt +++ b/core/api/system-removed.txt @@ -140,17 +140,6 @@ package android.media.tv { } -package android.nfc { - - public final class NfcAdapter { - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush(); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush(); - method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int); - field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1 - } - -} - package android.os { public class Build { diff --git a/core/java/android/nfc/BeamShareData.aidl b/core/java/android/nfc/BeamShareData.aidl new file mode 100644 index 0000000000000..a47e24057a54d --- /dev/null +++ b/core/java/android/nfc/BeamShareData.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +parcelable BeamShareData; diff --git a/core/java/android/nfc/BeamShareData.java b/core/java/android/nfc/BeamShareData.java new file mode 100644 index 0000000000000..6a40f98fe21c4 --- /dev/null +++ b/core/java/android/nfc/BeamShareData.java @@ -0,0 +1,67 @@ +package android.nfc; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; + +/** + * Class to IPC data to be shared over Android Beam. + * Allows bundling NdefMessage, Uris and flags in a single + * IPC call. This is important as we want to reduce the + * amount of IPC calls at "touch time". + * @hide + */ +public final class BeamShareData implements Parcelable { + public final NdefMessage ndefMessage; + public final Uri[] uris; + public final UserHandle userHandle; + public final int flags; + + public BeamShareData(NdefMessage msg, Uri[] uris, UserHandle userHandle, int flags) { + this.ndefMessage = msg; + this.uris = uris; + this.userHandle = userHandle; + this.flags = flags; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + int urisLength = (uris != null) ? uris.length : 0; + dest.writeParcelable(ndefMessage, 0); + dest.writeInt(urisLength); + if (urisLength > 0) { + dest.writeTypedArray(uris, 0); + } + dest.writeParcelable(userHandle, 0); + dest.writeInt(this.flags); + } + + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public BeamShareData createFromParcel(Parcel source) { + Uri[] uris = null; + NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader(), android.nfc.NdefMessage.class); + int numUris = source.readInt(); + if (numUris > 0) { + uris = new Uri[numUris]; + source.readTypedArray(uris, Uri.CREATOR); + } + UserHandle userHandle = source.readParcelable(UserHandle.class.getClassLoader(), android.os.UserHandle.class); + int flags = source.readInt(); + + return new BeamShareData(msg, uris, userHandle, flags); + } + + @Override + public BeamShareData[] newArray(int size) { + return new BeamShareData[size]; + } + }; +} diff --git a/core/java/android/nfc/IAppCallback.aidl b/core/java/android/nfc/IAppCallback.aidl index b06bf06d5197d..133146de2aa17 100644 --- a/core/java/android/nfc/IAppCallback.aidl +++ b/core/java/android/nfc/IAppCallback.aidl @@ -16,6 +16,7 @@ package android.nfc; +import android.nfc.BeamShareData; import android.nfc.Tag; /** @@ -23,5 +24,7 @@ import android.nfc.Tag; */ interface IAppCallback { + BeamShareData createBeamShareData(byte peerLlcpVersion); + oneway void onNdefPushComplete(byte peerLlcpVersion); oneway void onTagDiscovered(in Tag tag); } diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index a6d8cafe8263d..8a30ef4c21210 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -18,6 +18,7 @@ package android.nfc; import android.app.PendingIntent; import android.content.IntentFilter; +import android.nfc.BeamShareData; import android.nfc.NdefMessage; import android.nfc.Tag; import android.nfc.TechListParcel; @@ -46,18 +47,24 @@ interface INfcAdapter int getState(); boolean disable(boolean saveState); boolean enable(); + boolean enableNdefPush(); + boolean disableNdefPush(); + boolean isNdefPushEnabled(); void pausePolling(int timeoutInMs); void resumePolling(); void setForegroundDispatch(in PendingIntent intent, in IntentFilter[] filters, in TechListParcel techLists); void setAppCallback(in IAppCallback callback); + oneway void invokeBeam(); + oneway void invokeBeamInternal(in BeamShareData shareData); boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback); void dispatch(in Tag tag); void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras); + void setP2pModes(int initatorModes, int targetModes); void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList); void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler); diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index 8d75cac531fb6..911aaf317e3e3 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -19,6 +19,9 @@ package android.nfc; import android.app.Activity; import android.app.Application; import android.compat.annotation.UnsupportedAppUsage; +import android.content.ContentProvider; +import android.content.Intent; +import android.net.Uri; import android.nfc.NfcAdapter.ReaderCallback; import android.os.Binder; import android.os.Bundle; @@ -107,8 +110,14 @@ public final class NfcActivityManager extends IAppCallback.Stub class NfcActivityState { boolean resumed = false; Activity activity; - NfcAdapter.ReaderCallback readerCallback = null; + NdefMessage ndefMessage = null; // static NDEF message + NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null; + NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null; + NfcAdapter.CreateBeamUrisCallback uriCallback = null; + Uri[] uris = null; + int flags = 0; int readerModeFlags = 0; + NfcAdapter.ReaderCallback readerCallback = null; Bundle readerModeExtras = null; Binder token; @@ -128,16 +137,24 @@ public final class NfcActivityManager extends IAppCallback.Stub unregisterApplication(activity.getApplication()); resumed = false; activity = null; - readerCallback = null; + ndefMessage = null; + ndefMessageCallback = null; + onNdefPushCompleteCallback = null; + uriCallback = null; + uris = null; readerModeFlags = 0; - readerModeExtras = null; token = null; } @Override public String toString() { - StringBuilder s = new StringBuilder("["); - s.append(readerCallback); - s.append("]"); + StringBuilder s = new StringBuilder("[").append(" "); + s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" "); + s.append(uriCallback).append(" "); + if (uris != null) { + for (Uri uri : uris) { + s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]"); + } + } return s.toString(); } } @@ -228,6 +245,92 @@ public final class NfcActivityManager extends IAppCallback.Stub } } + public void setNdefPushContentUri(Activity activity, Uri[] uris) { + boolean isResumed; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + state.uris = uris; + isResumed = state.resumed; + } + if (isResumed) { + // requestNfcServiceCallback() verifies permission also + requestNfcServiceCallback(); + } else { + // Crash API calls early in case NFC permission is missing + verifyNfcPermission(); + } + } + + + public void setNdefPushContentUriCallback(Activity activity, + NfcAdapter.CreateBeamUrisCallback callback) { + boolean isResumed; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + state.uriCallback = callback; + isResumed = state.resumed; + } + if (isResumed) { + // requestNfcServiceCallback() verifies permission also + requestNfcServiceCallback(); + } else { + // Crash API calls early in case NFC permission is missing + verifyNfcPermission(); + } + } + + public void setNdefPushMessage(Activity activity, NdefMessage message, int flags) { + boolean isResumed; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + state.ndefMessage = message; + state.flags = flags; + isResumed = state.resumed; + } + if (isResumed) { + // requestNfcServiceCallback() verifies permission also + requestNfcServiceCallback(); + } else { + // Crash API calls early in case NFC permission is missing + verifyNfcPermission(); + } + } + + public void setNdefPushMessageCallback(Activity activity, + NfcAdapter.CreateNdefMessageCallback callback, int flags) { + boolean isResumed; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + state.ndefMessageCallback = callback; + state.flags = flags; + isResumed = state.resumed; + } + if (isResumed) { + // requestNfcServiceCallback() verifies permission also + requestNfcServiceCallback(); + } else { + // Crash API calls early in case NFC permission is missing + verifyNfcPermission(); + } + } + + public void setOnNdefPushCompleteCallback(Activity activity, + NfcAdapter.OnNdefPushCompleteCallback callback) { + boolean isResumed; + synchronized (NfcActivityManager.this) { + NfcActivityState state = getActivityState(activity); + state.onNdefPushCompleteCallback = callback; + isResumed = state.resumed; + } + if (isResumed) { + // requestNfcServiceCallback() verifies permission also + requestNfcServiceCallback(); + } else { + // Crash API calls early in case NFC permission is missing + verifyNfcPermission(); + } + } + /** * Request or unrequest NFC service callbacks. * Makes IPC call - do not hold lock. @@ -248,6 +351,86 @@ public final class NfcActivityManager extends IAppCallback.Stub } } + /** Callback from NFC service, usually on binder thread */ + @Override + public BeamShareData createBeamShareData(byte peerLlcpVersion) { + NfcAdapter.CreateNdefMessageCallback ndefCallback; + NfcAdapter.CreateBeamUrisCallback urisCallback; + NdefMessage message; + Activity activity; + Uri[] uris; + int flags; + NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion); + synchronized (NfcActivityManager.this) { + NfcActivityState state = findResumedActivityState(); + if (state == null) return null; + + ndefCallback = state.ndefMessageCallback; + urisCallback = state.uriCallback; + message = state.ndefMessage; + uris = state.uris; + flags = state.flags; + activity = state.activity; + } + final long ident = Binder.clearCallingIdentity(); + try { + // Make callbacks without lock + if (ndefCallback != null) { + message = ndefCallback.createNdefMessage(event); + } + if (urisCallback != null) { + uris = urisCallback.createBeamUris(event); + if (uris != null) { + ArrayList validUris = new ArrayList(); + for (Uri uri : uris) { + if (uri == null) { + Log.e(TAG, "Uri not allowed to be null."); + continue; + } + String scheme = uri.getScheme(); + if (scheme == null || (!scheme.equalsIgnoreCase("file") && + !scheme.equalsIgnoreCase("content"))) { + Log.e(TAG, "Uri needs to have " + + "either scheme file or scheme content"); + continue; + } + uri = ContentProvider.maybeAddUserId(uri, activity.getUserId()); + validUris.add(uri); + } + + uris = validUris.toArray(new Uri[validUris.size()]); + } + } + if (uris != null && uris.length > 0) { + for (Uri uri : uris) { + // Grant the NFC process permission to read these URIs + activity.grantUriPermission("com.android.nfc", uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + return new BeamShareData(message, uris, activity.getUser(), flags); + } + + /** Callback from NFC service, usually on binder thread */ + @Override + public void onNdefPushComplete(byte peerLlcpVersion) { + NfcAdapter.OnNdefPushCompleteCallback callback; + synchronized (NfcActivityManager.this) { + NfcActivityState state = findResumedActivityState(); + if (state == null) return; + + callback = state.onNdefPushCompleteCallback; + } + NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion); + // Make callback without lock + if (callback != null) { + callback.onNdefPushComplete(event); + } + } + @Override public void onTagDiscovered(Tag tag) throws RemoteException { NfcAdapter.ReaderCallback callback; diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index d947b4805fb8a..a980158a2e5e7 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -345,10 +345,7 @@ public final class NfcAdapter { */ public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; - /** - * @hide - * @removed - */ + /** @hide */ @SystemApi public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1; @@ -423,6 +420,7 @@ public final class NfcAdapter { // Guarded by NfcAdapter.class static boolean sIsInitialized = false; static boolean sHasNfcFeature; + static boolean sHasBeamFeature; // Final after first constructor, except for // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort @@ -486,7 +484,7 @@ public final class NfcAdapter { * A callback to be invoked when the system successfully delivers your {@link NdefMessage} * to another device. * @see #setOnNdefPushCompleteCallback - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -512,7 +510,7 @@ public final class NfcAdapter { * content currently visible to the user. Alternatively, you can call {@link * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the * same data. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -542,7 +540,7 @@ public final class NfcAdapter { /** - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -573,6 +571,26 @@ public final class NfcAdapter { public boolean onUnlockAttempted(Tag tag); } + /** + * Helper to check if this device has FEATURE_NFC_BEAM, but without using + * a context. + * Equivalent to + * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM) + */ + private static boolean hasBeamFeature() { + IPackageManager pm = ActivityThread.getPackageManager(); + if (pm == null) { + Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature"); + return false; + } + try { + return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0); + } catch (RemoteException e) { + Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e); + return false; + } + } + /** * Helper to check if this device has FEATURE_NFC, but without using * a context. @@ -652,6 +670,7 @@ public final class NfcAdapter { public static synchronized NfcAdapter getNfcAdapter(Context context) { if (!sIsInitialized) { sHasNfcFeature = hasNfcFeature(); + sHasBeamFeature = hasBeamFeature(); boolean hasHceFeature = hasNfcHceFeature(); /* is this device meant to have NFC */ if (!sHasNfcFeature && !hasHceFeature) { @@ -1144,7 +1163,7 @@ public final class NfcAdapter { * @param uris an array of Uri(s) to push over Android Beam * @param activity activity for which the Uri(s) will be pushed * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -1153,7 +1172,26 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } } + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + if (uris != null) { + for (Uri uri : uris) { + if (uri == null) throw new NullPointerException("Uri not " + + "allowed to be null"); + String scheme = uri.getScheme(); + if (scheme == null || (!scheme.equalsIgnoreCase("file") && + !scheme.equalsIgnoreCase("content"))) { + throw new IllegalArgumentException("URI needs to have " + + "either scheme file or scheme content"); + } + } + } + mNfcActivityManager.setNdefPushContentUri(activity, uris); } /** @@ -1213,7 +1251,7 @@ public final class NfcAdapter { * @param callback callback, or null to disable * @param activity activity for which the Uri(s) will be pushed * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -1222,7 +1260,14 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } } + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + mNfcActivityManager.setNdefPushContentUriCallback(activity, callback); } /** @@ -1296,7 +1341,7 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -1306,12 +1351,36 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } + } + int targetSdkVersion = getSdkVersion(); + try { + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + mNfcActivityManager.setNdefPushMessage(activity, message, 0); + for (Activity a : activities) { + if (a == null) { + throw new NullPointerException("activities cannot contain null"); + } + mNfcActivityManager.setNdefPushMessage(a, message, 0); + } + } catch (IllegalStateException e) { + if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { + // Less strict on old applications - just log the error + Log.e(TAG, "Cannot call API with Activity that has already " + + "been destroyed", e); + } else { + // Prevent new applications from making this mistake, re-throw + throw(e); + } } } /** * @hide - * @removed */ @SystemApi public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { @@ -1320,6 +1389,10 @@ public final class NfcAdapter { throw new UnsupportedOperationException(); } } + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + mNfcActivityManager.setNdefPushMessage(activity, message, flags); } /** @@ -1387,7 +1460,7 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -1397,7 +1470,44 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } } + int targetSdkVersion = getSdkVersion(); + try { + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0); + for (Activity a : activities) { + if (a == null) { + throw new NullPointerException("activities cannot contain null"); + } + mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0); + } + } catch (IllegalStateException e) { + if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { + // Less strict on old applications - just log the error + Log.e(TAG, "Cannot call API with Activity that has already " + + "been destroyed", e); + } else { + // Prevent new applications from making this mistake, re-throw + throw(e); + } + } + } + + /** + * @hide + */ + @UnsupportedAppUsage + public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, + int flags) { + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags); } /** @@ -1437,7 +1547,7 @@ public final class NfcAdapter { * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -1447,6 +1557,31 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } + } + int targetSdkVersion = getSdkVersion(); + try { + if (activity == null) { + throw new NullPointerException("activity cannot be null"); + } + mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback); + for (Activity a : activities) { + if (a == null) { + throw new NullPointerException("activities cannot contain null"); + } + mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback); + } + } catch (IllegalStateException e) { + if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { + // Less strict on old applications - just log the error + Log.e(TAG, "Cannot call API with Activity that has already " + + "been destroyed", e); + } else { + // Prevent new applications from making this mistake, re-throw + throw(e); + } } } @@ -1629,7 +1764,7 @@ public final class NfcAdapter { * @param activity the current foreground Activity that has registered data to share * @return whether the Beam animation was successfully invoked * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated @@ -1638,8 +1773,37 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return false; + } + } + if (activity == null) { + throw new NullPointerException("activity may not be null."); + } + enforceResumed(activity); + try { + sService.invokeBeam(); + return true; + } catch (RemoteException e) { + Log.e(TAG, "invokeBeam: NFC process has died."); + attemptDeadServiceRecovery(e); + return false; + } + } + + /** + * @hide + */ + public boolean invokeBeam(BeamShareData shareData) { + try { + Log.e(TAG, "invokeBeamInternal()"); + sService.invokeBeamInternal(shareData); + return true; + } catch (RemoteException e) { + Log.e(TAG, "invokeBeam: NFC process has died."); + attemptDeadServiceRecovery(e); + return false; } - return false; } /** @@ -1665,9 +1829,9 @@ public final class NfcAdapter { * * @param activity foreground activity * @param message a NDEF Message to push over NFC - * @throws UnsupportedOperationException if FEATURE_NFC is unavailable - * @removed this feature is removed. File sharing can work using other technology like - * Bluetooth. + * @throws IllegalStateException if the activity is not currently in the foreground + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. + * @deprecated use {@link #setNdefPushMessage} instead */ @Deprecated public void enableForegroundNdefPush(Activity activity, NdefMessage message) { @@ -1675,7 +1839,15 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } } + if (activity == null || message == null) { + throw new NullPointerException(); + } + enforceResumed(activity); + mNfcActivityManager.setNdefPushMessage(activity, message, 0); } /** @@ -1694,9 +1866,9 @@ public final class NfcAdapter { *

Requires the {@link android.Manifest.permission#NFC} permission. * * @param activity the Foreground activity - * @throws UnsupportedOperationException if FEATURE_NFC is unavailable - * @removed this feature is removed. File sharing can work using other technology like - * Bluetooth. + * @throws IllegalStateException if the Activity has already been paused + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. + * @deprecated use {@link #setNdefPushMessage} instead */ @Deprecated public void disableForegroundNdefPush(Activity activity) { @@ -1704,7 +1876,17 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return; + } } + if (activity == null) { + throw new NullPointerException(); + } + enforceResumed(activity); + mNfcActivityManager.setNdefPushMessage(activity, null, 0); + mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0); + mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null); } /** @@ -1829,24 +2011,40 @@ public final class NfcAdapter { * Enable NDEF Push feature. *

This API is for the Settings application. * @hide - * @removed */ @SystemApi @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush() { - return false; + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + try { + return sService.enableNdefPush(); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; + } } /** * Disable NDEF Push feature. *

This API is for the Settings application. * @hide - * @removed */ @SystemApi @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush() { - return false; + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } + try { + return sService.disableNdefPush(); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; + } } /** @@ -1872,17 +2070,26 @@ public final class NfcAdapter { * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS * @return true if NDEF Push feature is enabled * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. - * @removed this feature is removed. File sharing can work using other technology like + * @deprecated this feature is deprecated. File sharing can work using other technology like * Bluetooth. */ @java.lang.Deprecated + public boolean isNdefPushEnabled() { synchronized (NfcAdapter.class) { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } + if (!sHasBeamFeature) { + return false; + } + } + try { + return sService.isNdefPushEnabled(); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; } - return false; } /** @@ -1972,6 +2179,17 @@ public final class NfcAdapter { } } + /** + * @hide + */ + public void setP2pModes(int initiatorModes, int targetModes) { + try { + sService.setP2pModes(initiatorModes, targetModes); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + /** * Registers a new NFC unlock handler with the NFC service. * diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 32773a027ff1d..249f48608d404 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -754,9 +754,12 @@ public class Build { * PackageManager.setComponentEnabledSetting} will now throw an * IllegalArgumentException if the given component class name does not * exist in the application's manifest. - *

  • {@code NfcAdapter.setNdefPushMessage}, - * {@code NfcAdapter.setNdefPushMessageCallback} and - * {@code NfcAdapter.setOnNdefPushCompleteCallback} will throw + *
  • {@link android.nfc.NfcAdapter#setNdefPushMessage + * NfcAdapter.setNdefPushMessage}, + * {@link android.nfc.NfcAdapter#setNdefPushMessageCallback + * NfcAdapter.setNdefPushMessageCallback} and + * {@link android.nfc.NfcAdapter#setOnNdefPushCompleteCallback + * NfcAdapter.setOnNdefPushCompleteCallback} will throw * IllegalStateException if called after the Activity has been destroyed. *
  • Accessibility services must require the new * {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission or diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 62b99ba2ef536..5b05f219119c4 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1711,6 +1711,7 @@ public final class Settings { * Input: Nothing. *

    * Output: Nothing + * @see android.nfc.NfcAdapter#isNdefPushEnabled() */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_NFCSHARING_SETTINGS = diff --git a/core/proto/android/nfc/nfc_service.proto b/core/proto/android/nfc/nfc_service.proto index 1dcd5cc210d95..2df1d5d210da8 100644 --- a/core/proto/android/nfc/nfc_service.proto +++ b/core/proto/android/nfc/nfc_service.proto @@ -60,7 +60,7 @@ message NfcServiceDumpProto { optional bool secure_nfc_capable = 13; optional bool vr_mode_enabled = 14; optional DiscoveryParamsProto discovery_params = 15; - reserved 16; + optional P2pLinkManagerProto p2p_link_manager = 16; optional com.android.nfc.cardemulation.CardEmulationManagerProto card_emulation_manager = 17; optional NfcDispatcherProto nfc_dispatcher = 18; optional string native_crash_logs = 19 [(.android.privacy).dest = DEST_EXPLICIT]; @@ -77,6 +77,38 @@ message DiscoveryParamsProto { optional bool enable_p2p = 5; } +// Debugging information for com.android.nfc.P2pLinkManager +message P2pLinkManagerProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + enum LinkState { + LINK_STATE_UNKNOWN = 0; + LINK_STATE_DOWN = 1; + LINK_STATE_DEBOUNCE = 2; + LINK_STATE_UP = 3; + } + + enum SendState { + SEND_STATE_UNKNOWN = 0; + SEND_STATE_NOTHING_TO_SEND = 1; + SEND_STATE_NEED_CONFIRMATION = 2; + SEND_STATE_SENDING = 3; + SEND_STATE_COMPLETE = 4; + SEND_STATE_CANCELED = 5; + } + + optional int32 default_miu = 1; + optional int32 default_rw_size = 2; + optional LinkState link_state = 3; + optional SendState send_state = 4; + optional int32 send_flags = 5; + optional bool send_enabled = 6; + optional bool receive_enabled = 7; + optional string callback_ndef = 8 [(.android.privacy).dest = DEST_EXPLICIT]; + optional .android.nfc.NdefMessageProto message_to_send = 9; + repeated string uris_to_send = 10 [(.android.privacy).dest = DEST_EXPLICIT]; +} + // Debugging information for com.android.nfc.NfcDispatcher message NfcDispatcherProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC;