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

Commit bb951c89 authored by Jeff Hamilton's avatar Jeff Hamilton Committed by Nick Pelly
Browse files

Changes for access control.

The package name is now required when using the
NFC extras APIs so the context is stored away
and used to derive the package name to be sent
to the NfcService.

Bug: 4515759
Change-Id: I1a3aba3fc026e0090a914b0686fc4b8dec25b927
parent de62d9cb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import android.nfc.INfcTag;
interface INfcAdapter
{
    INfcTag getNfcTagInterface();
    INfcAdapterExtras getNfcAdapterExtrasInterface();
    INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);

    int getState();
    boolean disable();
+6 −6
Original line number Diff line number Diff line
@@ -23,10 +23,10 @@ import android.os.Bundle;
 * {@hide}
 */
interface INfcAdapterExtras {
    Bundle open(IBinder b);
    Bundle close();
    Bundle transceive(in byte[] data_in);
    int getCardEmulationRoute();
    void setCardEmulationRoute(int route);
    void authenticate(in byte[] token);
    Bundle open(in String pkg, IBinder b);
    Bundle close(in String pkg, IBinder b);
    Bundle transceive(in String pkg, in byte[] data_in);
    int getCardEmulationRoute(in String pkg);
    void setCardEmulationRoute(in String pkg, int route);
    void authenticate(in String pkg, in byte[] token);
}
+54 −24
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.nfc;

import java.util.HashMap;

