1a7596147b43940cad3f76c53ed154ef088b9269bJim Miller/**
2a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Copyright (C) 2014 The Android Open Source Project
3a7596147b43940cad3f76c53ed154ef088b9269bJim Miller *
4a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Licensed under the Apache License, Version 2.0 (the "License");
5a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * you may not use this file except in compliance with the License.
6a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * You may obtain a copy of the License at
7a7596147b43940cad3f76c53ed154ef088b9269bJim Miller *
8a7596147b43940cad3f76c53ed154ef088b9269bJim Miller *      http://www.apache.org/licenses/LICENSE-2.0
9a7596147b43940cad3f76c53ed154ef088b9269bJim Miller *
10a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Unless required by applicable law or agreed to in writing, software
11a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * distributed under the License is distributed on an "AS IS" BASIS,
12a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * See the License for the specific language governing permissions and
14a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * limitations under the License.
15a7596147b43940cad3f76c53ed154ef088b9269bJim Miller */
16a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
17a7596147b43940cad3f76c53ed154ef088b9269bJim Millerpackage com.android.server.fingerprint;
18a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
19a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.app.Service;
20a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.content.ContentResolver;
21a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.content.Context;
22a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.content.Intent;
23a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.Handler;
24a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.IBinder;
25a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.PowerManager;
26a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.RemoteException;
27a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.provider.Settings;
28a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.service.fingerprint.FingerprintManager;
29a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.ArrayMap;
30a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.Slog;
31a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
32a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport com.android.server.SystemService;
33a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
34a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.service.fingerprint.FingerprintUtils;
35a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.service.fingerprint.IFingerprintService;
36a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.service.fingerprint.IFingerprintServiceReceiver;
37a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
38a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport java.io.PrintWriter;
39a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport java.lang.ref.WeakReference;
40a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport java.util.HashMap;
41a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport java.util.Map.Entry;
42a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport java.util.Set;
43a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
44a7596147b43940cad3f76c53ed154ef088b9269bJim Miller/**
45a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * A service to manage multiple clients that want to access the fingerprint HAL API.
46a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * The service is responsible for maintaining a list of clients and dispatching all
47a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * fingerprint -related events.
48a7596147b43940cad3f76c53ed154ef088b9269bJim Miller *
49a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * @hide
50a7596147b43940cad3f76c53ed154ef088b9269bJim Miller */
51a7596147b43940cad3f76c53ed154ef088b9269bJim Millerpublic class FingerprintService extends SystemService {
52a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private final String TAG = "FingerprintService";
53a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final boolean DEBUG = true;
54a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private ArrayMap<IBinder, ClientData> mClients = new ArrayMap<IBinder, ClientData>();
55a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
56a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int MSG_NOTIFY = 10;
57a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
58a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    Handler mHandler = new Handler() {
59a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void handleMessage(android.os.Message msg) {
60a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            switch (msg.what) {
61a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                case MSG_NOTIFY:
62a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    handleNotify(msg.arg1, msg.arg2, (Integer) msg.obj);
63a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    break;
64a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
65a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                default:
66a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    Slog.w(TAG, "Unknown message:" + msg.what);
67a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
68a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
69a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    };
70a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private Context mContext;
71a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
72a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int STATE_IDLE = 0;
73a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int STATE_LISTENING = 1;
74a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int STATE_ENROLLING = 2;
75a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int STATE_REMOVING = 3;
76a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final long MS_PER_SEC = 1000;
77a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
78a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final String ENROLL_FINGERPRINT = "android.permission.ENROLL_FINGERPRINT";
79a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
80a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final class ClientData {
81a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public IFingerprintServiceReceiver receiver;
82a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        int state;
83a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        int userId;
84a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public TokenWatcher tokenWatcher;
85a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        IBinder getToken() { return tokenWatcher.getToken(); }
86a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
87a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
88a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private class TokenWatcher implements IBinder.DeathRecipient {
89a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        WeakReference<IBinder> token;
90a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
91a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        TokenWatcher(IBinder token) {
92a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            this.token = new WeakReference<IBinder>(token);
93a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
94a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
95a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        IBinder getToken() { return token.get(); }
96a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void binderDied() {
97a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            mClients.remove(token);
98a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            this.token = null;
99a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
100a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
101a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        protected void finalize() throws Throwable {
102a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            try {
103a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                if (token != null) {
104a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token);
105a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    mClients.remove(token);
106a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                }
107a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            } finally {
108a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                super.finalize();
109a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
110a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
111a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
112a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
113a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public FingerprintService(Context context) {
114a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        super(context);
115a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        mContext = context;
116a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        nativeInit(this);
117a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
118a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
119a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    // TODO: Move these into separate process
120a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    // JNI methods to communicate from FingerprintManagerService to HAL
121a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    native int nativeEnroll(int timeout);
122a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    native int nativeEnrollCancel();
123a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    native int nativeRemove(int fingerprintId);
124a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    native int nativeOpenHal();
125a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    native int nativeCloseHal();
126a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    native void nativeInit(FingerprintService service);
127a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
128a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    // JNI methods for communicating from HAL to clients
129a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void notify(int msg, int arg1, int arg2) {
130a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        mHandler.obtainMessage(MSG_NOTIFY, msg, arg1, arg2).sendToTarget();
131a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
132a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
133a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void handleNotify(int msg, int arg1, int arg2) {
134a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        Slog.v(TAG, "handleNotify(msg=" + msg + ", arg1=" + arg1 + ", arg2=" + arg2 + ")");
135a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        for (int i = 0; i < mClients.size(); i++) {
136a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            ClientData clientData = mClients.valueAt(i);
137a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (clientData == null || clientData.receiver == null) {
138a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                if (DEBUG) Slog.v(TAG, "clientData at " + i + " is invalid!!");
139a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                continue;
140a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
141a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            switch (msg) {
142a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                case FingerprintManager.FINGERPRINT_ERROR: {
143a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    final int error = arg1;
144a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    try {
145a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        clientData.receiver.onError(error);
146a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    } catch (RemoteException e) {
147a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        Slog.e(TAG, "can't send message to client. Did it die?", e);
148a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        mClients.remove(mClients.keyAt(i));
149a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    }
150a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                }
151a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                break;
152a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                case FingerprintManager.FINGERPRINT_ACQUIRED: {
153a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    final int acquireInfo = arg1;
154a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    try {
155a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        clientData.receiver.onAcquired(acquireInfo);
156a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    } catch (RemoteException e) {
157a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        Slog.e(TAG, "can't send message to client. Did it die?", e);
158a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        mClients.remove(mClients.keyAt(i));
159a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    }
160a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    break;
161a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                }
162a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                case FingerprintManager.FINGERPRINT_PROCESSED: {
163a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    final int fingerId = arg1;
164a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    try {
165a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        clientData.receiver.onProcessed(fingerId);
166a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    } catch (RemoteException e) {
167a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        Slog.e(TAG, "can't send message to client. Did it die?", e);
168a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        mClients.remove(mClients.keyAt(i));
169a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    }
170a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    break;
171a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                }
172a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: {
173a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    final int fingerId = arg1;
174a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    final int remaining = arg2;
175a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    if (clientData.state == STATE_ENROLLING) {
176a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        // Only send enroll updates to clients that are actually enrolling
177a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        try {
178a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            clientData.receiver.onEnrollResult(fingerId, remaining);
179a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        } catch (RemoteException e) {
180a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            Slog.e(TAG, "can't send message to client. Did it die?", e);
181a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            mClients.remove(mClients.keyAt(i));
182a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        }
183a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        // Update the database with new finger id.
184a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        // TODO: move to client code (Settings)
185a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        if (remaining == 0) {
186a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            FingerprintUtils.addFingerprintIdForUser(fingerId,
187a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                                    mContext.getContentResolver(), clientData.userId);
188a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            clientData.state = STATE_IDLE; // Nothing left to do
189a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        }
190a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    } else {
191a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        if (DEBUG) Slog.w(TAG, "Client not enrolling");
192a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        break;
193a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    }
194a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    break;
195a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                }
196a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: {
197a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    int fingerId = arg1;
198a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL");
199a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    FingerprintUtils.removeFingerprintIdForUser(fingerId,
200a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            mContext.getContentResolver(), clientData.userId);
201a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    if (clientData.receiver != null) {
202a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        try {
203a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            clientData.receiver.onRemoved(fingerId);
204a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        } catch (RemoteException e) {
205a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            Slog.e(TAG, "can't send message to client. Did it die?", e);
206a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                            mClients.remove(mClients.keyAt(i));
207a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                        }
208a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    }
209a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    clientData.state = STATE_LISTENING;
210a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                }
211a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                break;
212a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
213a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
214a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
215a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
216a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void startEnroll(IBinder token, long timeout, int userId) {
217a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        ClientData clientData = mClients.get(token);
218a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (clientData != null) {
219a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (clientData.userId != userId) throw new IllegalStateException("Bad user");
220a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.state = STATE_ENROLLING;
221a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            nativeEnroll((int) (timeout / MS_PER_SEC));
222a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
223a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            Slog.w(TAG, "enroll(): No listener registered");
224a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
225a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
226a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
227a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void startEnrollCancel(IBinder token, int userId) {
228a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        ClientData clientData = mClients.get(token);
229a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (clientData != null) {
230a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (clientData.userId != userId) throw new IllegalStateException("Bad user");
231a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.state = STATE_LISTENING;
232a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            nativeEnrollCancel();
233a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
234a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            Slog.w(TAG, "enrollCancel(): No listener registered");
235a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
236a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
237a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
238a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    // Remove all fingerprints for the given user.
239a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void startRemove(IBinder token, int fingerId, int userId) {
240a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        ClientData clientData = mClients.get(token);
241a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (clientData != null) {
242a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (clientData.userId != userId) throw new IllegalStateException("Bad user");
243a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.state = STATE_REMOVING;
244a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            // The fingerprint id will be removed when we get confirmation from the HAL
245a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            int result = nativeRemove(fingerId);
246a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (result != 0) {
247a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                Slog.w(TAG, "Error removing fingerprint with id = " + fingerId);
248a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
249a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
250a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            Slog.w(TAG, "remove(" + token + "): No listener registered");
251a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
252a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
253a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
254a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void addListener(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
255a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (DEBUG) Slog.v(TAG, "startListening(" + receiver + ")");
256a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (mClients.get(token) == null) {
257a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            ClientData clientData = new ClientData();
258a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.state = STATE_LISTENING;
259a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.receiver = receiver;
260a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.userId = userId;
261a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            clientData.tokenWatcher = new TokenWatcher(token);
262a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            try {
263a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                token.linkToDeath(clientData.tokenWatcher, 0);
264a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                mClients.put(token, clientData);
265a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            } catch (RemoteException e) {
266a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
267a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
268a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
269a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (DEBUG) Slog.v(TAG, "listener already registered for " + token);
270a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
271a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
272a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
273a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void removeListener(IBinder token, int userId) {
274a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (DEBUG) Slog.v(TAG, "stopListening(" + token + ")");
275a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        ClientData clientData = mClients.get(token);
276a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        if (clientData != null) {
277a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            token.unlinkToDeath(clientData.tokenWatcher, 0);
278a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            mClients.remove(token);
279a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
280a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            if (DEBUG) Slog.v(TAG, "listener not registered: " + token);
281a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
282a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        mClients.remove(token);
283a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
284a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
285a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    void checkPermission(String permisison) {
286a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        // TODO
287a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
288a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
289a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
290a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        @Override // Binder call
291a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void enroll(IBinder token, long timeout, int userId) {
292a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            checkPermission(ENROLL_FINGERPRINT);
293a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            startEnroll(token, timeout, userId);
294a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
295a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
296a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        @Override // Binder call
297a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void enrollCancel(IBinder token,int userId) {
298a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            checkPermission(ENROLL_FINGERPRINT);
299a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            startEnrollCancel(token, userId);
300a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
301a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
302a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        @Override // Binder call
303a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void remove(IBinder token, int fingerprintId, int userId) {
304a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            checkPermission(ENROLL_FINGERPRINT); // TODO: Maybe have another permission
305a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            startRemove(token, fingerprintId, userId);
306a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
307a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
308a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        @Override // Binder call
309a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId)
310a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        {
311a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            checkPermission(USE_FINGERPRINT);
312a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            addListener(token, receiver, userId);
313a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
314a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
315a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        @Override // Binder call
316a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void stopListening(IBinder token, int userId) {
317a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            checkPermission(USE_FINGERPRINT);
318a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            removeListener(token, userId);
319a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
320a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
321a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
322a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    @Override
323a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public void onStart() {
324a7596147b43940cad3f76c53ed154ef088b9269bJim Miller       publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
325a7596147b43940cad3f76c53ed154ef088b9269bJim Miller       nativeOpenHal();
326a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
327a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
328a7596147b43940cad3f76c53ed154ef088b9269bJim Miller}
329