• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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.os.cts;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 import android.os.Handler;
22 import android.os.IBinder;
23 import android.os.Looper;
24 import android.os.ParcelFileDescriptor;
25 import android.os.Process;
26 import android.os.ParcelFileDescriptor.OnCloseListener;
27 import android.os.ParcelFileDescriptor.FileDescriptorDetachedException;
28 import android.os.RemoteException;
29 import android.os.SystemClock;
30 
31 import com.google.common.util.concurrent.AbstractFuture;
32 
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.TimeoutException;
40 
41 /**
42  * Sits around in a remote process doing whatever the CTS test says.
43  */
44 public class ParcelFileDescriptorPeer extends IParcelFileDescriptorPeer.Stub {
45     private IParcelFileDescriptorPeer mPeer;
46 
47     private ParcelFileDescriptor mLocal;
48     private ParcelFileDescriptor mRemote;
49 
50     private FutureCloseListener mListener;
51 
52     @Override
setPeer(IParcelFileDescriptorPeer peer)53     public void setPeer(IParcelFileDescriptorPeer peer) throws RemoteException {
54         mPeer = peer;
55     }
56 
57     @Override
setupReadPipe()58     public void setupReadPipe() throws RemoteException {
59         try {
60             ParcelFileDescriptor[] pfds = ParcelFileDescriptor.createReliablePipe();
61             mLocal = pfds[0];
62             mRemote = pfds[1];
63         } catch (IOException e) {
64             throw new RuntimeException(e);
65         }
66     }
67 
68     @Override
setupWritePipe()69     public void setupWritePipe() throws RemoteException {
70         try {
71             ParcelFileDescriptor[] pfds = ParcelFileDescriptor.createReliablePipe();
72             mLocal = pfds[1];
73             mRemote = pfds[0];
74         } catch (IOException e) {
75             throw new RuntimeException(e);
76         }
77     }
78 
79     @Override
setupSocket()80     public void setupSocket() throws RemoteException {
81         try {
82             ParcelFileDescriptor[] pfds = ParcelFileDescriptor.createReliableSocketPair();
83             mLocal = pfds[0];
84             mRemote = pfds[1];
85         } catch (IOException e) {
86             throw new RuntimeException(e);
87         }
88     }
89 
90     @Override
setupFile()91     public void setupFile() throws RemoteException {
92         final Handler handler = new Handler(Looper.getMainLooper());
93         mListener = new FutureCloseListener();
94         try {
95             mLocal = null;
96             mRemote = ParcelFileDescriptor.open(File.createTempFile("pfd", "tmp"),
97                     ParcelFileDescriptor.MODE_READ_WRITE, handler, mListener);
98         } catch (IOException e) {
99             throw new RuntimeException(e);
100         }
101     }
102 
103     @Override
get()104     public ParcelFileDescriptor get() throws RemoteException {
105         return mRemote;
106     }
107 
108     @Override
set(ParcelFileDescriptor pfd)109     public void set(ParcelFileDescriptor pfd) throws RemoteException {
110         mLocal = pfd;
111     }
112 
113     @Override
doGet()114     public void doGet() throws RemoteException {
115         mLocal = mPeer.get();
116     }
117 
118     @Override
doSet()119     public void doSet() throws RemoteException {
120         mPeer.set(mRemote);
121     }
122 
123     @Override
read()124     public int read() throws RemoteException {
125         try {
126             return new FileInputStream(mLocal.getFileDescriptor()).read();
127         } catch (IOException e) {
128             throw new RuntimeException(e);
129         }
130     }
131 
132     @Override
write(int oneByte)133     public void write(int oneByte) throws RemoteException {
134         try {
135             new FileOutputStream(mLocal.getFileDescriptor()).write(oneByte);
136         } catch (IOException e) {
137             throw new RuntimeException(e);
138         }
139     }
140 
141     @Override
close()142     public void close() throws RemoteException {
143         try {
144             mLocal.close();
145         } catch (IOException e) {
146             throw new RuntimeException(e);
147         }
148     }
149 
150     @Override
closeWithError(String msg)151     public void closeWithError(String msg) throws RemoteException {
152         try {
153             mLocal.closeWithError(msg);
154         } catch (IOException e) {
155             throw new RuntimeException(e);
156         }
157     }
158 
159     @Override
detachFd()160     public void detachFd() throws RemoteException {
161         mLocal.detachFd();
162     }
163 
164     @Override
leak()165     public void leak() throws RemoteException {
166         mLocal = null;
167 
168         // Try really hard to finalize
169         for (int i = 0; i < 5; i++) {
170             System.gc();
171             System.runFinalization();
172             SystemClock.sleep(100);
173         }
174     }
175 
176     @Override
crash()177     public void crash() throws RemoteException {
178         Process.killProcess(Process.myPid());
179         System.exit(42);
180     }
181 
182     @Override
checkError()183     public String checkError() throws RemoteException {
184         try {
185             mLocal.checkError();
186             return null;
187         } catch (IOException e) {
188             return e.getMessage();
189         }
190     }
191 
192     @Override
checkListener()193     public String checkListener() throws RemoteException {
194         try {
195             return String.valueOf(mListener.get());
196         } catch (InterruptedException e1) {
197             return null;
198         } catch (ExecutionException e1) {
199             return null;
200         }
201     }
202 
203     public static class FutureCloseListener extends AbstractFuture<IOException>
204             implements OnCloseListener {
205         @Override
onClose(IOException e)206         public void onClose(IOException e) {
207             if (e instanceof FileDescriptorDetachedException) {
208                 set(new IOException("DETACHED"));
209             } else {
210                 set(e);
211             }
212         }
213 
214         @Override
get()215         public IOException get() throws InterruptedException, ExecutionException {
216             try {
217                 return get(5, TimeUnit.SECONDS);
218             } catch (TimeoutException e) {
219                 throw new RuntimeException(e);
220             }
221         }
222     }
223 
224     public static class Red extends Service {
225         @Override
onBind(Intent intent)226         public IBinder onBind(Intent intent) {
227             return new ParcelFileDescriptorPeer();
228         }
229     }
230 
231     public static class Blue extends Service {
232         @Override
onBind(Intent intent)233         public IBinder onBind(Intent intent) {
234             return new ParcelFileDescriptorPeer();
235         }
236     }
237 }
238