1 /*
2  * Copyright (C) 2021 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.hardware.input;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.SystemClock;
25 import android.view.InputEvent;
26 import android.view.MotionEvent;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 
31 /**
32  * An event describing a mouse button click interaction originating from a remote device.
33  *
34  * @hide
35  */
36 @SystemApi
37 public final class VirtualMouseButtonEvent implements Parcelable {
38 
39     /** @hide */
40     public static final int ACTION_UNKNOWN = -1;
41     /** Action indicating the mouse button has been pressed. */
42     public static final int ACTION_BUTTON_PRESS = MotionEvent.ACTION_BUTTON_PRESS;
43     /** Action indicating the mouse button has been released. */
44     public static final int ACTION_BUTTON_RELEASE = MotionEvent.ACTION_BUTTON_RELEASE;
45     /** @hide */
46     @IntDef(prefix = {"ACTION_"}, value = {
47             ACTION_UNKNOWN,
48             ACTION_BUTTON_PRESS,
49             ACTION_BUTTON_RELEASE,
50     })
51     @Retention(RetentionPolicy.SOURCE)
52     public @interface Action {}
53 
54     /** @hide */
55     public static final int BUTTON_UNKNOWN = -1;
56     /** Action indicating the mouse button involved in this event is in the left position. */
57     public static final int BUTTON_PRIMARY = MotionEvent.BUTTON_PRIMARY;
58     /** Action indicating the mouse button involved in this event is in the middle position. */
59     public static final int BUTTON_TERTIARY = MotionEvent.BUTTON_TERTIARY;
60     /** Action indicating the mouse button involved in this event is in the right position. */
61     public static final int BUTTON_SECONDARY = MotionEvent.BUTTON_SECONDARY;
62     /**
63      * Action indicating the mouse button involved in this event is intended to go back to the
64      * previous.
65      */
66     public static final int BUTTON_BACK = MotionEvent.BUTTON_BACK;
67     /**
68      * Action indicating the mouse button involved in this event is intended to move forward to the
69      * next.
70      */
71     public static final int BUTTON_FORWARD = MotionEvent.BUTTON_FORWARD;
72     /** @hide */
73     @IntDef(prefix = {"BUTTON_"}, value = {
74             BUTTON_UNKNOWN,
75             BUTTON_PRIMARY,
76             BUTTON_TERTIARY,
77             BUTTON_SECONDARY,
78             BUTTON_BACK,
79             BUTTON_FORWARD,
80     })
81     @Retention(RetentionPolicy.SOURCE)
82     public @interface Button {}
83 
84     private final @Action int mAction;
85     private final @Button int mButtonCode;
86     private final long mEventTimeNanos;
87 
VirtualMouseButtonEvent(@ction int action, @Button int buttonCode, long eventTimeNanos)88     private VirtualMouseButtonEvent(@Action int action, @Button int buttonCode,
89             long eventTimeNanos) {
90         mAction = action;
91         mButtonCode = buttonCode;
92         mEventTimeNanos = eventTimeNanos;
93     }
94 
VirtualMouseButtonEvent(@onNull Parcel parcel)95     private VirtualMouseButtonEvent(@NonNull Parcel parcel) {
96         mAction = parcel.readInt();
97         mButtonCode = parcel.readInt();
98         mEventTimeNanos = parcel.readLong();
99     }
100 
101     @Override
writeToParcel(@onNull Parcel parcel, int parcelableFlags)102     public void writeToParcel(@NonNull Parcel parcel, int parcelableFlags) {
103         parcel.writeInt(mAction);
104         parcel.writeInt(mButtonCode);
105         parcel.writeLong(mEventTimeNanos);
106     }
107 
108     @Override
describeContents()109     public int describeContents() {
110         return 0;
111     }
112 
113     /**
114      * Returns the button code associated with this event.
115      */
getButtonCode()116     public @Button int getButtonCode() {
117         return mButtonCode;
118     }
119 
120     /**
121      * Returns the action associated with this event.
122      */
getAction()123     public @Action int getAction() {
124         return mAction;
125     }
126 
127     /**
128      * Returns the time this event occurred, in the {@link SystemClock#uptimeMillis()} time base but
129      * with nanosecond (instead of millisecond) precision.
130      *
131      * @see InputEvent#getEventTime()
132      */
getEventTimeNanos()133     public long getEventTimeNanos() {
134         return mEventTimeNanos;
135     }
136 
137     /**
138      * Builder for {@link VirtualMouseButtonEvent}.
139      */
140     public static final class Builder {
141 
142         private @Action int mAction = ACTION_UNKNOWN;
143         private @Button int mButtonCode = -1;
144         private long mEventTimeNanos = 0L;
145 
146         /**
147          * Creates a {@link VirtualMouseButtonEvent} object with the current builder configuration.
148          */
build()149         public @NonNull VirtualMouseButtonEvent build() {
150             if (mAction == ACTION_UNKNOWN || mButtonCode == -1) {
151                 throw new IllegalArgumentException(
152                         "Cannot build virtual mouse button event with unset fields");
153             }
154             return new VirtualMouseButtonEvent(mAction, mButtonCode, mEventTimeNanos);
155         }
156 
157         /**
158          * Sets the button code of the event.
159          *
160          * @return this builder, to allow for chaining of calls
161          */
setButtonCode(int buttonCode)162         public @NonNull Builder setButtonCode(int buttonCode) {
163             if (buttonCode != BUTTON_PRIMARY
164                     && buttonCode != BUTTON_TERTIARY
165                     && buttonCode != BUTTON_SECONDARY
166                     && buttonCode != BUTTON_BACK
167                     && buttonCode != BUTTON_FORWARD) {
168                 throw new IllegalArgumentException("Unsupported mouse button code");
169             }
170             mButtonCode = buttonCode;
171             return this;
172         }
173 
174         /**
175          * Sets the action of the event.
176          *
177          * @return this builder, to allow for chaining of calls
178          */
setAction(@ction int action)179         public @NonNull Builder setAction(@Action int action) {
180             if (action != ACTION_BUTTON_PRESS && action != ACTION_BUTTON_RELEASE) {
181                 throw new IllegalArgumentException("Unsupported mouse button action type");
182             }
183             mAction = action;
184             return this;
185         }
186 
187         /**
188          * Sets the time (in nanoseconds) when this specific event was generated. This may be
189          * obtained from {@link SystemClock#uptimeMillis()} (with nanosecond precision instead of
190          * millisecond), but can be different depending on the use case.
191          * This field is optional and can be omitted.
192          *
193          * @return this builder, to allow for chaining of calls
194          * @see InputEvent#getEventTime()
195          */
setEventTimeNanos(long eventTimeNanos)196         public @NonNull Builder setEventTimeNanos(long eventTimeNanos) {
197             if (eventTimeNanos < 0L) {
198                 throw new IllegalArgumentException("Event time cannot be negative");
199             }
200             this.mEventTimeNanos = eventTimeNanos;
201             return this;
202         }
203     }
204 
205     public static final @NonNull Parcelable.Creator<VirtualMouseButtonEvent> CREATOR =
206             new Parcelable.Creator<VirtualMouseButtonEvent>() {
207                 public VirtualMouseButtonEvent createFromParcel(Parcel source) {
208                     return new VirtualMouseButtonEvent(source);
209                 }
210 
211                 public VirtualMouseButtonEvent[] newArray(int size) {
212                     return new VirtualMouseButtonEvent[size];
213                 }
214             };
215 }
216