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.ActivityManager; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.ServiceConnection; 24 import android.os.IBinder; 25 import android.os.ParcelFileDescriptor; 26 import android.os.RemoteException; 27 import android.os.SystemClock; 28 import android.test.AndroidTestCase; 29 30 import com.google.common.util.concurrent.AbstractFuture; 31 32 import junit.framework.ComparisonFailure; 33 34 import java.util.concurrent.ExecutionException; 35 import java.util.concurrent.TimeUnit; 36 import java.util.concurrent.TimeoutException; 37 38 /** 39 * Test various cross-process {@link ParcelFileDescriptor} interactions. 40 */ 41 public class ParcelFileDescriptorProcessTest extends AndroidTestCase { 42 43 private Intent redIntent; 44 private Intent blueIntent; 45 private PeerConnection redConn; 46 private PeerConnection blueConn; 47 private IParcelFileDescriptorPeer red; 48 private IParcelFileDescriptorPeer blue; 49 50 public static class PeerConnection extends AbstractFuture<IParcelFileDescriptorPeer> 51 implements ServiceConnection { 52 @Override 53 public void onServiceConnected(ComponentName name, IBinder service) { 54 set(IParcelFileDescriptorPeer.Stub.asInterface(service)); 55 } 56 57 @Override 58 public void onServiceDisconnected(ComponentName name) { 59 } 60 61 @Override 62 public IParcelFileDescriptorPeer get() throws InterruptedException, ExecutionException { 63 try { 64 return get(5, TimeUnit.SECONDS); 65 } catch (TimeoutException e) { 66 throw new RuntimeException(e); 67 } 68 } 69 } 70 71 private static void assertContains(String expected, String actual) { 72 if (actual.contains(expected)) return; 73 throw new ComparisonFailure("", expected, actual); 74 } 75 76 private static void crash(IParcelFileDescriptorPeer peer) { 77 try { 78 peer.crash(); 79 } catch (RemoteException e) { 80 } 81 SystemClock.sleep(500); 82 } 83 84 @Override 85 protected void setUp() throws Exception { 86 super.setUp(); 87 final Context context = getContext(); 88 89 // Bring up both remote processes and wire them to each other 90 redIntent = new Intent(); 91 redIntent.setComponent(new ComponentName( 92 "android.os.cts", "android.os.cts.ParcelFileDescriptorPeer$Red")); 93 blueIntent = new Intent(); 94 blueIntent.setComponent(new ComponentName( 95 "android.os.cts", "android.os.cts.ParcelFileDescriptorPeer$Blue")); 96 redConn = new PeerConnection(); 97 blueConn = new PeerConnection(); 98 context.startService(redIntent); 99 context.startService(blueIntent); 100 getContext().bindService(redIntent, redConn, 0); 101 getContext().bindService(blueIntent, blueConn, 0); 102 red = redConn.get(); 103 blue = blueConn.get(); 104 red.setPeer(blue); 105 blue.setPeer(red); 106 } 107 108 @Override 109 protected void tearDown() throws Exception { 110 super.tearDown(); 111 112 final Context context = getContext(); 113 context.unbindService(redConn); 114 context.unbindService(blueConn); 115 context.stopService(redIntent); 116 context.stopService(blueIntent); 117 118 final ActivityManager am = (ActivityManager) mContext.getSystemService( 119 Context.ACTIVITY_SERVICE); 120 am.killBackgroundProcesses(context.getPackageName()); 121 } 122 123 public void testPullPipeNormal() throws Exception { 124 // red <-- blue 125 red.setupReadPipe(); 126 blue.doGet(); 127 128 blue.write(1); 129 assertEquals(1, red.read()); 130 131 blue.close(); 132 assertEquals(-1, red.read()); 133 assertEquals(null, red.checkError()); 134 } 135 136 public void testPushPipeNormal() throws Exception { 137 // red --> blue 138 red.setupWritePipe(); 139 red.doSet(); 140 141 red.write(2); 142 assertEquals(2, blue.read()); 143 144 red.close(); 145 assertEquals(-1, blue.read()); 146 assertEquals(null, blue.checkError()); 147 } 148 149 public void testPipeWriterError() throws Exception { 150 // red --> blue 151 red.setupWritePipe(); 152 red.doSet(); 153 154 red.write(3); 155 red.closeWithError("OMG MUFFINS"); 156 157 // even though closed we should still drain pipe 158 assertEquals(3, blue.read()); 159 assertEquals(-1, blue.read()); 160 assertContains("OMG MUFFINS", blue.checkError()); 161 } 162 163 public void testPipeWriterCrash() throws Exception { 164 // red --> blue 165 red.setupWritePipe(); 166 blue.doGet(); 167 168 red.write(4); 169 crash(red); 170 171 // even though dead we should still drain pipe 172 assertEquals(4, blue.read()); 173 assertEquals(-1, blue.read()); 174 assertContains("Remote side is dead", blue.checkError()); 175 } 176 177 public void testSocketCrash() throws Exception { 178 // red <--> blue 179 red.setupSocket(); 180 blue.doGet(); 181 182 red.write(5); 183 blue.write(6); 184 185 assertEquals(5, blue.read()); 186 crash(blue); 187 assertEquals(6, red.read()); 188 assertEquals(-1, red.read()); 189 assertContains("Remote side is dead", red.checkError()); 190 } 191 192 public void testFileNormal() throws Exception { 193 red.setupFile(); 194 blue.doGet(); 195 196 blue.write(7); 197 blue.close(); 198 199 // make sure red heard us finish 200 assertEquals("null", red.checkListener()); 201 } 202 203 public void testFileError() throws Exception { 204 red.setupFile(); 205 blue.doGet(); 206 207 blue.write(8); 208 blue.closeWithError("OMG BANANAS"); 209 210 // make sure red heard us error 211 assertContains("OMG BANANAS", red.checkListener()); 212 } 213 214 public void testFileCrash() throws Exception { 215 red.setupFile(); 216 blue.doGet(); 217 218 blue.write(9); 219 crash(blue); 220 221 // make sure red heard us die 222 assertContains("Remote side is dead", red.checkListener()); 223 } 224 225 public void testFileDetach() throws Exception { 226 red.setupFile(); 227 blue.doGet(); 228 blue.detachFd(); 229 230 // make sure red heard us detach 231 assertContains("DETACHED", red.checkListener()); 232 } 233 234 public void testFileLeak() throws Exception { 235 red.setupFile(); 236 blue.doGet(); 237 blue.leak(); 238 239 // make sure red heard us get leaked 240 assertContains("leaked", red.checkListener()); 241 } 242 243 public void testSocketErrorAfterClose() throws Exception { 244 // red <--> blue 245 red.setupSocket(); 246 blue.doGet(); 247 248 // both sides throw their hands in the air 249 blue.closeWithError("BLUE RAWR"); 250 red.closeWithError("RED RAWR"); 251 252 // red noticed the blue error, but after that the comm pipe was dead so 253 // blue had no way of seeing the red error. 254 assertContains("BLUE RAWR", red.checkError()); 255 assertNull(blue.checkError()); 256 } 257 258 public void testSocketDeathBeforeClose() throws Exception { 259 // red <--> blue 260 red.setupSocket(); 261 blue.doGet(); 262 263 crash(blue); 264 assertContains("Remote side is dead", red.checkError()); 265 red.close(); 266 } 267 268 public void testSocketDeathAfterClose() throws Exception { 269 // red <--> blue 270 red.setupSocket(); 271 blue.doGet(); 272 273 crash(blue); 274 red.close(); 275 assertContains("Remote side is dead", red.checkError()); 276 } 277 278 public void testSocketMultipleCheck() throws Exception { 279 // red <--> blue 280 red.setupSocket(); 281 blue.doGet(); 282 283 // allow checking before closed 284 assertNull(blue.checkError()); 285 assertNull(blue.checkError()); 286 assertNull(blue.checkError()); 287 288 // and verify we actually see it 289 red.closeWithError("RAWR RED"); 290 assertContains("RAWR RED", blue.checkError()); 291 } 292 293 public void testSocketGiantError() throws Exception { 294 // red <--> blue 295 red.setupSocket(); 296 blue.doGet(); 297 298 final StringBuilder builder = new StringBuilder(); 299 for (int i = 0; i < 1024; i++) { 300 builder.append(i).append(","); 301 } 302 final String msg = builder.toString(); 303 red.closeWithError(msg); 304 305 // we should at least see the first 512 chars 306 assertContains(msg.substring(0, 512), blue.checkError()); 307 } 308 } 309