1package com.android.nfc;
2
3import android.nfc.INfcUnlockHandler;
4import android.nfc.Tag;
5import android.os.IBinder;
6import android.util.Log;
7
8import java.util.HashMap;
9import java.util.Iterator;
10
11/**
12 * Singleton for handling NFC Unlock related logic and state.
13 */
14class NfcUnlockManager {
15    private static final String TAG = "NfcUnlockManager";
16
17    private final HashMap<IBinder, UnlockHandlerWrapper> mUnlockHandlers;
18    private int mLockscreenPollMask;
19
20    private static class UnlockHandlerWrapper {
21        final INfcUnlockHandler mUnlockHandler;
22        final int mPollMask;
23
24
25        private UnlockHandlerWrapper(INfcUnlockHandler unlockHandler, int pollMask) {
26            mUnlockHandler = unlockHandler;
27            mPollMask = pollMask;
28        }
29    }
30
31    public static NfcUnlockManager getInstance() {
32        return Singleton.INSTANCE;
33    }
34
35
36    synchronized int addUnlockHandler(INfcUnlockHandler unlockHandler, int pollMask) {
37        if (mUnlockHandlers.containsKey(unlockHandler.asBinder())) {
38            return mLockscreenPollMask;
39        }
40
41        mUnlockHandlers.put(unlockHandler.asBinder(),
42                new UnlockHandlerWrapper(unlockHandler, pollMask));
43        return (mLockscreenPollMask |= pollMask);
44    }
45
46    synchronized int removeUnlockHandler(IBinder unlockHandler) {
47        if (mUnlockHandlers.containsKey(unlockHandler)) {
48            mUnlockHandlers.remove(unlockHandler);
49            mLockscreenPollMask = recomputePollMask();
50        }
51
52        return mLockscreenPollMask;
53    }
54
55    synchronized boolean tryUnlock(Tag tag) {
56        Iterator<IBinder> iterator = mUnlockHandlers.keySet().iterator();
57        while (iterator.hasNext()) {
58            try {
59                IBinder binder = iterator.next();
60                UnlockHandlerWrapper handlerWrapper = mUnlockHandlers.get(binder);
61                if (handlerWrapper.mUnlockHandler.onUnlockAttempted(tag)) {
62                    return true;
63                }
64            } catch (Exception e) {
65                Log.e(TAG, "failed to communicate with unlock handler, removing", e);
66                iterator.remove();
67                mLockscreenPollMask = recomputePollMask();
68            }
69        }
70
71        return false;
72    }
73
74    private int recomputePollMask() {
75        int pollMask = 0;
76        for (UnlockHandlerWrapper wrapper : mUnlockHandlers.values()) {
77            pollMask |= wrapper.mPollMask;
78        }
79        return pollMask;
80    }
81
82    synchronized int getLockscreenPollMask() {
83        return mLockscreenPollMask;
84    }
85
86    synchronized boolean isLockscreenPollingEnabled() {
87        return mLockscreenPollMask != 0;
88    }
89
90    private static class Singleton {
91        private static final NfcUnlockManager INSTANCE = new NfcUnlockManager();
92    }
93
94    private NfcUnlockManager() {
95        mUnlockHandlers = new HashMap<IBinder, UnlockHandlerWrapper>();
96        mLockscreenPollMask = 0;
97    }
98}
99
100