import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Activity;
@@ -197,15 +199,21 @@ public final class NfcAdapter {
    static INfcTag sTagService;

    /**
     * NfcAdapter is currently a singleton, and does not require a context.
     * However all the public API's are future-proofed to require a context.
     * If we start using that then we'll need to keep a HashMap of
     * Context.getApplicationContext() -> NfcAdapter, such that NfcAdapter
     * is a singleton within each application context.
     * The NfcAdapter object for each application context.
     * There is a 1-1 relationship between application context and
     * NfcAdapter object.
     */
    static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class

    /**
     * NfcAdapter used with a null context. This ctor was deprecated but we have
     * to support it for backwards compatibility. New methods that require context
     * might throw when called on the null-context NfcAdapter.
     */
    static NfcAdapter sSingleton;  // protected by NfcAdapter.class
    static NfcAdapter sNullContextNfcAdapter;  // protected by NfcAdapter.class

    final NfcActivityManager mNfcActivityManager;
    final Context mContext;

    /**
     * A callback to be invoked when the system successfully delivers your {@link NdefMessage}
@@ -280,12 +288,12 @@ public final class NfcAdapter {
    }

    /**
     * Returns the singleton, or throws if NFC is not available.
     * Returns the NfcAdapter for application context,
     * or throws if NFC is not available.
     * @hide
     */
    static synchronized NfcAdapter getSingleton() {
    public static synchronized NfcAdapter getNfcAdapter(Context context) {
        if (!sIsInitialized) {
            sIsInitialized = true;

            /* is this device meant to have NFC */
            if (!hasNfcFeature()) {
                Log.v(TAG, "this device does not have NFC support");
@@ -303,12 +311,21 @@ public final class NfcAdapter {
                Log.e(TAG, "could not retrieve NFC Tag service");
                throw new UnsupportedOperationException();
            }
            sSingleton = new NfcAdapter();

            sIsInitialized = true;
        }
        if (context == null) {
            if (sNullContextNfcAdapter == null) {
                sNullContextNfcAdapter = new NfcAdapter(null);
            }
        if (sSingleton == null) {
            throw new UnsupportedOperationException();
            return sNullContextNfcAdapter;
        }
        NfcAdapter adapter = sNfcAdapters.get(context);
        if (adapter == null) {
            adapter = new NfcAdapter(context);
            sNfcAdapters.put(context, adapter);
        }
        return sSingleton;
        return adapter;
    }

    /** get handle to NFC service interface */
@@ -336,6 +353,10 @@ public final class NfcAdapter {
     * @return the default NFC adapter, or null if no NFC adapter exists
     */
    public static NfcAdapter getDefaultAdapter(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("context cannot be null");
        }
        context = context.getApplicationContext();
        /* use getSystemService() instead of just instantiating to take
         * advantage of the context's cached NfcManager & NfcAdapter */
        NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
@@ -343,25 +364,30 @@ public final class NfcAdapter {
    }

    /**
     * Get a handle to the default NFC Adapter on this Android device.
     * <p>
     * Most Android devices will only have one NFC Adapter (NFC Controller).
     *
     * @return the default NFC adapter, or null if no NFC adapter exists
     * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p>
     * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required
     * for many NFC API methods. Those methods will fail when called on an NfcAdapter
     * object created from this method.<p>
     * @deprecated use {@link #getDefaultAdapter(Context)}
     */
    @Deprecated
    public static NfcAdapter getDefaultAdapter() {
        Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
                "NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
        return getSingleton();

        return NfcAdapter.getNfcAdapter(null);
    }

    NfcAdapter(Context context) {
        mContext = context;
        mNfcActivityManager = new NfcActivityManager(this);
    }

    /**
     * Does not currently need a context.
     * @hide
     */
    NfcAdapter() {
        mNfcActivityManager = new NfcActivityManager(this);
    public Context getContext() {
        return mContext;
    }

    /**
@@ -875,8 +901,12 @@ public final class NfcAdapter {
     * @hide
     */
    public INfcAdapterExtras getNfcAdapterExtrasInterface() {
        if (mContext == null) {
            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
                    + " NFC extras APIs");
        }
        try {
            return sService.getNfcAdapterExtrasInterface();
            return sService.getNfcAdapterExtrasInterface(mContext.getPackageName());
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
            return null;
+2 −1
Original line number Diff line number Diff line
@@ -39,8 +39,9 @@ public final class NfcManager {
     */
    public NfcManager(Context context) {
        NfcAdapter adapter;
        context = context.getApplicationContext();
        try {
            adapter = NfcAdapter.getSingleton();
            adapter = NfcAdapter.getNfcAdapter(context);
        } catch (UnsupportedOperationException e) {
            adapter = null;
        }
+37 −32
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@

package com.android.nfc_extras;

import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.nfc.INfcAdapterExtras;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
@@ -60,10 +59,14 @@ public final class NfcAdapterExtras {
    // best effort recovery
    private static NfcAdapter sAdapter;
    private static INfcAdapterExtras sService;
    private static NfcAdapterExtras sSingleton;
    private static NfcExecutionEnvironment sEmbeddedEe;
    private static CardEmulationRoute sRouteOff;
    private static CardEmulationRoute sRouteOnWhenScreenOn;
    private static final CardEmulationRoute ROUTE_OFF =
            new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);

    private final NfcExecutionEnvironment mEmbeddedEe;
    private final CardEmulationRoute mRouteOnWhenScreenOn;

    final Context mContext;
    final String mPackageName;

    /** get service handles */
    private static void initService() {
@@ -84,31 +87,35 @@ public final class NfcAdapterExtras {
     * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
     */
    public static NfcAdapterExtras get(NfcAdapter adapter) {
        Context context = adapter.getContext();
        if (context == null) {
            throw new UnsupportedOperationException(
                    "You must pass a context to your NfcAdapter to use the NFC extras APIs");
        }

        synchronized (NfcAdapterExtras.class) {
            if (sSingleton == null) {
            if (sService == null) {
                try {
                    sAdapter = adapter;
                    sSingleton = new NfcAdapterExtras();
                    sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
                    sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
                    sRouteOnWhenScreenOn = new CardEmulationRoute(
                            CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
                    initService();
                } finally {
                    if (sService == null) {
                        sRouteOnWhenScreenOn = null;
                        sRouteOff = null;
                        sEmbeddedEe = null;
                        sSingleton = null;
                        sAdapter = null;
                    }
                }
            }
            return sSingleton;
        }

        return new NfcAdapterExtras(context);
    }

    private NfcAdapterExtras() {}
    private NfcAdapterExtras(Context context) {
        mContext = context.getApplicationContext();
        mPackageName = context.getPackageName();
        mEmbeddedEe = new NfcExecutionEnvironment(this);
        mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
                mEmbeddedEe);
    }

    /**
     * Immutable data class that describes a card emulation route.
@@ -166,18 +173,16 @@ public final class NfcAdapterExtras {
     *
     * <p class="note">
     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
     *
     * @return
     */
    public CardEmulationRoute getCardEmulationRoute() {
        try {
            int route = sService.getCardEmulationRoute();
            int route = sService.getCardEmulationRoute(mPackageName);
            return route == CardEmulationRoute.ROUTE_OFF ?
                    sRouteOff :
                    sRouteOnWhenScreenOn;
                    ROUTE_OFF :
                    mRouteOnWhenScreenOn;
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
            return sRouteOff;
            return ROUTE_OFF;
        }
    }

@@ -189,11 +194,11 @@ public final class NfcAdapterExtras {
     * <p class="note">
     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
     *
     * @param route a {@link #CardEmulationRoute}
     * @param route a {@link CardEmulationRoute}
     */
    public void setCardEmulationRoute(CardEmulationRoute route) {
        try {
            sService.setCardEmulationRoute(route.route);
            sService.setCardEmulationRoute(mPackageName, route.route);
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
        }
@@ -201,7 +206,7 @@ public final class NfcAdapterExtras {

    /**
     * Get the {@link NfcExecutionEnvironment} that is embedded with the
     * {@link NFcAdapter}.
     * {@link NfcAdapter}.
     *
     * <p class="note">
     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
@@ -209,7 +214,7 @@ public final class NfcAdapterExtras {
     * @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE
     */
    public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
        return sEmbeddedEe;
        return mEmbeddedEe;
    }

    /**
@@ -218,12 +223,12 @@ public final class NfcAdapterExtras {
     * Some implementations of NFC Adapter Extras may require applications
     * to authenticate with a token, before using other methods.
     *
     * @param a implementation specific token
     * @throws a {@link java.lang.SecurityException} if authentication failed
     * @param token a implementation specific token
     * @throws java.lang.SecurityException if authentication failed
     */
    public void authenticate(byte[] token) {
        try {
            sService.authenticate(token);
            sService.authenticate(mPackageName, token);
        } catch (RemoteException e) {
            attemptDeadServiceRecovery(e);
        }
Loading