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