Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab5d84cf authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add NFC TagIntentAppPreference System API"

parents 49d070c4 ba43e33c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -9120,14 +9120,20 @@ package android.nfc {
    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<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported();
    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
  }
  public static interface NfcAdapter.ControllerAlwaysOnListener {
+6 −0
Original line number Diff line number Diff line
@@ -80,4 +80,10 @@ interface INfcAdapter
    boolean isControllerAlwaysOnSupported();
    void registerControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener);
    void unregisterControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
    boolean isTagIntentAppPreferenceSupported();
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
    Map getTagIntentAppPreferenceForUser(int userId);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
    int setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow);
}
+175 −0
Original line number Diff line number Diff line
@@ -17,12 +17,14 @@
package android.nfc;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.OnActivityPausedListener;
@@ -46,9 +48,14 @@ import android.os.ServiceManager;
import android.util.Log;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
@@ -371,6 +378,45 @@ public final class NfcAdapter {
    public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC =
            "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";

    /**
     * The requested app is correctly added to the Tag intent app preference.
     *
     * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
     * @hide
     */
    @SystemApi
    public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0;

    /**
     * The requested app is not installed on the device.
     *
     * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
     * @hide
     */
    @SystemApi
    public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1;

    /**
     * The NfcService is not available.
     *
     * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
     * @hide
     */
    @SystemApi
    public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2;

    /**
     * Possible response codes from {@link #setTagIntentAppPreferenceForUser}.
     *
     * @hide
     */
    @IntDef(prefix = { "TAG_INTENT_APP_PREF_RESULT" }, value = {
            TAG_INTENT_APP_PREF_RESULT_SUCCESS,
            TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND,
            TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface TagIntentAppPreferenceResult {}

    // Guarded by NfcAdapter.class
    static boolean sIsInitialized = false;
    static boolean sHasNfcFeature;
@@ -2408,4 +2454,133 @@ public final class NfcAdapter {
            @NonNull ControllerAlwaysOnListener listener) {
        mControllerAlwaysOnListener.unregister(listener);
    }


    /**
     * Sets whether we dispatch NFC Tag intents to the package.
     *
     * <p>{@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
     * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
     * disallowed.
     * <p>An app is added to the preference list with the allowed flag set to {@code true}
     * when a Tag intent is dispatched to the package for the first time. This API is called
     * by settings to note that the user wants to change this default preference.
     *
     * @param userId the user to whom this package name will belong to
     * @param pkg the full name (i.e. com.google.android.tag) of the package that will be added to
     * the preference list
     * @param allow {@code true} to allow dispatching Tag intents to the package's activity,
     * {@code false} otherwise
     * @return the {@link #TagIntentAppPreferenceResult} value
     * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns
     * {@code false}
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    @TagIntentAppPreferenceResult
    public int setTagIntentAppPreferenceForUser(@UserIdInt int userId,
                @NonNull String pkg, boolean allow) {
        Objects.requireNonNull(pkg, "pkg cannot be null");
        if (!isTagIntentAppPreferenceSupported()) {
            Log.e(TAG, "TagIntentAppPreference is not supported");
            throw new UnsupportedOperationException();
        }
        try {
            return sService.setTagIntentAppPreferenceForUser(userId, pkg, allow);
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
            // Try one more time
            if (sService == null) {
                Log.e(TAG, "Failed to recover NFC Service.");
            }
            try {
                return sService.setTagIntentAppPreferenceForUser(userId, pkg, allow);
            } catch (RemoteException ee) {
                Log.e(TAG, "Failed to recover NFC Service.");
            }
            return TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE;
        }
    }


    /**
     * Get the Tag dispatch preference list of the UserId.
     *
     * <p>This returns a mapping of package names for this user id to whether we dispatch Tag
     * intents to the package. {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
    *  {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
    *  disallowed.
     *
     * @param userId the user to whom this preference list will belong to
     * @return a map of the UserId which indicates the mapping from package name to
     * boolean(allow status), otherwise return an empty map
     * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns
     * {@code false}
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    @NonNull
    public Map<String, Boolean> getTagIntentAppPreferenceForUser(@UserIdInt int userId) {
        if (!isTagIntentAppPreferenceSupported()) {
            Log.e(TAG, "TagIntentAppPreference is not supported");
            throw new UnsupportedOperationException();
        }
        try {
            Map<String, Boolean> result = (Map<String, Boolean>) sService
                     .getTagIntentAppPreferenceForUser(userId);
            return result;
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
            // Try one more time
            if (sService == null) {
                Log.e(TAG, "Failed to recover NFC Service.");
                return Collections.emptyMap();
            }
            try {
                Map<String, Boolean> result = (Map<String, Boolean>) sService
                        .getTagIntentAppPreferenceForUser(userId);
                return result;
            } catch (RemoteException ee) {
                Log.e(TAG, "Failed to recover NFC Service.");
            }
            return Collections.emptyMap();
        }
    }

    /**
     * Checks if the device supports Tag application preference.
     *
     * @return {@code true} if the device supports Tag application preference, {@code false}
     * otherwise
     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
    public boolean isTagIntentAppPreferenceSupported() {
        if (!sHasNfcFeature) {
            throw new UnsupportedOperationException();
        }
        try {
            return sService.isTagIntentAppPreferenceSupported();
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
            // Try one more time
            if (sService == null) {
                Log.e(TAG, "Failed to recover NFC Service.");
                return false;
            }
            try {
                return sService.isTagIntentAppPreferenceSupported();
            } catch (RemoteException ee) {
                Log.e(TAG, "Failed to recover NFC Service.");
            }
            return false;
        }
    }
}