1 /* 2 * Copyright (C) 2006 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.app.activity; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.ServiceConnection; 23 import android.os.Binder; 24 import android.os.Bundle; 25 import android.os.RemoteException; 26 import android.os.IBinder; 27 import android.os.Parcel; 28 import android.test.suitebuilder.annotation.MediumTest; 29 import android.test.suitebuilder.annotation.SmallTest; 30 import android.test.suitebuilder.annotation.Suppress; 31 import android.util.Log; 32 33 // These test binders purport to support an interface whose canonical 34 // interface name is ServiceTest.SERVICE_LOCAL 35 // Temporarily suppress, this test is causing unit test suite run to fail 36 // TODO: remove this suppress 37 @Suppress 38 public class ServiceTest extends ActivityTestsBase { 39 40 public static final String SERVICE_LOCAL = 41 "com.android.frameworks.coretests.activity.SERVICE_LOCAL"; 42 public static final String SERVICE_LOCAL_GRANTED = 43 "com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED"; 44 public static final String SERVICE_LOCAL_DENIED = 45 "com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED"; 46 47 public static final String REPORT_OBJ_NAME = "report"; 48 49 public static final int STARTED_CODE = 1; 50 public static final int DESTROYED_CODE = 2; 51 public static final int SET_REPORTER_CODE = 3; 52 public static final int UNBIND_CODE = 4; 53 public static final int REBIND_CODE = 5; 54 55 public static final int STATE_START_1 = 0; 56 public static final int STATE_START_2 = 1; 57 public static final int STATE_UNBIND = 2; 58 public static final int STATE_DESTROY = 3; 59 public static final int STATE_REBIND = 4; 60 public static final int STATE_UNBIND_ONLY = 5; 61 public int mStartState; 62 63 public IBinder mStartReceiver = new Binder() { 64 @Override 65 protected boolean onTransact(int code, Parcel data, Parcel reply, 66 int flags) throws RemoteException { 67 //Log.i("ServiceTest", "Received code " + code + " in state " + mStartState); 68 if (code == STARTED_CODE) { 69 data.enforceInterface(SERVICE_LOCAL); 70 int count = data.readInt(); 71 if (mStartState == STATE_START_1) { 72 if (count == 1) { 73 finishGood(); 74 } else { 75 finishBad("onStart() again on an object when it should have been the first time"); 76 } 77 } else if (mStartState == STATE_START_2) { 78 if (count == 2) { 79 finishGood(); 80 } else { 81 finishBad("onStart() the first time on an object when it should have been the second time"); 82 } 83 } else { 84 finishBad("onStart() was called when not expected (state="+mStartState+")"); 85 } 86 return true; 87 } else if (code == DESTROYED_CODE) { 88 data.enforceInterface(SERVICE_LOCAL); 89 if (mStartState == STATE_DESTROY) { 90 finishGood(); 91 } else { 92 finishBad("onDestroy() was called when not expected (state="+mStartState+")"); 93 } 94 return true; 95 } else if (code == UNBIND_CODE) { 96 data.enforceInterface(SERVICE_LOCAL); 97 if (mStartState == STATE_UNBIND) { 98 mStartState = STATE_DESTROY; 99 } else if (mStartState == STATE_UNBIND_ONLY) { 100 finishGood(); 101 } else { 102 finishBad("onUnbind() was called when not expected (state="+mStartState+")"); 103 } 104 return true; 105 } else if (code == REBIND_CODE) { 106 data.enforceInterface(SERVICE_LOCAL); 107 if (mStartState == STATE_REBIND) { 108 finishGood(); 109 } else { 110 finishBad("onRebind() was called when not expected (state="+mStartState+")"); 111 } 112 return true; 113 } else { 114 return super.onTransact(code, data, reply, flags); 115 } 116 } 117 }; 118 119 public class EmptyConnection implements ServiceConnection { 120 public void onServiceConnected(ComponentName name, IBinder service) { 121 } 122 123 public void onServiceDisconnected(ComponentName name) { 124 } 125 } 126 127 public class TestConnection implements ServiceConnection { 128 private final boolean mExpectDisconnect; 129 private final boolean mSetReporter; 130 private boolean mMonitor; 131 private int mCount; 132 133 public TestConnection(boolean expectDisconnect, boolean setReporter) { 134 mExpectDisconnect = expectDisconnect; 135 mSetReporter = setReporter; 136 mMonitor = !setReporter; 137 } 138 139 void setMonitor(boolean v) { 140 mMonitor = v; 141 } 142 143 public void onServiceConnected(ComponentName name, IBinder service) { 144 if (mSetReporter) { 145 Parcel data = Parcel.obtain(); 146 data.writeInterfaceToken(SERVICE_LOCAL); 147 data.writeStrongBinder(mStartReceiver); 148 try { 149 service.transact(SET_REPORTER_CODE, data, null, 0); 150 } catch (RemoteException e) { 151 finishBad("DeadObjectException when sending reporting object"); 152 } 153 data.recycle(); 154 } 155 156 if (mMonitor) { 157 mCount++; 158 if (mStartState == STATE_START_1) { 159 if (mCount == 1) { 160 finishGood(); 161 } else { 162 finishBad("onServiceConnected() again on an object when it should have been the first time"); 163 } 164 } else if (mStartState == STATE_START_2) { 165 if (mCount == 2) { 166 finishGood(); 167 } else { 168 finishBad("onServiceConnected() the first time on an object when it should have been the second time"); 169 } 170 } else { 171 finishBad("onServiceConnected() called unexpectedly"); 172 } 173 } 174 } 175 176 public void onServiceDisconnected(ComponentName name) { 177 if (mMonitor) { 178 if (mStartState == STATE_DESTROY) { 179 if (mExpectDisconnect) { 180 finishGood(); 181 } else { 182 finishBad("onServiceDisconnected() when it shouldn't have been"); 183 } 184 } else { 185 finishBad("onServiceDisconnected() called unexpectedly"); 186 } 187 } 188 } 189 } 190 191 void startExpectResult(Intent service) { 192 startExpectResult(service, new Bundle()); 193 } 194 195 void startExpectResult(Intent service, Bundle bundle) { 196 bundle.putIBinder(REPORT_OBJ_NAME, mStartReceiver); 197 boolean success = false; 198 try { 199 //Log.i("foo", "STATE_START_1"); 200 mStartState = STATE_START_1; 201 getContext().startService(new Intent(service).putExtras(bundle)); 202 waitForResultOrThrow(5 * 1000, "service to start first time"); 203 //Log.i("foo", "STATE_START_2"); 204 mStartState = STATE_START_2; 205 getContext().startService(new Intent(service).putExtras(bundle)); 206 waitForResultOrThrow(5 * 1000, "service to start second time"); 207 success = true; 208 } finally { 209 if (!success) { 210 try { 211 getContext().stopService(service); 212 } catch (Exception e) { 213 // eat 214 } 215 } 216 } 217 //Log.i("foo", "STATE_DESTROY"); 218 mStartState = STATE_DESTROY; 219 getContext().stopService(service); 220 waitForResultOrThrow(5 * 1000, "service to be destroyed"); 221 } 222 223 void startExpectNoPermission(Intent service) { 224 try { 225 getContext().startService(service); 226 fail("Expected security exception when starting " + service); 227 } catch (SecurityException e) { 228 // expected 229 } 230 } 231 232 void bindExpectResult(Intent service) { 233 TestConnection conn = new TestConnection(true, false); 234 TestConnection conn2 = new TestConnection(false, false); 235 boolean success = false; 236 try { 237 // Expect to see the TestConnection connected. 238 mStartState = STATE_START_1; 239 getContext().bindService(service, conn, 0); 240 getContext().startService(service); 241 waitForResultOrThrow(5 * 1000, "existing connection to receive service"); 242 243 // Expect to see the second TestConnection connected. 244 getContext().bindService(service, conn2, 0); 245 waitForResultOrThrow(5 * 1000, "new connection to receive service"); 246 247 getContext().unbindService(conn2); 248 success = true; 249 } finally { 250 if (!success) { 251 try { 252 getContext().stopService(service); 253 getContext().unbindService(conn); 254 getContext().unbindService(conn2); 255 } catch (Exception e) { 256 // eat 257 } 258 } 259 } 260 261 // Expect to see the TestConnection disconnected. 262 mStartState = STATE_DESTROY; 263 getContext().stopService(service); 264 waitForResultOrThrow(5 * 1000, "existing connection to lose service"); 265 266 getContext().unbindService(conn); 267 268 conn = new TestConnection(true, true); 269 success = false; 270 try { 271 // Expect to see the TestConnection connected. 272 conn.setMonitor(true); 273 mStartState = STATE_START_1; 274 getContext().bindService(service, conn, 0); 275 getContext().startService(service); 276 waitForResultOrThrow(5 * 1000, "existing connection to receive service"); 277 278 success = true; 279 } finally { 280 if (!success) { 281 try { 282 getContext().stopService(service); 283 getContext().unbindService(conn); 284 } catch (Exception e) { 285 // eat 286 } 287 } 288 } 289 290 // Expect to see the service unbind and then destroyed. 291 conn.setMonitor(false); 292 mStartState = STATE_UNBIND; 293 getContext().stopService(service); 294 waitForResultOrThrow(5 * 1000, "existing connection to lose service"); 295 296 getContext().unbindService(conn); 297 298 conn = new TestConnection(true, true); 299 success = false; 300 try { 301 // Expect to see the TestConnection connected. 302 conn.setMonitor(true); 303 mStartState = STATE_START_1; 304 getContext().bindService(service, conn, 0); 305 getContext().startService(service); 306 waitForResultOrThrow(5 * 1000, "existing connection to receive service"); 307 308 success = true; 309 } finally { 310 if (!success) { 311 try { 312 getContext().stopService(service); 313 getContext().unbindService(conn); 314 } catch (Exception e) { 315 // eat 316 } 317 } 318 } 319 320 // Expect to see the service unbind but not destroyed. 321 conn.setMonitor(false); 322 mStartState = STATE_UNBIND_ONLY; 323 getContext().unbindService(conn); 324 waitForResultOrThrow(5 * 1000, "existing connection to unbind service"); 325 326 // Expect to see the service rebound. 327 mStartState = STATE_REBIND; 328 getContext().bindService(service, conn, 0); 329 waitForResultOrThrow(5 * 1000, "existing connection to rebind service"); 330 331 // Expect to see the service unbind and then destroyed. 332 mStartState = STATE_UNBIND; 333 getContext().stopService(service); 334 waitForResultOrThrow(5 * 1000, "existing connection to lose service"); 335 336 getContext().unbindService(conn); 337 } 338 339 void bindAutoExpectResult(Intent service) { 340 TestConnection conn = new TestConnection(false, true); 341 boolean success = false; 342 try { 343 conn.setMonitor(true); 344 mStartState = STATE_START_1; 345 getContext().bindService( 346 service, conn, Context.BIND_AUTO_CREATE); 347 waitForResultOrThrow(5 * 1000, "connection to start and receive service"); 348 success = true; 349 } finally { 350 if (!success) { 351 try { 352 getContext().unbindService(conn); 353 } catch (Exception e) { 354 // eat 355 } 356 } 357 } 358 mStartState = STATE_UNBIND; 359 getContext().unbindService(conn); 360 waitForResultOrThrow(5 * 1000, "disconnecting from service"); 361 } 362 363 void bindExpectNoPermission(Intent service) { 364 TestConnection conn = new TestConnection(false, false); 365 try { 366 getContext().bindService(service, conn, Context.BIND_AUTO_CREATE); 367 fail("Expected security exception when binding " + service); 368 } catch (SecurityException e) { 369 // expected 370 } finally { 371 getContext().unbindService(conn); 372 } 373 } 374 375 376 @MediumTest 377 public void testLocalStartClass() throws Exception { 378 startExpectResult(new Intent(getContext(), LocalService.class)); 379 } 380 381 @MediumTest 382 public void testLocalStartAction() throws Exception { 383 startExpectResult(new Intent(SERVICE_LOCAL)); 384 } 385 386 @MediumTest 387 public void testLocalBindClass() throws Exception { 388 bindExpectResult(new Intent(getContext(), LocalService.class)); 389 } 390 391 @MediumTest 392 public void testLocalBindAction() throws Exception { 393 bindExpectResult(new Intent(SERVICE_LOCAL)); 394 } 395 396 @MediumTest 397 public void testLocalBindAutoClass() throws Exception { 398 bindAutoExpectResult(new Intent(getContext(), LocalService.class)); 399 } 400 401 @MediumTest 402 public void testLocalBindAutoAction() throws Exception { 403 bindAutoExpectResult(new Intent(SERVICE_LOCAL)); 404 } 405 406 @MediumTest 407 public void testLocalStartClassPermissionGranted() throws Exception { 408 startExpectResult(new Intent(getContext(), LocalGrantedService.class)); 409 } 410 411 @MediumTest 412 public void testLocalStartActionPermissionGranted() throws Exception { 413 startExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); 414 } 415 416 @MediumTest 417 public void testLocalBindClassPermissionGranted() throws Exception { 418 bindExpectResult(new Intent(getContext(), LocalGrantedService.class)); 419 } 420 421 @MediumTest 422 public void testLocalBindActionPermissionGranted() throws Exception { 423 bindExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); 424 } 425 426 @MediumTest 427 public void testLocalBindAutoClassPermissionGranted() throws Exception { 428 bindAutoExpectResult(new Intent(getContext(), LocalGrantedService.class)); 429 } 430 431 @MediumTest 432 public void testLocalBindAutoActionPermissionGranted() throws Exception { 433 bindAutoExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); 434 } 435 436 @MediumTest 437 public void testLocalStartClassPermissionDenied() throws Exception { 438 startExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); 439 } 440 441 @MediumTest 442 public void testLocalStartActionPermissionDenied() throws Exception { 443 startExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); 444 } 445 446 @MediumTest 447 public void testLocalBindClassPermissionDenied() throws Exception { 448 bindExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); 449 } 450 451 @MediumTest 452 public void testLocalBindActionPermissionDenied() throws Exception { 453 bindExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); 454 } 455 456 @MediumTest 457 public void testLocalUnbindTwice() throws Exception { 458 EmptyConnection conn = new EmptyConnection(); 459 getContext().bindService( 460 new Intent(SERVICE_LOCAL_GRANTED), conn, 0); 461 getContext().unbindService(conn); 462 try { 463 getContext().unbindService(conn); 464 fail("No exception thrown on second unbind"); 465 } catch (IllegalArgumentException e) { 466 //Log.i("foo", "Unbind exception", e); 467 } 468 } 469 } 470