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);
nativeRelease()58     private native void nativeRelease();
nativeTransferTo(InputChannel other)59     private native void nativeTransferTo(InputChannel other);
nativeReadFromParcel(Parcel parcel)60     private native void nativeReadFromParcel(Parcel parcel);
nativeWriteToParcel(Parcel parcel)61     private native void nativeWriteToParcel(Parcel parcel);
nativeDup(InputChannel target)62     private native void nativeDup(InputChannel target);
nativeGetToken()63     private native IBinder nativeGetToken();
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      * Release the Java objects hold over the native InputChannel. If other references
124      * still exist in native-land, then the channel may continue to exist.
125      */
release()126     public void release() {
127         nativeRelease();
128     }
129 
130     /**
131      * Transfers ownership of the internal state of the input channel to another
132      * instance and invalidates this instance.  This is used to pass an input channel
133      * as an out parameter in a binder call.
134      * @param other The other input channel instance.
135      */
transferTo(InputChannel outParameter)136     public void transferTo(InputChannel outParameter) {
137         if (outParameter == null) {
138             throw new IllegalArgumentException("outParameter must not be null");
139         }
140 
141         nativeTransferTo(outParameter);
142     }
143 
144     /**
145      * Duplicates the input channel.
146      */
dup()147     public InputChannel dup() {
148         InputChannel target = new InputChannel();
149         nativeDup(target);
150         return target;
151     }
152 
153     @Override
describeContents()154     public int describeContents() {
155         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
156     }
157 
readFromParcel(Parcel in)158     public void readFromParcel(Parcel in) {
159         if (in == null) {
160             throw new IllegalArgumentException("in must not be null");
161         }
162 
163         nativeReadFromParcel(in);
164     }
165 
166     @Override
writeToParcel(Parcel out, int flags)167     public void writeToParcel(Parcel out, int flags) {
168         if (out == null) {
169             throw new IllegalArgumentException("out must not be null");
170         }
171 
172         nativeWriteToParcel(out);
173 
174         if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
175             dispose();
176         }
177     }
178 
179     @Override
toString()180     public String toString() {
181         return getName();
182     }
183 
getToken()184     public IBinder getToken() {
185         return nativeGetToken();
186     }
187 }
188