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.IBinder;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.util.Slog;
24 
25 /**
26  * An input channel specifies the file descriptors used to send input events to
27  * a window in another process.  It is Parcelable so that it can be sent
28  * to the process that is to receive events.  Only one thread should be reading
29  * from an InputChannel at a time.
30  * @hide
31  */
32 public final class InputChannel implements Parcelable {
33     private static final String TAG = "InputChannel";
34 
35     private static final boolean DEBUG = false;
36 
37     @UnsupportedAppUsage
38     public static final @android.annotation.NonNull Parcelable.Creator<InputChannel> CREATOR
39             = new Parcelable.Creator<InputChannel>() {
40         public InputChannel createFromParcel(Parcel source) {
41             InputChannel result = new InputChannel();
42             result.readFromParcel(source);
43             return result;
44         }
45 
46         public InputChannel[] newArray(int size) {
47             return new InputChannel[size];
48         }
49     };
50 
51     @SuppressWarnings("unused")
52     @UnsupportedAppUsage
53     private long mPtr; // used by native code
54 
nativeOpenInputChannelPair(String name)55     private static native InputChannel[] nativeOpenInputChannelPair(String name);
56 
nativeDispose(boolean finalized)57     private native void nativeDispose(boolean finalized);
nativeTransferTo(InputChannel other)58     private native void nativeTransferTo(InputChannel other);
nativeReadFromParcel(Parcel parcel)59     private native void nativeReadFromParcel(Parcel parcel);
nativeWriteToParcel(Parcel parcel)60     private native void nativeWriteToParcel(Parcel parcel);
nativeDup(InputChannel target)61     private native void nativeDup(InputChannel target);
nativeGetToken()62     private native IBinder nativeGetToken();
nativeSetToken(IBinder token)63     private native void nativeSetToken(IBinder token);
64 
nativeGetName()65     private native String nativeGetName();
66 
67     /**
68      * Creates an uninitialized input channel.
69      * It can be initialized by reading from a Parcel or by transferring the state of
70      * another input channel into this one.
71      */
72     @UnsupportedAppUsage
InputChannel()73     public InputChannel() {
74     }
75 
76     @Override
finalize()77     protected void finalize() throws Throwable {
78         try {
79             nativeDispose(true);
80         } finally {
81             super.finalize();
82         }
83     }
84 
85     /**
86      * Creates a new input channel pair.  One channel should be provided to the input
87      * dispatcher and the other to the application's input queue.
88      * @param name The descriptive (non-unique) name of the channel pair.
89      * @return A pair of input channels.  The first channel is designated as the
90      * server channel and should be used to publish input events.  The second channel
91      * is designated as the client channel and should be used to consume input events.
92      */
openInputChannelPair(String name)93     public static InputChannel[] openInputChannelPair(String name) {
94         if (name == null) {
95             throw new IllegalArgumentException("name must not be null");
96         }
97 
98         if (DEBUG) {
99             Slog.d(TAG, "Opening input channel pair '" + name + "'");
100         }
101         return nativeOpenInputChannelPair(name);
102     }
103 
104     /**
105      * Gets the name of the input channel.
106      * @return The input channel name.
107      */
getName()108     public String getName() {
109         String name = nativeGetName();
110         return name != null ? name : "uninitialized";
111     }
112 
113     /**
114      * Disposes the input channel.
115      * Explicitly releases the reference this object is holding on the input channel.
116      * When all references are released, the input channel will be closed.
117      */
dispose()118     public void dispose() {
119         nativeDispose(false);
120     }
121 
122     /**
123      * Transfers ownership of the internal state of the input channel to another
124      * instance and invalidates this instance.  This is used to pass an input channel
125      * as an out parameter in a binder call.
126      * @param other The other input channel instance.
127      */
transferTo(InputChannel outParameter)128     public void transferTo(InputChannel outParameter) {
129         if (outParameter == null) {
130             throw new IllegalArgumentException("outParameter must not be null");
131         }
132 
133         nativeTransferTo(outParameter);
134     }
135 
136     /**
137      * Duplicates the input channel.
138      */
dup()139     public InputChannel dup() {
140         InputChannel target = new InputChannel();
141         nativeDup(target);
142         return target;
143     }
144 
145     @Override
describeContents()146     public int describeContents() {
147         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
148     }
149 
readFromParcel(Parcel in)150     public void readFromParcel(Parcel in) {
151         if (in == null) {
152             throw new IllegalArgumentException("in must not be null");
153         }
154 
155         nativeReadFromParcel(in);
156     }
157 
158     @Override
writeToParcel(Parcel out, int flags)159     public void writeToParcel(Parcel out, int flags) {
160         if (out == null) {
161             throw new IllegalArgumentException("out must not be null");
162         }
163 
164         nativeWriteToParcel(out);
165 
166         if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
167             dispose();
168         }
169     }
170 
171     @Override
toString()172     public String toString() {
173         return getName();
174     }
175 
getToken()176     public IBinder getToken() {
177         return nativeGetToken();
178     }
179 
setToken(IBinder token)180     public void setToken(IBinder token) {
181         nativeSetToken(token);
182     }
183 }
184