• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.IBinder;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.util.Slog;
25 
26 import libcore.util.NativeAllocationRegistry;
27 
28 /**
29  * An input channel specifies the file descriptors used to send input events to
30  * a window in another process.  It is Parcelable so that it can be sent
31  * to the process that is to receive events.  Only one thread should be reading
32  * from an InputChannel at a time.
33  * @hide
34  */
35 public final class InputChannel implements Parcelable {
36     private static final String TAG = "InputChannel";
37 
38     private static final boolean DEBUG = false;
39     private static final NativeAllocationRegistry sRegistry =
40             NativeAllocationRegistry.createMalloced(
41                     InputChannel.class.getClassLoader(),
42                     nativeGetFinalizer());
43 
44     @UnsupportedAppUsage
45     public static final @android.annotation.NonNull Parcelable.Creator<InputChannel> CREATOR
46             = new Parcelable.Creator<InputChannel>() {
47         public InputChannel createFromParcel(Parcel source) {
48             InputChannel result = new InputChannel();
49             result.readFromParcel(source);
50             return result;
51         }
52 
53         public InputChannel[] newArray(int size) {
54             return new InputChannel[size];
55         }
56     };
57 
58     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
59     private long mPtr; // used by native code
60 
nativeOpenInputChannelPair(String name)61     private static native long[] nativeOpenInputChannelPair(String name);
62 
nativeGetFinalizer()63     private static native long nativeGetFinalizer();
nativeDispose(long channel)64     private native void nativeDispose(long channel);
nativeReadFromParcel(Parcel parcel)65     private native long nativeReadFromParcel(Parcel parcel);
nativeWriteToParcel(Parcel parcel, long channel)66     private native void nativeWriteToParcel(Parcel parcel, long channel);
nativeDup(long channel)67     private native long nativeDup(long channel);
nativeGetToken(long channel)68     private native IBinder nativeGetToken(long channel);
69 
nativeGetName(long channel)70     private native String nativeGetName(long channel);
71 
72     /**
73      * Creates an uninitialized input channel.
74      * It can be initialized by reading from a Parcel or by transferring the state of
75      * another input channel into this one.
76      */
77     @UnsupportedAppUsage
InputChannel()78     public InputChannel() {
79     }
80 
81     /**
82      *  Set Native input channel object from native space.
83      *  @param nativeChannel the native channel object.
84      *
85      *  @hide
86      */
setNativeInputChannel(long nativeChannel)87     private void setNativeInputChannel(long nativeChannel) {
88         if (nativeChannel == 0) {
89             throw new IllegalArgumentException("Attempting to set native input channel to null.");
90         }
91         if (mPtr != 0) {
92             throw new IllegalArgumentException("Already has native input channel.");
93         }
94         if (DEBUG) {
95             Slog.d(TAG, "setNativeInputChannel : " +  String.format("%x", nativeChannel));
96         }
97         sRegistry.registerNativeAllocation(this, nativeChannel);
98         mPtr = nativeChannel;
99     }
100 
101     /**
102      * Creates a new input channel pair.  One channel should be provided to the input
103      * dispatcher and the other to the application's input queue.
104      * @param name The descriptive (non-unique) name of the channel pair.
105      * @return A pair of input channels.  The first channel is designated as the
106      * server channel and should be used to publish input events.  The second channel
107      * is designated as the client channel and should be used to consume input events.
108      */
openInputChannelPair(String name)109     public static InputChannel[] openInputChannelPair(String name) {
110         if (name == null) {
111             throw new IllegalArgumentException("name must not be null");
112         }
113 
114         if (DEBUG) {
115             Slog.d(TAG, "Opening input channel pair '" + name + "'");
116         }
117         InputChannel channels[] = new InputChannel[2];
118         long[] nativeChannels = nativeOpenInputChannelPair(name);
119         for (int i = 0; i< 2; i++) {
120             channels[i] = new InputChannel();
121             channels[i].setNativeInputChannel(nativeChannels[i]);
122         }
123         return channels;
124     }
125 
126     /**
127      * Gets the name of the input channel.
128      * @return The input channel name.
129      */
getName()130     public String getName() {
131         String name = nativeGetName(mPtr);
132         return name != null ? name : "uninitialized";
133     }
134 
135     /**
136      * Disposes the input channel.
137      * Explicitly releases the reference this object is holding on the input channel.
138      * When all references are released, the input channel will be closed.
139      */
dispose()140     public void dispose() {
141         nativeDispose(mPtr);
142     }
143 
144     /**
145      * Release the Java objects hold over the native InputChannel. If other references
146      * still exist in native-land, then the channel may continue to exist.
147      */
release()148     public void release() {
149     }
150 
151     /**
152      * Creates a copy of this instance to the outParameter. This is used to pass an input channel
153      * as an out parameter in a binder call.
154      * @param other The other input channel instance.
155      */
copyTo(InputChannel outParameter)156     public void copyTo(InputChannel outParameter) {
157         if (outParameter == null) {
158             throw new IllegalArgumentException("outParameter must not be null");
159         }
160         if (outParameter.mPtr != 0) {
161             throw new IllegalArgumentException("Other object already has a native input channel.");
162         }
163         outParameter.setNativeInputChannel(nativeDup(mPtr));
164     }
165 
166     /**
167      * Duplicates the input channel.
168      */
dup()169     public InputChannel dup() {
170         InputChannel target = new InputChannel();
171         target.setNativeInputChannel(nativeDup(mPtr));
172         return target;
173     }
174 
175     @Override
describeContents()176     public int describeContents() {
177         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
178     }
179 
readFromParcel(Parcel in)180     public void readFromParcel(Parcel in) {
181         if (in == null) {
182             throw new IllegalArgumentException("in must not be null");
183         }
184         long nativeIn = nativeReadFromParcel(in);
185         if (nativeIn != 0) {
186             setNativeInputChannel(nativeIn);
187         }
188     }
189 
190     @Override
writeToParcel(Parcel out, int flags)191     public void writeToParcel(Parcel out, int flags) {
192         if (out == null) {
193             throw new IllegalArgumentException("out must not be null");
194         }
195 
196         nativeWriteToParcel(out, mPtr);
197 
198         if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
199             dispose();
200         }
201     }
202 
203     @Override
toString()204     public String toString() {
205         return getName();
206     }
207 
getToken()208     public IBinder getToken() {
209         return nativeGetToken(mPtr);
210     }
211 }
212