• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.os.Build;
21 import android.os.Looper;
22 import android.os.MessageQueue;
23 import android.util.Log;
24 
25 import dalvik.system.CloseGuard;
26 
27 import java.lang.ref.WeakReference;
28 
29 /**
30  * Provides a low-level mechanism for an application to send input events.
31  * @hide
32  */
33 public abstract class InputEventSender {
34     private static final String TAG = "InputEventSender";
35 
36     private final CloseGuard mCloseGuard = CloseGuard.get();
37 
38     private long mSenderPtr;
39 
40     // We keep references to the input channel and message queue objects here so that
41     // they are not GC'd while the native peer of the receiver is using them.
42     private InputChannel mInputChannel;
43     private MessageQueue mMessageQueue;
44 
nativeInit(WeakReference<InputEventSender> sender, InputChannel inputChannel, MessageQueue messageQueue)45     private static native long nativeInit(WeakReference<InputEventSender> sender,
46             InputChannel inputChannel, MessageQueue messageQueue);
nativeDispose(long senderPtr)47     private static native void nativeDispose(long senderPtr);
nativeSendKeyEvent(long senderPtr, int seq, KeyEvent event)48     private static native boolean nativeSendKeyEvent(long senderPtr, int seq, KeyEvent event);
nativeSendMotionEvent(long senderPtr, int seq, MotionEvent event)49     private static native boolean nativeSendMotionEvent(long senderPtr, int seq, MotionEvent event);
50 
51     /**
52      * Creates an input event sender bound to the specified input channel.
53      *
54      * @param inputChannel The input channel.
55      * @param looper The looper to use when invoking callbacks.
56      */
InputEventSender(InputChannel inputChannel, Looper looper)57     public InputEventSender(InputChannel inputChannel, Looper looper) {
58         if (inputChannel == null) {
59             throw new IllegalArgumentException("inputChannel must not be null");
60         }
61         if (looper == null) {
62             throw new IllegalArgumentException("looper must not be null");
63         }
64 
65         mInputChannel = inputChannel;
66         mMessageQueue = looper.getQueue();
67         mSenderPtr = nativeInit(new WeakReference<InputEventSender>(this),
68                 inputChannel, mMessageQueue);
69 
70         mCloseGuard.open("dispose");
71     }
72 
73     @Override
finalize()74     protected void finalize() throws Throwable {
75         try {
76             dispose(true);
77         } finally {
78             super.finalize();
79         }
80     }
81 
82     /**
83      * Disposes the receiver.
84      */
dispose()85     public void dispose() {
86         dispose(false);
87     }
88 
dispose(boolean finalized)89     private void dispose(boolean finalized) {
90         if (mCloseGuard != null) {
91             if (finalized) {
92                 mCloseGuard.warnIfOpen();
93             }
94             mCloseGuard.close();
95         }
96 
97         if (mSenderPtr != 0) {
98             nativeDispose(mSenderPtr);
99             mSenderPtr = 0;
100         }
101         mInputChannel = null;
102         mMessageQueue = null;
103     }
104 
105     /**
106      * Called when an input event is finished.
107      *
108      * @param seq The input event sequence number.
109      * @param handled True if the input event was handled.
110      */
onInputEventFinished(int seq, boolean handled)111     public void onInputEventFinished(int seq, boolean handled) {
112     }
113 
114     /**
115      * Called when timeline is sent to the publisher.
116      *
117      * @param inputEventId The id of the input event that caused the frame being reported
118      * @param gpuCompletedTime The time when the frame left the app process
119      * @param presentTime The time when the frame was presented on screen
120      */
onTimelineReported(int inputEventId, long gpuCompletedTime, long presentTime)121     public void onTimelineReported(int inputEventId, long gpuCompletedTime, long presentTime) {
122     }
123 
124     /**
125      * Sends an input event.
126      * Must be called on the same Looper thread to which the sender is attached.
127      *
128      * @param seq The input event sequence number.
129      * @param event The input event to send.
130      * @return True if the entire event was sent successfully.  May return false
131      * if the input channel buffer filled before all samples were dispatched.
132      */
sendInputEvent(int seq, InputEvent event)133     public final boolean sendInputEvent(int seq, InputEvent event) {
134         if (event == null) {
135             throw new IllegalArgumentException("event must not be null");
136         }
137         if (mSenderPtr == 0) {
138             Log.w(TAG, "Attempted to send an input event but the input event "
139                     + "sender has already been disposed.");
140             return false;
141         }
142 
143         if (event instanceof KeyEvent) {
144             return nativeSendKeyEvent(mSenderPtr, seq, (KeyEvent)event);
145         } else {
146             return nativeSendMotionEvent(mSenderPtr, seq, (MotionEvent)event);
147         }
148     }
149 
150     // Called from native code.
151     @SuppressWarnings("unused")
152     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchInputEventFinished(int seq, boolean handled)153     private void dispatchInputEventFinished(int seq, boolean handled) {
154         onInputEventFinished(seq, handled);
155     }
156 
157     // Called from native code.
158     @SuppressWarnings("unused")
dispatchTimelineReported( int inputEventId, long gpuCompletedTime, long presentTime)159     private void dispatchTimelineReported(
160             int inputEventId, long gpuCompletedTime, long presentTime) {
161         onTimelineReported(inputEventId, gpuCompletedTime, presentTime);
162     }
163 }
164