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

Commit 6d55e134 authored by Nick Pelly's avatar Nick Pelly
Browse files

Make best effort attempt to recover NFC service when it dies.



Retrieve the service again from ServiceManager on RemoteException.

Change-Id: Ie227b52019e7deafeab712af1addd6d957f7a8ee
Signed-off-by: default avatarNick Pelly <npelly@google.com>
parent 2088e371
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -42,8 +42,8 @@ public class NdefTagConnection extends RawTagConnection {
     * Internal constructor, to be used by NfcAdapter
     * @hide
     */
    /* package private */ NdefTagConnection(INfcAdapter service, NdefTag tag, String target) throws RemoteException {
        super(service, tag);
    /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag, String target) throws RemoteException {
        super(adapter, tag);
        String[] targets = tag.getNdefTargets();
        int i;

@@ -63,8 +63,8 @@ public class NdefTagConnection extends RawTagConnection {
     * Internal constructor, to be used by NfcAdapter
     * @hide
     */
    /* package private */ NdefTagConnection(INfcAdapter service, NdefTag tag) throws RemoteException {
        this(service, tag, tag.getNdefTargets()[0]);
    /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag) throws RemoteException {
        this(adapter, tag, tag.getNdefTargets()[0]);
    }

    /**
@@ -97,7 +97,7 @@ public class NdefTagConnection extends RawTagConnection {
            msgArray[0] = msg;
            return msgArray;
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died");
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
@@ -134,7 +134,7 @@ public class NdefTagConnection extends RawTagConnection {
                    throw new IOException();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died");
            attemptDeadServiceRecovery(e);
        }
    }

@@ -161,7 +161,7 @@ public class NdefTagConnection extends RawTagConnection {
                    throw new IOException();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died");
            attemptDeadServiceRecovery(e);
            return false;
        }
    }
@@ -188,7 +188,7 @@ public class NdefTagConnection extends RawTagConnection {
            return result;

        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died");
            attemptDeadServiceRecovery(e);
            return NDEF_MODE_UNKNOWN;
        }
    }
+44 −18
Original line number Diff line number Diff line
@@ -168,7 +168,10 @@ public final class NfcAdapter {
    private static boolean sIsInitialized = false;
    private static NfcAdapter sAdapter;

    private final INfcAdapter mService;
    // Final after construction, except for attemptDeadServiceRecovery()
    // when NFC crashes.
    // Not locked - we accept a best effort attempt when NFC crashes.
    /*package*/ INfcAdapter mService;

    private NfcAdapter(INfcAdapter service) {
        mService = service;
@@ -194,6 +197,16 @@ public final class NfcAdapter {
        }
    }

    /** get handle to NFC service interface */
    private static synchronized INfcAdapter getServiceInterface() {
        /* get a handle to NFC service */
        IBinder b = ServiceManager.getService("nfc");
        if (b == null) {
            return null;
        }
        return INfcAdapter.Stub.asInterface(b);
    }

    /**
     * Get a handle to the default NFC Adapter on this Android device.
     * <p>
@@ -214,18 +227,31 @@ public final class NfcAdapter {
                return null;
            }

            /* get a handle to NFC service */
            IBinder b = ServiceManager.getService("nfc");
            if (b == null) {
            INfcAdapter service = getServiceInterface();
            if (service == null) {
                Log.e(TAG, "could not retrieve NFC service");
                return null;
            }

            sAdapter = new NfcAdapter(INfcAdapter.Stub.asInterface(b));
            sAdapter = new NfcAdapter(service);
            return sAdapter;
        }
    }

    /** NFC service dead - attempt best effort recovery */
    /*package*/ void attemptDeadServiceRecovery(Exception e) {
        Log.e(TAG, "NFC service dead - attempting to recover", e);
        INfcAdapter service = getServiceInterface();
        if (service == null) {
            Log.e(TAG, "could not retrieve NFC service during service recovery");
            return;
        }
        /* assigning to mService is not thread-safe, but this is best-effort code
         * and on a well-behaved system should never happen */
        mService = service;
        return;
    }

    /**
     * Return true if this NFC Adapter has any features enabled.
     * <p>
@@ -241,7 +267,7 @@ public final class NfcAdapter {
        try {
            return mService.isEnabled();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in isEnabled()", e);
            attemptDeadServiceRecovery(e);
            return false;
        }
    }
@@ -258,7 +284,7 @@ public final class NfcAdapter {
        try {
            return mService.enable();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in enable()", e);
            attemptDeadServiceRecovery(e);
            return false;
        }
    }
@@ -277,7 +303,7 @@ public final class NfcAdapter {
        try {
            return mService.disable();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in disable()", e);
            attemptDeadServiceRecovery(e);
            return false;
        }
    }
@@ -303,7 +329,7 @@ public final class NfcAdapter {
        try {
            mService.localSet(message);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
        }
    }

@@ -317,7 +343,7 @@ public final class NfcAdapter {
        try {
            return mService.localGet();
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
@@ -331,9 +357,9 @@ public final class NfcAdapter {
            throw new IllegalArgumentException("mock tag cannot be used for connections");
        }
        try {
            return new RawTagConnection(mService, tag);
            return new RawTagConnection(this, tag);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
@@ -347,9 +373,9 @@ public final class NfcAdapter {
            throw new IllegalArgumentException("mock tag cannot be used for connections");
        }
        try {
            return new RawTagConnection(mService, tag, target);
            return new RawTagConnection(this, tag, target);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
@@ -363,9 +389,9 @@ public final class NfcAdapter {
            throw new IllegalArgumentException("mock tag cannot be used for connections");
        }
        try {
            return new NdefTagConnection(mService, tag);
            return new NdefTagConnection(this, tag);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
@@ -379,9 +405,9 @@ public final class NfcAdapter {
            throw new IllegalArgumentException("mock tag cannot be used for connections");
        }
        try {
            return new NdefTagConnection(mService, tag, target);
            return new NdefTagConnection(this, tag, target);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
+29 −10
Original line number Diff line number Diff line
@@ -35,15 +35,20 @@ import android.util.Log;
 */
public class RawTagConnection {

    /*package*/ final INfcAdapter mService;
    /*package*/ final INfcTag mTagService;
    /*package*/ final Tag mTag;
    /*package*/ boolean mIsConnected;
    /*package*/ String mSelectedTarget;
    private final NfcAdapter mAdapter;

    // Following fields are final after construction, except for
    // during attemptDeadServiceRecovery() when NFC crashes.
    // Not locked - we accept a best effort attempt when NFC crashes.
    /*package*/ INfcAdapter mService;
    /*package*/ INfcTag mTagService;

    private static final String TAG = "NFC";

    /* package private */ RawTagConnection(INfcAdapter service, Tag tag, String target) throws RemoteException {
    /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag, String target) throws RemoteException {
        String[] targets = tag.getRawTargets();
        int i;

@@ -58,14 +63,28 @@ public class RawTagConnection {
            throw new IllegalArgumentException();
        }

        mService = service;
        mTagService = service.getNfcTagInterface();
        mAdapter = adapter;
        mService = mAdapter.mService;
        mTagService = mService.getNfcTagInterface();
        mTag = tag;
        mSelectedTarget = target;
    }

    /* package private */ RawTagConnection(INfcAdapter service, Tag tag) throws RemoteException {
        this(service, tag, tag.getRawTargets()[0]);
    /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag) throws RemoteException {
        this(adapter, tag, tag.getRawTargets()[0]);
    }

    /** NFC service dead - attempt best effort recovery */
    /*package*/ void attemptDeadServiceRecovery(Exception e) {
        mAdapter.attemptDeadServiceRecovery(e);
        /* assigning to mService is not thread-safe, but this is best-effort code
         * and on a well-behaved system should never happen */
        mService = mAdapter.mService;
        try {
            mTagService = mService.getNfcTagInterface();
        } catch (RemoteException e2) {
            Log.e(TAG, "second RemoteException trying to recover from dead NFC service", e2);
        }
    }

    /**
@@ -101,7 +120,7 @@ public class RawTagConnection {
        try {
            return mTagService.isPresent(mTag.mServiceHandle);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            return false;
        }
    }
@@ -136,7 +155,7 @@ public class RawTagConnection {
        try {
            mTagService.close(mTag.mServiceHandle);
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
        }
    }

@@ -159,7 +178,7 @@ public class RawTagConnection {
            }
            return response;
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service died", e);
            attemptDeadServiceRecovery(e);
            throw new IOException("NFC service died");
        }
    }