127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver/*
227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * Copyright (C) 2017 The Android Open Source Project
327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver *
427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * Licensed under the Apache License, Version 2.0 (the "License");
527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * you may not use this file except in compliance with the License.
627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * You may obtain a copy of the License at
727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver *
827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver *      http://www.apache.org/licenses/LICENSE-2.0
927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver *
1027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * Unless required by applicable law or agreed to in writing, software
1127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * distributed under the License is distributed on an "AS IS" BASIS,
1227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * See the License for the specific language governing permissions and
1427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * limitations under the License.
1527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver */
1627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
1727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverpackage com.android.server.accessibility;
1827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
1927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.accessibilityservice.FingerprintGestureController;
2027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.hardware.fingerprint.IFingerprintClientActiveCallback;
2127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.hardware.fingerprint.IFingerprintService;
2227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.os.Binder;
2327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.os.Handler;
2427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.os.Message;
2527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.os.RemoteException;
2627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.util.Slog;
2727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.view.KeyEvent;
2827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
2927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport java.util.ArrayList;
3027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport java.util.List;
3127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
3227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver/**
3327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver * Encapsulate fingerprint gesture logic
3427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver */
3527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverpublic class FingerprintGestureDispatcher extends IFingerprintClientActiveCallback.Stub
3627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        implements Handler.Callback{
3727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private static final int MSG_REGISTER = 1;
3827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private static final int MSG_UNREGISTER = 2;
3927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private static final String LOG_TAG = "FingerprintGestureDispatcher";
4027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
4127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private final List<FingerprintGestureClient> mCapturingClients = new ArrayList<>(0);
4227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private final Object mLock;
4327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private final IFingerprintService mFingerprintService;
4427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private final Handler mHandler;
4527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
4627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    // This field is ground truth for whether or not we are registered. Only write to it in handler.
4727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private boolean mRegisteredReadOnlyExceptInHandler;
4827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
4927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    /**
5027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param fingerprintService The system's fingerprint service
5127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param lock A lock to use when managing internal state
5227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     */
5327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public FingerprintGestureDispatcher(IFingerprintService fingerprintService, Object lock) {
5427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        mFingerprintService = fingerprintService;
5527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        mLock = lock;
5627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        mHandler = new Handler(this);
5727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
5827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
5927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    /**
6027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param fingerprintService The system's fingerprint service
6127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param lock A lock to use when managing internal state
6227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param handler A handler to use internally. Used for testing.
6327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     */
6427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public FingerprintGestureDispatcher(IFingerprintService fingerprintService, Object lock,
6527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            Handler handler) {
6627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        mFingerprintService = fingerprintService;
6727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        mLock = lock;
6827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        mHandler = handler;
6927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
7027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
7127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    /**
7227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * Update the list of clients that are interested in fingerprint gestures.
7327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     *
7427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param clientList The list of potential clients.
7527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     */
7627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public void updateClientList(List<? extends FingerprintGestureClient> clientList) {
7727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        synchronized (mLock) {
7827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            mCapturingClients.clear();
7927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            for (int i = 0; i < clientList.size(); i++) {
8027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                FingerprintGestureClient client = clientList.get(i);
8127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                if (client.isCapturingFingerprintGestures()) {
8227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    mCapturingClients.add(client);
8327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                }
8427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
8527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            if (mCapturingClients.isEmpty()) {
8627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                if (mRegisteredReadOnlyExceptInHandler) {
8727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    mHandler.obtainMessage(MSG_UNREGISTER).sendToTarget();
8827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                }
8927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            } else {
9027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                if(!mRegisteredReadOnlyExceptInHandler) {
9127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    mHandler.obtainMessage(MSG_REGISTER).sendToTarget();
9227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                }
9327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
9427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
9527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
9627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
9727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    @Override
9827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public void onClientActiveChanged(boolean nonGestureFingerprintClientActive) {
9927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        synchronized (mLock) {
10027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            for (int i = 0; i < mCapturingClients.size(); i++) {
10127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                mCapturingClients.get(i).onFingerprintGestureDetectionActiveChanged(
10227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                        !nonGestureFingerprintClientActive);
10327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
10427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
10527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
10627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
10727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public boolean isFingerprintGestureDetectionAvailable() {
10827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        long identity = Binder.clearCallingIdentity();
10927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        try {
11027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            return !mFingerprintService.isClientActive();
11127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        } catch (RemoteException re) {
11227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            return false;
11327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        } finally {
11427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            Binder.restoreCallingIdentity(identity);
11527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
11627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
11727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
11827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    /**
11927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * Called when the fingerprint sensor detects a gesture
12027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     *
12127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @param fingerprintKeyCode
12227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     * @return {@code true} if the gesture is consumed. {@code false} otherwise.
12327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver     */
12427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public boolean onFingerprintGesture(int fingerprintKeyCode) {
12527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        int idForFingerprintGestureManager;
12627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
12727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        final List<FingerprintGestureClient> clientList;
12827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        synchronized (mLock) {
12927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            if (mCapturingClients.isEmpty()) {
13027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                return false;
13127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
13227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            switch (fingerprintKeyCode) {
13327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
13427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    idForFingerprintGestureManager =
13527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_UP;
13627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    break;
13727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
13827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    idForFingerprintGestureManager =
13927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN;
14027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    break;
14127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT:
14227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    idForFingerprintGestureManager =
14327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_RIGHT;
14427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    break;
14527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
14627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    idForFingerprintGestureManager =
14727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                            FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_LEFT;
14827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    break;
14927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                default:
15027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                    return false;
15127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
15227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            clientList = new ArrayList<>(mCapturingClients);
15327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
15427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        for (int i = 0; i < clientList.size(); i++) {
15527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            clientList.get(i).onFingerprintGesture(idForFingerprintGestureManager);
15627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
15727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        return true;
15827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
15927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
16027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    @Override
16127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public boolean handleMessage(Message message) {
16227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        if (message.what == MSG_REGISTER) {
16327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            long identity = Binder.clearCallingIdentity();
16427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            try {
16527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                mFingerprintService.addClientActiveCallback(this);
16627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                mRegisteredReadOnlyExceptInHandler = true;
16727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            } catch (RemoteException re) {
16827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                Slog.e(LOG_TAG, "Failed to register for fingerprint activity callbacks");
16927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            } finally {
17027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                Binder.restoreCallingIdentity(identity);
17127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
17227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            return false;
17327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        } else if (message.what == MSG_UNREGISTER) {
17427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            long identity = Binder.clearCallingIdentity();
17527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            try {
17627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                mFingerprintService.removeClientActiveCallback(this);
17727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            } catch (RemoteException re) {
17827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                Slog.e(LOG_TAG, "Failed to unregister for fingerprint activity callbacks");
17927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            } finally {
18027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                Binder.restoreCallingIdentity(identity);
18127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
18227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            mRegisteredReadOnlyExceptInHandler = false;
18327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        } else {
18427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            Slog.e(LOG_TAG, "Unknown message: " + message.what);
18527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            return false;
18627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
18727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        return true;
18827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
18927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
19027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    // Interface for potential clients.
19127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    public interface FingerprintGestureClient {
19227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        /**
19327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         * @return {@code true} if the client is capturing fingerprint gestures
19427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         */
19527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        boolean isCapturingFingerprintGestures();
19627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
19727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        /**
19827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         * Callback when gesture detection becomes active or inactive.
19927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         *
20027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         * @param active {@code true} when detection is active
20127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         */
20227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        void onFingerprintGestureDetectionActiveChanged(boolean active);
20327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
20427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        /**
20527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         * Callback when gesture is detected
20627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         *
20727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         * @param gesture The identifier for the gesture. For example,
20827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         * {@link FingerprintGestureController#FINGERPRINT_GESTURE_SWIPE_LEFT}
20927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver         */
21027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        void onFingerprintGesture(int gesture);
21127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
21227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver}
213