1 /* 2 * Copyright (C) 2008 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.cts; 18 19 import static android.app.stubs.LocalForegroundService.COMMAND_START_FOREGROUND; 20 import static android.app.stubs.LocalForegroundService.COMMAND_START_FOREGROUND_DEFER_NOTIFICATION; 21 import static android.app.stubs.LocalForegroundService.COMMAND_STOP_FOREGROUND_DETACH_NOTIFICATION; 22 import static android.app.stubs.LocalForegroundService.COMMAND_STOP_FOREGROUND_DONT_REMOVE_NOTIFICATION; 23 24 import android.app.Activity; 25 import android.app.ActivityManager; 26 import android.app.Notification; 27 import android.app.NotificationChannel; 28 import android.app.NotificationManager; 29 import android.app.PendingIntent; 30 import android.app.stubs.ActivityTestsBase; 31 import android.app.stubs.IsolatedService; 32 import android.app.stubs.LaunchpadActivity; 33 import android.app.stubs.LocalDeniedService; 34 import android.app.stubs.LocalForegroundService; 35 import android.app.stubs.LocalGrantedService; 36 import android.app.stubs.LocalPhoneCallService; 37 import android.app.stubs.LocalService; 38 import android.app.stubs.LocalStoppedService; 39 import android.app.stubs.NullService; 40 import android.app.stubs.R; 41 import android.content.ComponentName; 42 import android.content.Context; 43 import android.content.Intent; 44 import android.content.ServiceConnection; 45 import android.os.Binder; 46 import android.os.Bundle; 47 import android.os.Handler; 48 import android.os.HandlerThread; 49 import android.os.IBinder; 50 import android.os.Parcel; 51 import android.os.ParcelFileDescriptor; 52 import android.os.Process; 53 import android.os.RemoteException; 54 import android.os.SystemClock; 55 import android.os.UserHandle; 56 import android.service.notification.StatusBarNotification; 57 import android.test.suitebuilder.annotation.MediumTest; 58 import android.util.Log; 59 import android.util.SparseArray; 60 61 import androidx.test.InstrumentationRegistry; 62 import androidx.test.filters.FlakyTest; 63 64 import com.android.compatibility.common.util.IBinderParcelable; 65 import com.android.compatibility.common.util.SystemUtil; 66 import com.android.server.am.nano.ActivityManagerServiceDumpProcessesProto; 67 import com.android.server.am.nano.ProcessRecordProto; 68 69 import com.google.protobuf.nano.InvalidProtocolBufferNanoException; 70 71 import java.io.ByteArrayOutputStream; 72 import java.io.FileInputStream; 73 import java.io.IOException; 74 import java.util.ArrayList; 75 import java.util.List; 76 import java.util.concurrent.Executor; 77 78 public class ServiceTest extends ActivityTestsBase { 79 private static final String TAG = "ServiceTest"; 80 private static final String NOTIFICATION_CHANNEL_ID = TAG; 81 private static final int STATE_START_1 = 0; 82 private static final int STATE_START_2 = 1; 83 private static final int STATE_START_3 = 2; 84 private static final int STATE_UNBIND = 3; 85 private static final int STATE_DESTROY = 4; 86 private static final int STATE_REBIND = 5; 87 private static final int STATE_UNBIND_ONLY = 6; 88 private static final int STATE_STOP_SELF_SUCCESS_UNBIND = 6; 89 private static final int DELAY = 5000; 90 private static final 91 String EXIST_CONN_TO_RECEIVE_SERVICE = "existing connection to receive service"; 92 private static final String EXIST_CONN_TO_LOSE_SERVICE = "existing connection to lose service"; 93 private static final String EXTERNAL_SERVICE_PACKAGE = "com.android.app2"; 94 private static final String EXTERNAL_SERVICE_COMPONENT = 95 EXTERNAL_SERVICE_PACKAGE + "/android.app.stubs.LocalService"; 96 private static final String APP_ZYGOTE_PROCESS_NAME = "android.app.stubs_zygote"; 97 private int mExpectedServiceState; 98 private Context mContext; 99 private Intent mLocalService; 100 private Intent mLocalDeniedService; 101 private Intent mLocalForegroundService; 102 private Intent mLocalPhoneCallService; 103 private Intent mLocalGrantedService; 104 private Intent mLocalService_ApplicationHasPermission; 105 private Intent mLocalService_ApplicationDoesNotHavePermission; 106 private Intent mIsolatedService; 107 private Intent mExternalService; 108 private Executor mContextMainExecutor; 109 private HandlerThread mBackgroundThread; 110 private Executor mBackgroundThreadExecutor; 111 112 private IBinder mStateReceiver; 113 114 private static class EmptyConnection implements ServiceConnection { 115 @Override onServiceConnected(ComponentName name, IBinder service)116 public void onServiceConnected(ComponentName name, IBinder service) { 117 } 118 119 @Override onServiceDisconnected(ComponentName name)120 public void onServiceDisconnected(ComponentName name) { 121 } 122 } 123 124 private static class NullServiceConnection implements ServiceConnection { 125 boolean mNullBinding = false; 126 onServiceConnected(ComponentName name, IBinder service)127 @Override public void onServiceConnected(ComponentName name, IBinder service) {} onServiceDisconnected(ComponentName name)128 @Override public void onServiceDisconnected(ComponentName name) {} 129 130 @Override onNullBinding(ComponentName name)131 public void onNullBinding(ComponentName name) { 132 synchronized (this) { 133 mNullBinding = true; 134 this.notifyAll(); 135 } 136 } 137 waitForNullBinding(final long timeout)138 public void waitForNullBinding(final long timeout) { 139 long now = SystemClock.uptimeMillis(); 140 final long end = now + timeout; 141 synchronized (this) { 142 while (!mNullBinding && (now < end)) { 143 try { 144 this.wait(end - now); 145 } catch (InterruptedException e) { 146 } 147 now = SystemClock.uptimeMillis(); 148 } 149 } 150 } 151 nullBindingReceived()152 public boolean nullBindingReceived() { 153 synchronized (this) { 154 return mNullBinding; 155 } 156 } 157 } 158 159 private class TestConnection implements ServiceConnection { 160 private final boolean mExpectDisconnect; 161 private final boolean mSetReporter; 162 private boolean mMonitor; 163 private int mCount; 164 private Thread mOnServiceConnectedThread; 165 TestConnection(boolean expectDisconnect, boolean setReporter)166 public TestConnection(boolean expectDisconnect, boolean setReporter) { 167 mExpectDisconnect = expectDisconnect; 168 mSetReporter = setReporter; 169 mMonitor = !setReporter; 170 } 171 setMonitor(boolean v)172 void setMonitor(boolean v) { 173 mMonitor = v; 174 } 175 getOnServiceConnectedThread()176 public Thread getOnServiceConnectedThread() { 177 return mOnServiceConnectedThread; 178 } 179 180 @Override onServiceConnected(ComponentName name, IBinder service)181 public void onServiceConnected(ComponentName name, IBinder service) { 182 mOnServiceConnectedThread = Thread.currentThread(); 183 if (mSetReporter) { 184 Parcel data = Parcel.obtain(); 185 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 186 data.writeStrongBinder(mStateReceiver); 187 try { 188 service.transact(LocalService.SET_REPORTER_CODE, data, null, 0); 189 } catch (RemoteException e) { 190 finishBad("DeadObjectException when sending reporting object"); 191 } 192 data.recycle(); 193 } 194 195 if (mMonitor) { 196 mCount++; 197 if (mExpectedServiceState == STATE_START_1) { 198 if (mCount == 1) { 199 finishGood(); 200 } else { 201 finishBad("onServiceConnected() again on an object when it " 202 + "should have been the first time"); 203 } 204 } else if (mExpectedServiceState == STATE_START_2) { 205 if (mCount == 2) { 206 finishGood(); 207 } else { 208 finishBad("onServiceConnected() the first time on an object " 209 + "when it should have been the second time"); 210 } 211 } else { 212 finishBad("onServiceConnected() called unexpectedly"); 213 } 214 } 215 } 216 217 @Override onServiceDisconnected(ComponentName name)218 public void onServiceDisconnected(ComponentName name) { 219 if (mMonitor) { 220 if (mExpectedServiceState == STATE_DESTROY) { 221 if (mExpectDisconnect) { 222 finishGood(); 223 } else { 224 finishBad("onServiceDisconnected() when it shouldn't have been"); 225 } 226 } else { 227 finishBad("onServiceDisconnected() called unexpectedly"); 228 } 229 } 230 } 231 } 232 233 private class TestStopSelfConnection extends TestConnection { 234 private IBinder mService; 235 TestStopSelfConnection()236 public TestStopSelfConnection() { 237 super(false /* expectDisconnect */, true /* setReporter */); 238 } 239 executeTransact(int code)240 private void executeTransact(int code) { 241 Parcel data = Parcel.obtain(); 242 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 243 try { 244 mService.transact(code, data, null /* reply */, 0); 245 } catch (RemoteException e) { 246 finishBad("DeadObjectException when sending reporting object"); 247 } 248 data.recycle(); 249 } 250 stopSelf()251 public void stopSelf() { 252 executeTransact(LocalService.STOP_SELF_CODE); 253 } 254 stopSelfResult()255 public void stopSelfResult() { 256 executeTransact(LocalService.STOP_SELF_RESULT_CODE); 257 } 258 259 @Override onServiceConnected(ComponentName name, IBinder service)260 public void onServiceConnected(ComponentName name, IBinder service) { 261 mService = service; 262 super.onServiceConnected(name, service); 263 } 264 265 @Override onServiceDisconnected(ComponentName name)266 public void onServiceDisconnected(ComponentName name) { 267 synchronized (this) { 268 mService = null; 269 } 270 } 271 } 272 273 final class IsolatedConnection implements ServiceConnection { 274 private IBinder mService; 275 private int mUid; 276 private int mPid; 277 private int mPpid; 278 private Thread mOnServiceConnectedThread; 279 IsolatedConnection()280 public IsolatedConnection() { 281 mUid = mPid = -1; 282 } 283 waitForService(int timeoutMs)284 public void waitForService(int timeoutMs) { 285 final long endTime = System.currentTimeMillis() + timeoutMs; 286 287 boolean timeout = false; 288 synchronized (this) { 289 while (mService == null) { 290 final long delay = endTime - System.currentTimeMillis(); 291 if (delay < 0) { 292 timeout = true; 293 break; 294 } 295 296 try { 297 wait(delay); 298 } catch (final java.lang.InterruptedException e) { 299 // do nothing 300 } 301 } 302 } 303 304 if (timeout) { 305 throw new RuntimeException("Timed out waiting for connection"); 306 } 307 } 308 getUid()309 public int getUid() { 310 return mUid; 311 } 312 getPid()313 public int getPid() { 314 return mPid; 315 } 316 getPpid()317 public int getPpid() { 318 return mPpid; 319 } 320 zygotePreloadCalled()321 public boolean zygotePreloadCalled() { 322 Parcel data = Parcel.obtain(); 323 Parcel reply = Parcel.obtain(); 324 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 325 try { 326 mService.transact(LocalService.GET_ZYGOTE_PRELOAD_CALLED, data, reply, 0); 327 } catch (RemoteException e) { 328 finishBad("DeadObjectException when sending reporting object"); 329 } 330 boolean value = reply.readBoolean(); 331 reply.recycle(); 332 data.recycle(); 333 return value; 334 } 335 setValue(int value)336 public void setValue(int value) { 337 Parcel data = Parcel.obtain(); 338 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 339 data.writeInt(value); 340 try { 341 mService.transact(LocalService.SET_VALUE_CODE, data, null, 0); 342 } catch (RemoteException e) { 343 finishBad("DeadObjectException when sending reporting object"); 344 } 345 data.recycle(); 346 } 347 getValue()348 public int getValue() { 349 Parcel data = Parcel.obtain(); 350 Parcel reply = Parcel.obtain(); 351 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 352 try { 353 mService.transact(LocalService.GET_VALUE_CODE, data, reply, 0); 354 } catch (RemoteException e) { 355 finishBad("DeadObjectException when sending reporting object"); 356 } 357 int value = reply.readInt(); 358 reply.recycle(); 359 data.recycle(); 360 return value; 361 } 362 getPidIpc()363 public int getPidIpc() { 364 Parcel data = Parcel.obtain(); 365 Parcel reply = Parcel.obtain(); 366 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 367 try { 368 mService.transact(LocalService.GET_PID_CODE, data, reply, 0); 369 } catch (RemoteException e) { 370 finishBad("DeadObjectException when sending reporting object"); 371 } 372 int value = reply.readInt(); 373 reply.recycle(); 374 data.recycle(); 375 return value; 376 } 377 getPpidIpc()378 public int getPpidIpc() { 379 Parcel data = Parcel.obtain(); 380 Parcel reply = Parcel.obtain(); 381 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 382 try { 383 mService.transact(LocalService.GET_PPID_CODE, data, reply, 0); 384 } catch (RemoteException e) { 385 finishBad("DeadObjectException when sending reporting object"); 386 } 387 int value = reply.readInt(); 388 reply.recycle(); 389 data.recycle(); 390 return value; 391 } 392 getUidIpc()393 public int getUidIpc() { 394 Parcel data = Parcel.obtain(); 395 Parcel reply = Parcel.obtain(); 396 data.writeInterfaceToken(LocalService.SERVICE_LOCAL); 397 try { 398 mService.transact(LocalService.GET_UID_CODE, data, reply, 0); 399 } catch (RemoteException e) { 400 finishBad("DeadObjectException when sending reporting object"); 401 } 402 int value = reply.readInt(); 403 reply.recycle(); 404 data.recycle(); 405 return value; 406 } 407 getOnServiceConnectedThread()408 public Thread getOnServiceConnectedThread() { 409 return mOnServiceConnectedThread; 410 } 411 412 @Override onServiceConnected(ComponentName name, IBinder service)413 public void onServiceConnected(ComponentName name, IBinder service) { 414 synchronized (this) { 415 mOnServiceConnectedThread = Thread.currentThread(); 416 mService = service; 417 mUid = getUidIpc(); 418 mPid = getPidIpc(); 419 mPpid = getPpidIpc(); 420 notifyAll(); 421 } 422 } 423 424 @Override onServiceDisconnected(ComponentName name)425 public void onServiceDisconnected(ComponentName name) { 426 synchronized (this) { 427 mService = null; 428 } 429 } 430 } 431 executeShellCommand(String cmd)432 private byte[] executeShellCommand(String cmd) { 433 try { 434 ParcelFileDescriptor pfd = 435 InstrumentationRegistry.getInstrumentation().getUiAutomation() 436 .executeShellCommand(cmd); 437 byte[] buf = new byte[512]; 438 int bytesRead; 439 FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 440 ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 441 while ((bytesRead = fis.read(buf)) != -1) { 442 stdout.write(buf, 0, bytesRead); 443 } 444 fis.close(); 445 return stdout.toByteArray(); 446 } catch (IOException e) { 447 throw new RuntimeException(e); 448 } 449 } 450 getActivityManagerProcesses()451 public ActivityManagerServiceDumpProcessesProto getActivityManagerProcesses() { 452 byte[] dump = executeShellCommand("dumpsys activity --proto processes"); 453 try { 454 return ActivityManagerServiceDumpProcessesProto.parseFrom(dump); 455 } catch (InvalidProtocolBufferNanoException e) { 456 throw new RuntimeException("Failed parsing proto", e); 457 } 458 } 459 startExpectResult(Intent service)460 private void startExpectResult(Intent service) { 461 startExpectResult(service, new Bundle()); 462 } 463 startExpectResult(Intent service, Bundle bundle)464 private void startExpectResult(Intent service, Bundle bundle) { 465 bundle.putParcelable(LocalService.REPORT_OBJ_NAME, new IBinderParcelable(mStateReceiver)); 466 467 boolean success = false; 468 try { 469 mExpectedServiceState = STATE_START_1; 470 mContext.startService(new Intent(service).putExtras(bundle)); 471 waitForResultOrThrow(DELAY, "service to start first time"); 472 mExpectedServiceState = STATE_START_2; 473 mContext.startService(new Intent(service).putExtras(bundle)); 474 waitForResultOrThrow(DELAY, "service to start second time"); 475 success = true; 476 } finally { 477 if (!success) { 478 mContext.stopService(service); 479 } 480 } 481 mExpectedServiceState = STATE_DESTROY; 482 mContext.stopService(service); 483 waitForResultOrThrow(DELAY, "service to be destroyed"); 484 } 485 getNotificationManager()486 private NotificationManager getNotificationManager() { 487 NotificationManager notificationManager = 488 (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE); 489 return notificationManager; 490 } 491 sendNotification(int id, String title)492 private void sendNotification(int id, String title) { 493 Notification notification = new Notification.Builder(getContext(), NOTIFICATION_CHANNEL_ID) 494 .setContentTitle(title) 495 .setSmallIcon(R.drawable.black) 496 .build(); 497 getNotificationManager().notify(id, notification); 498 } 499 cancelNotification(int id)500 private void cancelNotification(int id) { 501 getNotificationManager().cancel(id); 502 } 503 assertNotification(int id, String expectedTitle)504 private void assertNotification(int id, String expectedTitle) { 505 String packageName = getContext().getPackageName(); 506 String errorMessage = null; 507 for (int i = 1; i<=2; i++) { 508 errorMessage = null; 509 StatusBarNotification[] sbns = getNotificationManager().getActiveNotifications(); 510 for (StatusBarNotification sbn : sbns) { 511 if (sbn.getId() == id && sbn.getPackageName().equals(packageName)) { 512 String actualTitle = 513 sbn.getNotification().extras.getString(Notification.EXTRA_TITLE); 514 if (expectedTitle.equals(actualTitle)) { 515 return; 516 } 517 // It's possible the notification hasn't been updated yet, so save the error 518 // message to only fail after retrying. 519 errorMessage = String.format("Wrong title for notification #%d: " 520 + "expected '%s', actual '%s'", id, expectedTitle, actualTitle); 521 Log.w(TAG, errorMessage); 522 } 523 } 524 // Notification might not be rendered yet, wait and try again... 525 try { 526 Thread.sleep(DELAY); 527 } catch (InterruptedException e) { 528 Thread.currentThread().interrupt(); 529 } 530 } 531 if (errorMessage != null) { 532 fail(errorMessage); 533 } 534 fail("No notification with id " + id + " for package " + packageName); 535 } 536 assertNoNotification(int id)537 private void assertNoNotification(int id) { 538 String packageName = getContext().getPackageName(); 539 StatusBarNotification found = null; 540 for (int i = 1; i<=2; i++) { 541 found = null; 542 StatusBarNotification[] sbns = getNotificationManager().getActiveNotifications(); 543 for (StatusBarNotification sbn : sbns) { 544 if (sbn.getId() == id && sbn.getPackageName().equals(packageName)) { 545 found = sbn; 546 break; 547 } 548 } 549 if (found != null) { 550 // Notification might not be canceled yet, wait and try again... 551 try { 552 Thread.sleep(DELAY); 553 } catch (InterruptedException e) { 554 Thread.currentThread().interrupt(); 555 } 556 } 557 } 558 assertNull("Found notification with id " + id + " for package " + packageName + ": " 559 + found, found); 560 } 561 562 /** 563 * test the service lifecycle, a service can be used in two ways: 564 * 1 It can be started and allowed to run until someone stops it or it stops itself. 565 * In this mode, it's started by calling Context.startService() 566 * and stopped by calling Context.stopService(). 567 * It can stop itself by calling Service.stopSelf() or Service.stopSelfResult(). 568 * Only one stopService() call is needed to stop the service, 569 * no matter how many times startService() was called. 570 * 2 It can be operated programmatically using an interface that it defines and exports. 571 * Clients establish a connection to the Service object 572 * and use that connection to call into the service. 573 * The connection is established by calling Context.bindService(), 574 * and is closed by calling Context.unbindService(). 575 * Multiple clients can bind to the same service. 576 * If the service has not already been launched, bindService() can optionally launch it. 577 */ bindExpectResult(Intent service)578 private void bindExpectResult(Intent service) { 579 TestConnection conn = new TestConnection(true, false); 580 TestConnection conn2 = new TestConnection(false, false); 581 boolean success = false; 582 try { 583 // Expect to see the TestConnection connected. 584 mExpectedServiceState = STATE_START_1; 585 mContext.bindService(service, conn, 0); 586 mContext.startService(service); 587 waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE); 588 589 // Expect to see the second TestConnection connected. 590 mContext.bindService(service, conn2, 0); 591 waitForResultOrThrow(DELAY, "new connection to receive service"); 592 593 mContext.unbindService(conn2); 594 success = true; 595 } finally { 596 if (!success) { 597 mContext.unbindService(conn); 598 mContext.unbindService(conn2); 599 mContext.stopService(service); 600 } 601 } 602 603 // Expect to see the TestConnection disconnected. 604 mExpectedServiceState = STATE_DESTROY; 605 mContext.stopService(service); 606 waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE); 607 608 mContext.unbindService(conn); 609 610 conn = new TestConnection(true, true); 611 success = false; 612 try { 613 // Expect to see the TestConnection connected. 614 conn.setMonitor(true); 615 mExpectedServiceState = STATE_START_1; 616 mContext.bindService(service, conn, 0); 617 mContext.startService(service); 618 waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE); 619 620 success = true; 621 } finally { 622 if (!success) { 623 mContext.unbindService(conn); 624 mContext.stopService(service); 625 } 626 } 627 628 // Expect to see the service unbind and then destroyed. 629 conn.setMonitor(false); 630 mExpectedServiceState = STATE_UNBIND; 631 mContext.stopService(service); 632 waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE); 633 634 mContext.unbindService(conn); 635 636 conn = new TestConnection(true, true); 637 success = false; 638 try { 639 // Expect to see the TestConnection connected. 640 conn.setMonitor(true); 641 mExpectedServiceState = STATE_START_1; 642 mContext.bindService(service, conn, 0); 643 mContext.startService(service); 644 waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE); 645 646 success = true; 647 } finally { 648 if (!success) { 649 mContext.unbindService(conn); 650 mContext.stopService(service); 651 } 652 } 653 654 // Expect to see the service unbind but not destroyed. 655 conn.setMonitor(false); 656 mExpectedServiceState = STATE_UNBIND_ONLY; 657 mContext.unbindService(conn); 658 waitForResultOrThrow(DELAY, "existing connection to unbind service"); 659 660 // Expect to see the service rebound. 661 mExpectedServiceState = STATE_REBIND; 662 mContext.bindService(service, conn, 0); 663 waitForResultOrThrow(DELAY, "existing connection to rebind service"); 664 665 // Expect to see the service unbind and then destroyed. 666 mExpectedServiceState = STATE_UNBIND; 667 mContext.stopService(service); 668 waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE); 669 670 mContext.unbindService(conn); 671 } 672 673 /** 674 * test automatically create the service as long as the binding exists 675 * and disconnect from an application service 676 */ bindAutoExpectResult(Intent service)677 private void bindAutoExpectResult(Intent service) { 678 TestConnection conn = new TestConnection(false, true); 679 boolean success = false; 680 try { 681 conn.setMonitor(true); 682 mExpectedServiceState = STATE_START_1; 683 mContext.bindService( 684 service, conn, Context.BIND_AUTO_CREATE); 685 waitForResultOrThrow(DELAY, "connection to start and receive service"); 686 success = true; 687 } finally { 688 if (!success) { 689 mContext.unbindService(conn); 690 } 691 } 692 mExpectedServiceState = STATE_UNBIND; 693 mContext.unbindService(conn); 694 waitForResultOrThrow(DELAY, "disconnecting from service"); 695 } 696 697 @Override setUp()698 protected void setUp() throws Exception { 699 super.setUp(); 700 mContext = getContext(); 701 mLocalService = new Intent(mContext, LocalService.class); 702 mExternalService = new Intent(); 703 mExternalService.setComponent(ComponentName.unflattenFromString(EXTERNAL_SERVICE_COMPONENT)); 704 mLocalForegroundService = new Intent(mContext, LocalForegroundService.class); 705 mLocalPhoneCallService = new Intent(mContext, LocalPhoneCallService.class); 706 mLocalDeniedService = new Intent(mContext, LocalDeniedService.class); 707 mLocalGrantedService = new Intent(mContext, LocalGrantedService.class); 708 mLocalService_ApplicationHasPermission = new Intent( 709 LocalService.SERVICE_LOCAL_GRANTED, null /*uri*/, mContext, LocalService.class); 710 mLocalService_ApplicationDoesNotHavePermission = new Intent( 711 LocalService.SERVICE_LOCAL_DENIED, null /*uri*/, mContext, LocalService.class); 712 mIsolatedService = new Intent(mContext, IsolatedService.class); 713 mStateReceiver = new MockBinder(); 714 getNotificationManager().createNotificationChannel(new NotificationChannel( 715 NOTIFICATION_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_DEFAULT)); 716 mContextMainExecutor = mContext.getMainExecutor(); 717 executeShellCommand("cmd activity fgs-notification-rate-limit disable"); 718 } 719 setupBackgroundThread()720 private void setupBackgroundThread() { 721 HandlerThread thread = new HandlerThread("ServiceTestBackgroundThread"); 722 thread.start(); 723 Handler handler = new Handler(thread.getLooper()); 724 mBackgroundThread = thread; 725 mBackgroundThreadExecutor = new Executor() { 726 @Override 727 public void execute(Runnable runnable) { 728 handler.post(runnable); 729 } 730 }; 731 } 732 733 @Override tearDown()734 protected void tearDown() throws Exception { 735 super.tearDown(); 736 executeShellCommand("cmd activity fgs-notification-rate-limit enable"); 737 getNotificationManager().deleteNotificationChannel(NOTIFICATION_CHANNEL_ID); 738 mContext.stopService(mLocalService); 739 mContext.stopService(mLocalForegroundService); 740 mContext.stopService(mLocalGrantedService); 741 mContext.stopService(mLocalService_ApplicationHasPermission); 742 mContext.stopService(mExternalService); 743 if (mBackgroundThread != null) { 744 mBackgroundThread.quitSafely(); 745 } 746 mBackgroundThread = null; 747 mBackgroundThreadExecutor = null; 748 } 749 750 private class MockBinder extends Binder { 751 @Override onTransact(int code, Parcel data, Parcel reply, int flags)752 protected boolean onTransact(int code, Parcel data, Parcel reply, 753 int flags) throws RemoteException { 754 if (code == LocalService.STARTED_CODE) { 755 data.enforceInterface(LocalService.SERVICE_LOCAL); 756 int count = data.readInt(); 757 if (mExpectedServiceState == STATE_START_1) { 758 if (count == 1) { 759 finishGood(); 760 } else { 761 finishBad("onStart() again on an object when it " 762 + "should have been the first time"); 763 } 764 } else if (mExpectedServiceState == STATE_START_2) { 765 if (count == 2) { 766 finishGood(); 767 } else { 768 finishBad("onStart() the first time on an object when it " 769 + "should have been the second time"); 770 } 771 } else if (mExpectedServiceState == STATE_START_3) { 772 if (count == 3) { 773 finishGood(); 774 } else { 775 finishBad("onStart() the first time on an object when it " 776 + "should have been the third time"); 777 } 778 } else { 779 finishBad("onStart() was called when not expected (state=" 780 + mExpectedServiceState + ")"); 781 } 782 return true; 783 } else if (code == LocalService.DESTROYED_CODE) { 784 data.enforceInterface(LocalService.SERVICE_LOCAL); 785 if (mExpectedServiceState == STATE_DESTROY) { 786 finishGood(); 787 } else { 788 finishBad("onDestroy() was called when not expected (state=" 789 + mExpectedServiceState + ")"); 790 } 791 return true; 792 } else if (code == LocalService.UNBIND_CODE) { 793 data.enforceInterface(LocalService.SERVICE_LOCAL); 794 if (mExpectedServiceState == STATE_UNBIND) { 795 mExpectedServiceState = STATE_DESTROY; 796 } else if (mExpectedServiceState == STATE_UNBIND_ONLY) { 797 finishGood(); 798 } else { 799 finishBad("onUnbind() was called when not expected (state=" 800 + mExpectedServiceState + ")"); 801 } 802 return true; 803 } else if (code == LocalService.REBIND_CODE) { 804 data.enforceInterface(LocalService.SERVICE_LOCAL); 805 if (mExpectedServiceState == STATE_REBIND) { 806 finishGood(); 807 } else { 808 finishBad("onRebind() was called when not expected (state=" 809 + mExpectedServiceState + ")"); 810 } 811 return true; 812 } else if (code == LocalService.STOP_SELF_SUCCESS_UNBIND_CODE) { 813 data.enforceInterface(LocalService.SERVICE_LOCAL); 814 if (mExpectedServiceState == STATE_STOP_SELF_SUCCESS_UNBIND) { 815 finishGood(); 816 } else { 817 finishBad("onUnbind() was called when not expected (state=" 818 + mExpectedServiceState + ")"); 819 } 820 return true; 821 } else { 822 return super.onTransact(code, data, reply, flags); 823 } 824 } 825 } 826 testStopSelf()827 public void testStopSelf() throws Exception { 828 TestStopSelfConnection conn = new TestStopSelfConnection(); 829 boolean success = false; 830 final Intent service = new Intent(mContext, LocalStoppedService.class); 831 try { 832 conn.setMonitor(true); 833 mExpectedServiceState = STATE_START_1; 834 mContext.bindService(service, conn, 0); 835 mContext.startService(service); 836 waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE); 837 success = true; 838 } finally { 839 if (!success) { 840 mContext.unbindService(conn); 841 mContext.stopService(service); 842 } 843 } 844 // Expect to see the service unbind and then destroyed. 845 mExpectedServiceState = STATE_UNBIND; 846 conn.stopSelf(); 847 waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE); 848 849 mContext.unbindService(conn); 850 } 851 testStopSelfResult()852 public void testStopSelfResult() throws Exception { 853 TestStopSelfConnection conn = new TestStopSelfConnection(); 854 boolean success = false; 855 final Intent service = new Intent(mContext, LocalStoppedService.class); 856 try { 857 conn.setMonitor(true); 858 mExpectedServiceState = STATE_START_1; 859 mContext.bindService(service, conn, 0); 860 mContext.startService(service); 861 waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE); 862 success = true; 863 } finally { 864 if (!success) { 865 mContext.unbindService(conn); 866 mContext.stopService(service); 867 } 868 } 869 // Expect to see the service unbind and then destroyed. 870 mExpectedServiceState = STATE_STOP_SELF_SUCCESS_UNBIND; 871 conn.stopSelfResult(); 872 waitForResultOrThrow(DELAY, EXIST_CONN_TO_LOSE_SERVICE); 873 874 mContext.unbindService(conn); 875 } 876 testLocalStartClass()877 public void testLocalStartClass() throws Exception { 878 startExpectResult(mLocalService); 879 } 880 testLocalStartAction()881 public void testLocalStartAction() throws Exception { 882 startExpectResult(new Intent( 883 LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class)); 884 } 885 testLocalBindClass()886 public void testLocalBindClass() throws Exception { 887 bindExpectResult(mLocalService); 888 } 889 testBindServiceWithExecutor()890 public void testBindServiceWithExecutor() throws Exception { 891 setupBackgroundThread(); 892 893 TestConnection conn = new TestConnection(true, false); 894 mExpectedServiceState = STATE_START_1; 895 mContext.bindService( 896 mLocalService, Context.BIND_AUTO_CREATE, mBackgroundThreadExecutor, conn); 897 waitForResultOrThrow(DELAY, EXIST_CONN_TO_RECEIVE_SERVICE); 898 assertEquals(mBackgroundThread, conn.getOnServiceConnectedThread()); 899 900 mContext.unbindService(conn); 901 } 902 foregroundServiceIntent(Intent intent, int command)903 private Intent foregroundServiceIntent(Intent intent, int command) { 904 return new Intent(intent) 905 .putExtras(LocalForegroundService.newCommand(mStateReceiver, command)); 906 } 907 908 /* Just the Intent for a foreground service */ foregroundServiceIntent(int command)909 private Intent foregroundServiceIntent(int command) { 910 return foregroundServiceIntent(mLocalForegroundService, command); 911 } 912 startForegroundService(Intent intent, int command)913 private void startForegroundService(Intent intent, int command) { 914 mContext.startService(foregroundServiceIntent(intent, command)); 915 } 916 startForegroundService(int command)917 private void startForegroundService(int command) { 918 mContext.startService(foregroundServiceIntent(command)); 919 } 920 921 /* Start the service in a way that promises to go into the foreground */ startRequiredForegroundService(int command)922 private void startRequiredForegroundService(int command) { 923 mContext.startForegroundService(foregroundServiceIntent(command)); 924 } 925 926 @MediumTest testForegroundService_dontRemoveNotificationOnStop()927 public void testForegroundService_dontRemoveNotificationOnStop() throws Exception { 928 boolean success = false; 929 try { 930 // Start service as foreground - it should show notification #1 931 mExpectedServiceState = STATE_START_1; 932 startForegroundService(COMMAND_START_FOREGROUND); 933 waitForResultOrThrow(DELAY, "service to start first time"); 934 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 935 936 // Stop foreground without removing notification - it should still show notification #1 937 mExpectedServiceState = STATE_START_2; 938 startForegroundService(COMMAND_STOP_FOREGROUND_DONT_REMOVE_NOTIFICATION); 939 waitForResultOrThrow(DELAY, "service to stop foreground"); 940 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 941 942 // Sends another notification reusing the same notification id. 943 String newTitle = "YODA I AM"; 944 sendNotification(1, newTitle); 945 assertNotification(1, newTitle); 946 947 // Start service as foreground again - it should kill notification #1 and show #2 948 mExpectedServiceState = STATE_START_3; 949 startForegroundService(COMMAND_START_FOREGROUND); 950 waitForResultOrThrow(DELAY, "service to start foreground 2nd time"); 951 assertNoNotification(1); 952 assertNotification(2, LocalForegroundService.getNotificationTitle(2)); 953 954 success = true; 955 } finally { 956 if (!success) { 957 mContext.stopService(mLocalForegroundService); 958 } 959 } 960 mExpectedServiceState = STATE_DESTROY; 961 mContext.stopService(mLocalForegroundService); 962 waitForResultOrThrow(DELAY, "service to be destroyed"); 963 assertNoNotification(1); 964 assertNoNotification(2); 965 } 966 967 @MediumTest testForegroundService_removeNotificationOnStop()968 public void testForegroundService_removeNotificationOnStop() throws Exception { 969 testForegroundServiceRemoveNotificationOnStop(false); 970 } 971 972 @MediumTest testForegroundService_removeNotificationOnStopUsingFlags()973 public void testForegroundService_removeNotificationOnStopUsingFlags() throws Exception { 974 testForegroundServiceRemoveNotificationOnStop(true); 975 } 976 testForegroundServiceRemoveNotificationOnStop(boolean usingFlags)977 private void testForegroundServiceRemoveNotificationOnStop(boolean usingFlags) 978 throws Exception { 979 boolean success = false; 980 try { 981 // Start service as foreground - it should show notification #1 982 Log.d(TAG, "Expecting first start state..."); 983 mExpectedServiceState = STATE_START_1; 984 startForegroundService(COMMAND_START_FOREGROUND); 985 waitForResultOrThrow(DELAY, "service to start first time"); 986 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 987 988 // Stop foreground removing notification 989 Log.d(TAG, "Expecting second start state..."); 990 mExpectedServiceState = STATE_START_2; 991 if (usingFlags) { 992 startForegroundService(LocalForegroundService 993 .COMMAND_STOP_FOREGROUND_REMOVE_NOTIFICATION_USING_FLAGS); 994 } else { 995 startForegroundService(LocalForegroundService 996 .COMMAND_STOP_FOREGROUND_REMOVE_NOTIFICATION); 997 } 998 waitForResultOrThrow(DELAY, "service to stop foreground"); 999 assertNoNotification(1); 1000 1001 // Start service as foreground again - it should show notification #2 1002 mExpectedServiceState = STATE_START_3; 1003 startForegroundService(COMMAND_START_FOREGROUND); 1004 waitForResultOrThrow(DELAY, "service to start as foreground 2nd time"); 1005 assertNotification(2, LocalForegroundService.getNotificationTitle(2)); 1006 1007 success = true; 1008 } finally { 1009 if (!success) { 1010 mContext.stopService(mLocalForegroundService); 1011 } 1012 } 1013 mExpectedServiceState = STATE_DESTROY; 1014 mContext.stopService(mLocalForegroundService); 1015 waitForResultOrThrow(DELAY, "service to be destroyed"); 1016 assertNoNotification(1); 1017 assertNoNotification(2); 1018 } 1019 1020 @FlakyTest testRunningServices()1021 public void testRunningServices() throws Exception { 1022 final int maxReturnedServices = 10; 1023 final Bundle bundle = new Bundle(); 1024 bundle.putParcelable(LocalService.REPORT_OBJ_NAME, new IBinderParcelable(mStateReceiver)); 1025 1026 boolean success = false; 1027 1028 ActivityManager am = mContext.getSystemService(ActivityManager.class); 1029 1030 // Put target app on whitelist so we can start its services. 1031 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 1032 "cmd deviceidle whitelist +" + EXTERNAL_SERVICE_PACKAGE); 1033 1034 // No services should be reported back at the beginning 1035 assertEquals(0, am.getRunningServices(maxReturnedServices).size()); 1036 try { 1037 mExpectedServiceState = STATE_START_1; 1038 // Start external service. 1039 mContext.startService(new Intent(mExternalService).putExtras(bundle)); 1040 waitForResultOrThrow(DELAY, "external service to start first time"); 1041 1042 // Ensure we can't see service. 1043 assertEquals(0, am.getRunningServices(maxReturnedServices).size()); 1044 1045 // Start local service. 1046 mContext.startService(new Intent(mLocalService).putExtras(bundle)); 1047 waitForResultOrThrow(DELAY, "local service to start first time"); 1048 success = true; 1049 1050 // Ensure we can see service and it is ours. 1051 List<ActivityManager.RunningServiceInfo> services = am.getRunningServices(maxReturnedServices); 1052 assertEquals(1, services.size()); 1053 assertEquals(android.os.Process.myUid(), services.get(0).uid); 1054 } finally { 1055 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 1056 "cmd deviceidle whitelist -" + EXTERNAL_SERVICE_PACKAGE); 1057 if (!success) { 1058 mContext.stopService(mLocalService); 1059 mContext.stopService(mExternalService); 1060 } 1061 } 1062 mExpectedServiceState = STATE_DESTROY; 1063 1064 mContext.stopService(mExternalService); 1065 waitForResultOrThrow(DELAY, "external service to be destroyed"); 1066 1067 mContext.stopService(mLocalService); 1068 waitForResultOrThrow(DELAY, "local service to be destroyed"); 1069 1070 // Once our service has stopped, make sure we can't see any services. 1071 assertEquals(0, am.getRunningServices(maxReturnedServices).size()); 1072 } 1073 1074 @MediumTest testForegroundService_detachNotificationOnStop()1075 public void testForegroundService_detachNotificationOnStop() throws Exception { 1076 String newTitle = null; 1077 boolean success = false; 1078 try { 1079 1080 // Start service as foreground - it should show notification #1 1081 mExpectedServiceState = STATE_START_1; 1082 startForegroundService(COMMAND_START_FOREGROUND); 1083 waitForResultOrThrow(DELAY, "service to start first time"); 1084 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 1085 1086 // Detaching notification 1087 mExpectedServiceState = STATE_START_2; 1088 startForegroundService(COMMAND_STOP_FOREGROUND_DETACH_NOTIFICATION); 1089 waitForResultOrThrow(DELAY, "service to stop foreground"); 1090 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 1091 1092 // Sends another notification reusing the same notification id. 1093 newTitle = "YODA I AM"; 1094 sendNotification(1, newTitle); 1095 assertNotification(1, newTitle); 1096 1097 // Start service as foreground again - it should show notification #2.. 1098 mExpectedServiceState = STATE_START_3; 1099 startForegroundService(COMMAND_START_FOREGROUND); 1100 waitForResultOrThrow(DELAY, "service to start as foreground 2nd time"); 1101 assertNotification(2, LocalForegroundService.getNotificationTitle(2)); 1102 //...but keeping notification #1 1103 assertNotification(1, newTitle); 1104 1105 success = true; 1106 } finally { 1107 if (!success) { 1108 mContext.stopService(mLocalForegroundService); 1109 } 1110 } 1111 mExpectedServiceState = STATE_DESTROY; 1112 mContext.stopService(mLocalForegroundService); 1113 waitForResultOrThrow(DELAY, "service to be destroyed"); 1114 if (newTitle == null) { 1115 assertNoNotification(1); 1116 } else { 1117 assertNotification(1, newTitle); 1118 cancelNotification(1); 1119 assertNoNotification(1); 1120 } 1121 assertNoNotification(2); 1122 } 1123 testForegroundService_notificationChannelDeletion()1124 public void testForegroundService_notificationChannelDeletion() throws Exception { 1125 NotificationManager noMan = mContext.getSystemService(NotificationManager.class); 1126 1127 // Start service as foreground - it should show notification #1 1128 mExpectedServiceState = STATE_START_1; 1129 startForegroundService(COMMAND_START_FOREGROUND); 1130 waitForResultOrThrow(DELAY, "service to start first time"); 1131 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 1132 1133 try { 1134 final String channel = LocalForegroundService.NOTIFICATION_CHANNEL_ID; 1135 noMan.deleteNotificationChannel(channel); 1136 fail("Deleting FGS notification channel did not throw"); 1137 } catch (SecurityException se) { 1138 // Expected outcome, i.e. success case 1139 } catch (Exception e) { 1140 fail("Deleting FGS notification threw unexpected failure " + e); 1141 } 1142 1143 mExpectedServiceState = STATE_DESTROY; 1144 mContext.stopService(mLocalForegroundService); 1145 waitForResultOrThrow(DELAY, "service to be destroyed"); 1146 1147 } 1148 testForegroundService_deferredNotificationChannelDeletion()1149 public void testForegroundService_deferredNotificationChannelDeletion() throws Exception { 1150 NotificationManager noMan = mContext.getSystemService(NotificationManager.class); 1151 1152 // Start service as foreground - it should show notification #1 1153 mExpectedServiceState = STATE_START_1; 1154 startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1155 waitForResultOrThrow(DELAY, "service to start first time"); 1156 assertNoNotification(1); 1157 1158 try { 1159 final String channel = LocalForegroundService.NOTIFICATION_CHANNEL_ID; 1160 noMan.deleteNotificationChannel(channel); 1161 fail("Deleting FGS deferred notification channel did not throw"); 1162 } catch (SecurityException se) { 1163 // Expected outcome 1164 } catch (Exception e) { 1165 fail("Deleting deferred FGS notification threw unexpected failure " + e); 1166 } 1167 1168 mExpectedServiceState = STATE_DESTROY; 1169 mContext.stopService(mLocalForegroundService); 1170 waitForResultOrThrow(DELAY, "service to be destroyed"); 1171 } 1172 testForegroundService_typeImmediateNotification()1173 public void testForegroundService_typeImmediateNotification() throws Exception { 1174 // expect that an FGS with phoneCall type has its notification displayed 1175 // immediately even without explicit request by the app 1176 mExpectedServiceState = STATE_START_1; 1177 startForegroundService(mLocalPhoneCallService, 1178 COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1179 waitForResultOrThrow(DELAY, "phoneCall service to start"); 1180 assertNotification(1, LocalPhoneCallService.getNotificationTitle(1)); 1181 1182 mExpectedServiceState = STATE_DESTROY; 1183 mContext.stopService(mLocalPhoneCallService); 1184 waitForResultOrThrow(DELAY, "service to be destroyed"); 1185 } 1186 waitMillis(long timeMillis)1187 private void waitMillis(long timeMillis) { 1188 final long stopTime = SystemClock.uptimeMillis() + timeMillis; 1189 while (SystemClock.uptimeMillis() < stopTime) { 1190 try { 1191 Thread.sleep(1000L); 1192 } catch (InterruptedException e) { 1193 /* ignore */ 1194 } 1195 } 1196 } 1197 testForegroundService_deferredNotification()1198 public void testForegroundService_deferredNotification() throws Exception { 1199 mExpectedServiceState = STATE_START_1; 1200 startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1201 waitForResultOrThrow(DELAY, "service to start with deferred notification"); 1202 assertNoNotification(1); 1203 1204 // Wait ten seconds and verify that the notification is now visible 1205 waitMillis(10_000L); 1206 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 1207 1208 mExpectedServiceState = STATE_DESTROY; 1209 mContext.stopService(mLocalForegroundService); 1210 waitForResultOrThrow(DELAY, "service to be destroyed"); 1211 } 1212 testForegroundService_deferredExistingNotification()1213 public void testForegroundService_deferredExistingNotification() throws Exception { 1214 // First, post the notification outright as not-FGS-related 1215 final NotificationManager nm = getNotificationManager(); 1216 final String channelId = LocalForegroundService.getNotificationChannelId(); 1217 nm.createNotificationChannel(new NotificationChannel(channelId, channelId, 1218 NotificationManager.IMPORTANCE_DEFAULT)); 1219 Notification.Builder builder = 1220 new Notification.Builder(mContext, channelId) 1221 .setContentTitle(LocalForegroundService.getNotificationTitle(1)) 1222 .setSmallIcon(R.drawable.black); 1223 nm.notify(1, builder.build()); 1224 1225 mExpectedServiceState = STATE_START_1; 1226 startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1227 waitForResultOrThrow(DELAY, "service to start with existing notification"); 1228 1229 // Normally deferred but should display immediately because the notification 1230 // was already showing 1231 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 1232 1233 mExpectedServiceState = STATE_DESTROY; 1234 mContext.stopService(mLocalForegroundService); 1235 waitForResultOrThrow(DELAY, "service to be destroyed"); 1236 } 1237 testForegroundService_deferThenImmediateNotify()1238 public void testForegroundService_deferThenImmediateNotify() throws Exception { 1239 final String notificationTitle = "deferThenImmediateNotify"; 1240 1241 mExpectedServiceState = STATE_START_1; 1242 startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1243 waitForResultOrThrow(DELAY, "service to start with deferred notification"); 1244 assertNoNotification(1); 1245 1246 // Explicitly post a new Notification with the same id, still deferrable 1247 final NotificationManager nm = getNotificationManager(); 1248 final String channelId = LocalForegroundService.getNotificationChannelId(); 1249 nm.createNotificationChannel(new NotificationChannel(channelId, channelId, 1250 NotificationManager.IMPORTANCE_DEFAULT)); 1251 Notification.Builder builder = 1252 new Notification.Builder(mContext, channelId) 1253 .setContentTitle(notificationTitle) 1254 .setSmallIcon(R.drawable.black) 1255 .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE); 1256 nm.notify(1, builder.build()); 1257 1258 // Verify that the notification is immediately shown with the new content 1259 assertNotification(1, notificationTitle); 1260 1261 mExpectedServiceState = STATE_DESTROY; 1262 mContext.stopService(mLocalForegroundService); 1263 waitForResultOrThrow(DELAY, "service to be destroyed"); 1264 } 1265 testForegroundService_deferThenDeferrableNotify()1266 public void testForegroundService_deferThenDeferrableNotify() throws Exception { 1267 final String notificationTitle = "deferThenDeferrableNotify"; 1268 1269 mExpectedServiceState = STATE_START_1; 1270 startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1271 waitForResultOrThrow(DELAY, "service to start with deferred notification"); 1272 assertNoNotification(1); 1273 1274 // Explicitly post a new Notification with the same id, still deferrable 1275 final NotificationManager nm = getNotificationManager(); 1276 final String channelId = LocalForegroundService.getNotificationChannelId(); 1277 nm.createNotificationChannel(new NotificationChannel(channelId, channelId, 1278 NotificationManager.IMPORTANCE_DEFAULT)); 1279 Notification.Builder builder = 1280 new Notification.Builder(mContext, channelId) 1281 .setContentTitle(notificationTitle) 1282 .setSmallIcon(R.drawable.black) 1283 .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_DEFERRED); 1284 nm.notify(1, builder.build()); 1285 1286 // Normally would have displayed, but should only have been taken as the eventual 1287 // deferred notification. Verify that it isn't shown yet, then re-verify after 1288 // the ten second deferral period that it's both visible and has the correct 1289 // (updated) title. 1290 assertNoNotification(1); 1291 waitMillis(10_000L); 1292 assertNotification(1, notificationTitle); 1293 1294 mExpectedServiceState = STATE_DESTROY; 1295 mContext.stopService(mLocalForegroundService); 1296 waitForResultOrThrow(DELAY, "service to be destroyed"); 1297 } 1298 testForegroundService_deferThenKeepNotification()1299 public void testForegroundService_deferThenKeepNotification() throws Exception { 1300 // Start FGS with deferred notification; it should not display 1301 mExpectedServiceState = STATE_START_1; 1302 startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION); 1303 waitForResultOrThrow(DELAY, "service to start first time"); 1304 assertNoNotification(1); 1305 1306 // Exit foreground but keep notification - it should display immediately 1307 mExpectedServiceState = STATE_START_2; 1308 startForegroundService(COMMAND_STOP_FOREGROUND_DONT_REMOVE_NOTIFICATION); 1309 waitForResultOrThrow(DELAY, "service to stop foreground"); 1310 assertNotification(1, LocalForegroundService.getNotificationTitle(1)); 1311 1312 mExpectedServiceState = STATE_DESTROY; 1313 mContext.stopService(mLocalForegroundService); 1314 waitForResultOrThrow(DELAY, "service to be destroyed"); 1315 } 1316 1317 class TestSendCallback implements PendingIntent.OnFinished { 1318 public volatile int result = -1; 1319 1320 @Override onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)1321 public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, 1322 String resultData, Bundle resultExtras) { 1323 Log.i(TAG, "foreground service PendingIntent callback got " + resultCode); 1324 this.result = resultCode; 1325 } 1326 } 1327 1328 @MediumTest testForegroundService_pendingIntentForeground()1329 public void testForegroundService_pendingIntentForeground() throws Exception { 1330 boolean success = false; 1331 1332 PendingIntent pi = PendingIntent.getForegroundService(mContext, 1, 1333 foregroundServiceIntent(COMMAND_START_FOREGROUND), 1334 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); 1335 TestSendCallback callback = new TestSendCallback(); 1336 1337 try { 1338 mExpectedServiceState = STATE_START_1; 1339 pi.send(5038, callback, null); 1340 waitForResultOrThrow(DELAY, "service to start first time"); 1341 assertTrue(callback.result > -1); 1342 1343 success = true; 1344 } finally { 1345 if (!success) { 1346 mContext.stopService(mLocalForegroundService); 1347 } 1348 } 1349 1350 mExpectedServiceState = STATE_DESTROY; 1351 mContext.stopService(mLocalForegroundService); 1352 waitForResultOrThrow(DELAY, "pendingintent service to be destroyed"); 1353 } 1354 1355 @MediumTest testLocalBindAction()1356 public void testLocalBindAction() throws Exception { 1357 bindExpectResult(new Intent( 1358 LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class)); 1359 } 1360 1361 @MediumTest testLocalBindAutoClass()1362 public void testLocalBindAutoClass() throws Exception { 1363 bindAutoExpectResult(mLocalService); 1364 } 1365 1366 @MediumTest testLocalBindAutoAction()1367 public void testLocalBindAutoAction() throws Exception { 1368 bindAutoExpectResult(new Intent( 1369 LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class)); 1370 } 1371 1372 @MediumTest testLocalStartClassPermissions()1373 public void testLocalStartClassPermissions() throws Exception { 1374 startExpectResult(mLocalGrantedService); 1375 startExpectResult(mLocalDeniedService); 1376 } 1377 1378 @MediumTest testLocalStartActionPermissions()1379 public void testLocalStartActionPermissions() throws Exception { 1380 startExpectResult(mLocalService_ApplicationHasPermission); 1381 startExpectResult(mLocalService_ApplicationDoesNotHavePermission); 1382 } 1383 1384 @MediumTest testLocalBindClassPermissions()1385 public void testLocalBindClassPermissions() throws Exception { 1386 bindExpectResult(mLocalGrantedService); 1387 bindExpectResult(mLocalDeniedService); 1388 } 1389 1390 @MediumTest testLocalBindActionPermissions()1391 public void testLocalBindActionPermissions() throws Exception { 1392 bindExpectResult(mLocalService_ApplicationHasPermission); 1393 bindExpectResult(mLocalService_ApplicationDoesNotHavePermission); 1394 } 1395 1396 @MediumTest testLocalBindAutoClassPermissionGranted()1397 public void testLocalBindAutoClassPermissionGranted() throws Exception { 1398 bindAutoExpectResult(mLocalGrantedService); 1399 } 1400 1401 @MediumTest testLocalBindAutoActionPermissionGranted()1402 public void testLocalBindAutoActionPermissionGranted() throws Exception { 1403 bindAutoExpectResult(mLocalService_ApplicationHasPermission); 1404 } 1405 1406 @MediumTest testLocalUnbindTwice()1407 public void testLocalUnbindTwice() throws Exception { 1408 EmptyConnection conn = new EmptyConnection(); 1409 mContext.bindService( 1410 mLocalService_ApplicationHasPermission, conn, 0); 1411 mContext.unbindService(conn); 1412 try { 1413 mContext.unbindService(conn); 1414 fail("No exception thrown on the second unbind"); 1415 } catch (IllegalArgumentException e) { 1416 // expected 1417 } 1418 } 1419 1420 @MediumTest testImplicitIntentFailsOnApiLevel21()1421 public void testImplicitIntentFailsOnApiLevel21() throws Exception { 1422 Intent intent = new Intent(LocalService.SERVICE_LOCAL); 1423 EmptyConnection conn = new EmptyConnection(); 1424 try { 1425 mContext.bindService(intent, conn, 0); 1426 mContext.unbindService(conn); 1427 fail("Implicit intents should be disallowed for apps targeting API 21+"); 1428 } catch (IllegalArgumentException e) { 1429 // expected 1430 } 1431 } 1432 1433 /** 1434 * Verify that when the requested service's onBind() returns null, 1435 * the connection's onNullBinding() method is invoked. 1436 */ 1437 @MediumTest testNullServiceBinder()1438 public void testNullServiceBinder() throws Exception { 1439 Intent intent = new Intent(mContext, NullService.class); 1440 intent.setAction("testNullServiceBinder"); 1441 NullServiceConnection conn1 = new NullServiceConnection(); 1442 NullServiceConnection conn2 = new NullServiceConnection(); 1443 try { 1444 assertTrue(mContext.bindService(intent, conn1, Context.BIND_AUTO_CREATE)); 1445 conn1.waitForNullBinding(DELAY); 1446 assertTrue(conn1.nullBindingReceived()); 1447 1448 assertTrue(mContext.bindService(intent, conn2, Context.BIND_AUTO_CREATE)); 1449 conn2.waitForNullBinding(DELAY); 1450 assertTrue(conn2.nullBindingReceived()); 1451 } finally { 1452 mContext.unbindService(conn1); 1453 mContext.unbindService(conn2); 1454 } 1455 } 1456 1457 /** 1458 * Verify that we can't use bindIsolatedService() on a non-isolated service. 1459 */ 1460 @MediumTest testFailBindNonIsolatedService()1461 public void testFailBindNonIsolatedService() throws Exception { 1462 EmptyConnection conn = new EmptyConnection(); 1463 try { 1464 mContext.bindIsolatedService(mLocalService, 0, "isolated", mContextMainExecutor, conn); 1465 mContext.unbindService(conn); 1466 fail("Didn't get IllegalArgumentException"); 1467 } catch (IllegalArgumentException e) { 1468 // This is expected. 1469 } 1470 } 1471 1472 /** 1473 * Verify that certain characters are prohibited in instanceName. 1474 */ testFailBindIsoaltedServiceWithInvalidInstanceName()1475 public void testFailBindIsoaltedServiceWithInvalidInstanceName() throws Exception { 1476 String[] badNames = { 1477 "t\rest", 1478 "test\n", 1479 "test-three", 1480 "test four", 1481 "escape\u00a9seq", 1482 "\u0164est", 1483 }; 1484 for (String instanceName : badNames) { 1485 EmptyConnection conn = new EmptyConnection(); 1486 try { 1487 mContext.bindIsolatedService(mIsolatedService, Context.BIND_AUTO_CREATE, 1488 instanceName, mContextMainExecutor, conn); 1489 mContext.unbindService(conn); 1490 fail("Didn't get IllegalArgumentException: " + instanceName); 1491 } catch (IllegalArgumentException e) { 1492 // This is expected. 1493 } 1494 } 1495 } 1496 1497 /** 1498 * Verify that bindIsolatedService() correctly makes different instances when given 1499 * different instance names. 1500 */ 1501 @MediumTest testBindIsolatedServiceInstances()1502 public void testBindIsolatedServiceInstances() throws Exception { 1503 IsolatedConnection conn1a = null; 1504 IsolatedConnection conn1b = null; 1505 IsolatedConnection conn2 = null; 1506 try { 1507 conn1a = new IsolatedConnection(); 1508 mContext.bindIsolatedService( 1509 mIsolatedService, Context.BIND_AUTO_CREATE, "1", mContextMainExecutor, conn1a); 1510 conn1b = new IsolatedConnection(); 1511 mContext.bindIsolatedService( 1512 mIsolatedService, Context.BIND_AUTO_CREATE, "1", mContextMainExecutor, conn1b); 1513 conn2 = new IsolatedConnection(); 1514 mContext.bindIsolatedService( 1515 mIsolatedService, Context.BIND_AUTO_CREATE, "2", mContextMainExecutor, conn2); 1516 1517 conn1a.waitForService(DELAY); 1518 conn1b.waitForService(DELAY); 1519 conn2.waitForService(DELAY); 1520 1521 if (conn1a.getPid() != conn1b.getPid()) { 1522 fail("Connections to same service name in different pids"); 1523 } 1524 if (conn1a.getPid() == conn2.getPid()) { 1525 fail("Connections to different service names in same pids"); 1526 } 1527 1528 conn1a.setValue(1); 1529 assertEquals(1, conn1a.getValue()); 1530 assertEquals(1, conn1b.getValue()); 1531 1532 conn2.setValue(2); 1533 assertEquals(1, conn1a.getValue()); 1534 assertEquals(1, conn1b.getValue()); 1535 assertEquals(2, conn2.getValue()); 1536 1537 conn1b.setValue(3); 1538 assertEquals(3, conn1a.getValue()); 1539 assertEquals(3, conn1b.getValue()); 1540 assertEquals(2, conn2.getValue()); 1541 } finally { 1542 if (conn2 != null) { 1543 mContext.unbindService(conn2); 1544 } 1545 if (conn1b != null) { 1546 mContext.unbindService(conn1b); 1547 } 1548 if (conn1a != null) { 1549 mContext.unbindService(conn1a); 1550 } 1551 } 1552 } 1553 testBindIsolatedServiceOnBackgroundThread()1554 public void testBindIsolatedServiceOnBackgroundThread() throws Exception { 1555 setupBackgroundThread(); 1556 IsolatedConnection conn = new IsolatedConnection(); 1557 mContext.bindIsolatedService(mIsolatedService, Context.BIND_AUTO_CREATE, 1558 "background_instance", mBackgroundThreadExecutor, conn); 1559 conn.waitForService(DELAY); 1560 assertEquals(mBackgroundThread, conn.getOnServiceConnectedThread()); 1561 mContext.unbindService(conn); 1562 } 1563 1564 static final int BINDING_WEAK = 0; 1565 static final int BINDING_STRONG = 1; 1566 static final int BINDING_ANY = -1; 1567 1568 final class IsolatedConnectionInfo { 1569 final int mStrong; 1570 final String mInstanceName; 1571 final String mLabel; 1572 int mGroup; 1573 int mImportance; 1574 IsolatedConnection mConnection; 1575 IsolatedConnectionInfo(int group, int importance, int strong)1576 IsolatedConnectionInfo(int group, int importance, int strong) { 1577 mGroup = group; 1578 mImportance = importance; 1579 mStrong = strong; 1580 mInstanceName = group + "_" + importance; 1581 StringBuilder b = new StringBuilder(mInstanceName); 1582 b.append('_'); 1583 if (strong == BINDING_WEAK) { 1584 b.append('W'); 1585 } else if (strong == BINDING_STRONG) { 1586 b.append('S'); 1587 } else { 1588 b.append(strong); 1589 } 1590 mLabel = b.toString(); 1591 } 1592 setGroup(int group)1593 void setGroup(int group) { 1594 mGroup = group; 1595 } 1596 setImportance(int importance)1597 void setImportance(int importance) { 1598 mImportance = importance; 1599 } 1600 match(int group, int strong)1601 boolean match(int group, int strong) { 1602 return (group < 0 || mGroup == group) 1603 && (strong == BINDING_ANY || mStrong == strong); 1604 } 1605 bind(Context context)1606 boolean bind(Context context) { 1607 if (mConnection != null) { 1608 return true; 1609 } 1610 Log.i("XXXXXXX", "Binding " + mLabel + ": conn=" + mConnection 1611 + " context=" + context); 1612 mConnection = new IsolatedConnection(); 1613 boolean result = context.bindIsolatedService( 1614 mIsolatedService, 1615 Context.BIND_AUTO_CREATE | Context.BIND_DEBUG_UNBIND 1616 | (mStrong == BINDING_STRONG ? 0 : Context.BIND_ALLOW_OOM_MANAGEMENT), 1617 mInstanceName, mContextMainExecutor, mConnection); 1618 if (!result) { 1619 mConnection = null; 1620 } 1621 return result; 1622 } 1623 getConnection()1624 IsolatedConnection getConnection() { 1625 return mConnection; 1626 } 1627 unbind(Context context)1628 void unbind(Context context) { 1629 if (mConnection != null) { 1630 Log.i("XXXXXXX", "Unbinding " + mLabel + ": conn=" + mConnection 1631 + " context=" + context); 1632 context.unbindService(mConnection); 1633 mConnection = null; 1634 } 1635 } 1636 } 1637 1638 final class LruOrderItem { 1639 static final int FLAG_SKIP_UNKNOWN = 1<<0; 1640 1641 final IsolatedConnectionInfo mInfo; 1642 final int mUid; 1643 final int mFlags; 1644 LruOrderItem(IsolatedConnectionInfo info, int flags)1645 LruOrderItem(IsolatedConnectionInfo info, int flags) { 1646 mInfo = info; 1647 mUid = -1; 1648 mFlags = flags; 1649 } 1650 LruOrderItem(int uid, int flags)1651 LruOrderItem(int uid, int flags) { 1652 mInfo = null; 1653 mUid = uid; 1654 mFlags = flags; 1655 } 1656 getInfo()1657 IsolatedConnectionInfo getInfo() { 1658 return mInfo; 1659 } 1660 getUid()1661 int getUid() { 1662 return mInfo != null ? mInfo.getConnection().getUid() : mUid; 1663 } 1664 getUserId()1665 int getUserId() { 1666 return UserHandle.getUserHandleForUid(getUid()).getIdentifier(); 1667 } 1668 getAppId()1669 int getAppId() { 1670 return UserHandle.getAppId(getUid()); 1671 } 1672 isEquivalentTo(ProcessRecordProto proc)1673 boolean isEquivalentTo(ProcessRecordProto proc) { 1674 int procAppId = proc.isolatedAppId != 0 ? proc.isolatedAppId : UserHandle.getAppId( 1675 proc.uid); 1676 1677 // Compare appid and userid separately because UserHandle.getUid is @hide. 1678 return procAppId == getAppId() && proc.userId == getUserId(); 1679 } 1680 getFlags()1681 int getFlags() { 1682 return mFlags; 1683 } 1684 } 1685 doBind(Context context, IsolatedConnectionInfo[] connections, int group, int strong)1686 private void doBind(Context context, IsolatedConnectionInfo[] connections, int group, 1687 int strong) { 1688 for (IsolatedConnectionInfo ci : connections) { 1689 if (ci.match(group, strong)) { 1690 ci.bind(context); 1691 } 1692 } 1693 } 1694 doBind(Context context, IsolatedConnectionInfo[] connections, int[] selected)1695 private void doBind(Context context, IsolatedConnectionInfo[] connections, int[] selected) { 1696 for (int i : selected) { 1697 boolean result = connections[i].bind(context); 1698 if (!result) { 1699 fail("Unable to bind connection " + connections[i].mLabel); 1700 } 1701 } 1702 } 1703 doWaitForService(IsolatedConnectionInfo[] connections, int group, int strong)1704 private void doWaitForService(IsolatedConnectionInfo[] connections, int group, 1705 int strong) { 1706 for (IsolatedConnectionInfo ci : connections) { 1707 if (ci.match(group, strong)) { 1708 ci.mConnection.waitForService(DELAY); 1709 } 1710 } 1711 } 1712 doUpdateServiceGroup(Context context, IsolatedConnectionInfo[] connections, int group, int strong)1713 private void doUpdateServiceGroup(Context context, IsolatedConnectionInfo[] connections, 1714 int group, int strong) { 1715 for (IsolatedConnectionInfo ci : connections) { 1716 if (ci.match(group, strong)) { 1717 context.updateServiceGroup(ci.mConnection, ci.mGroup, ci.mImportance); 1718 } 1719 } 1720 } 1721 doUnbind(Context context, IsolatedConnectionInfo[] connections, int group, int strong)1722 private void doUnbind(Context context, IsolatedConnectionInfo[] connections, int group, 1723 int strong) { 1724 for (IsolatedConnectionInfo ci : connections) { 1725 if (ci.match(group, strong)) { 1726 ci.unbind(context); 1727 } 1728 } 1729 } 1730 doUnbind(Context context, IsolatedConnectionInfo[] connections, int[] selected)1731 private void doUnbind(Context context, IsolatedConnectionInfo[] connections, int[] selected) { 1732 for (int i : selected) { 1733 connections[i].unbind(context); 1734 } 1735 } 1736 getLruProcesses()1737 List<ProcessRecordProto> getLruProcesses() { 1738 ActivityManagerServiceDumpProcessesProto dump = getActivityManagerProcesses(); 1739 SparseArray<ProcessRecordProto> procs = new SparseArray<>(); 1740 ProcessRecordProto[] procsList = dump.procs; 1741 for (ProcessRecordProto proc : procsList) { 1742 procs.put(proc.lruIndex, proc); 1743 } 1744 ArrayList<ProcessRecordProto> lruProcs = new ArrayList<>(); 1745 for (int i = 0; i < procs.size(); i++) { 1746 lruProcs.add(procs.valueAt(i)); 1747 } 1748 return lruProcs; 1749 } 1750 printProc(int i, ProcessRecordProto proc)1751 String printProc(int i, ProcessRecordProto proc) { 1752 return "#" + i + ": " + proc.processName 1753 + " pid=" + proc.pid + " uid=" + proc.uid 1754 + (proc.isolatedAppId != 0 ? " isolated=" + proc.isolatedAppId : ""); 1755 } 1756 logProc(int i, ProcessRecordProto proc)1757 private void logProc(int i, ProcessRecordProto proc) { 1758 Log.i("XXXXXXXX", printProc(i, proc)); 1759 } 1760 verifyLruOrder(LruOrderItem[] orderItems)1761 private void verifyLruOrder(LruOrderItem[] orderItems) { 1762 List<ProcessRecordProto> procs = getLruProcesses(); 1763 Log.i("XXXXXXXX", "Processes:"); 1764 int orderI = 0; 1765 for (int i = procs.size() - 1; i >= 0; i--) { 1766 ProcessRecordProto proc = procs.get(i); 1767 logProc(i, proc); 1768 final LruOrderItem lru = orderItems[orderI]; 1769 Log.i("XXXXXXXX", "Expecting uid: " + lru.getUid()); 1770 if (!lru.isEquivalentTo(proc)) { 1771 if ((lru.getFlags() & LruOrderItem.FLAG_SKIP_UNKNOWN) != 0) { 1772 while (i > 0) { 1773 i--; 1774 proc = procs.get(i); 1775 logProc(i, proc); 1776 if (lru.isEquivalentTo(proc)) { 1777 break; 1778 } 1779 } 1780 } 1781 if (!lru.isEquivalentTo(proc)) { 1782 if ((lru.getFlags() & LruOrderItem.FLAG_SKIP_UNKNOWN) != 0) { 1783 fail("Didn't find expected LRU proc uid=" + lru.getUid()); 1784 } 1785 fail("Expected proc uid=" + lru.getUid() + " at found proc " 1786 + printProc(i, proc)); 1787 } 1788 } 1789 orderI++; 1790 if (orderI >= orderItems.length) { 1791 return; 1792 } 1793 } 1794 } 1795 1796 @MediumTest testAppZygotePreload()1797 public void testAppZygotePreload() throws Exception { 1798 IsolatedConnection conn = new IsolatedConnection(); 1799 try { 1800 mContext.bindIsolatedService( 1801 mIsolatedService, Context.BIND_AUTO_CREATE, "1", mContextMainExecutor, conn); 1802 1803 conn.waitForService(DELAY); 1804 1805 // Verify application preload was done 1806 assertTrue(conn.zygotePreloadCalled()); 1807 } finally { 1808 if (conn != null) { 1809 mContext.unbindService(conn); 1810 } 1811 } 1812 } 1813 1814 @MediumTest testAppZygoteServices()1815 public void testAppZygoteServices() throws Exception { 1816 IsolatedConnection conn1a = null; 1817 IsolatedConnection conn1b = null; 1818 IsolatedConnection conn2 = null; 1819 int appZygotePid; 1820 try { 1821 conn1a = new IsolatedConnection(); 1822 mContext.bindIsolatedService( 1823 mIsolatedService, Context.BIND_AUTO_CREATE, "1", mContextMainExecutor, conn1a); 1824 conn1b = new IsolatedConnection(); 1825 mContext.bindIsolatedService( 1826 mIsolatedService, Context.BIND_AUTO_CREATE, "1", mContextMainExecutor, conn1b); 1827 conn2 = new IsolatedConnection(); 1828 mContext.bindIsolatedService( 1829 mIsolatedService, Context.BIND_AUTO_CREATE, "2", mContextMainExecutor, conn2); 1830 1831 conn1a.waitForService(DELAY); 1832 conn1b.waitForService(DELAY); 1833 conn2.waitForService(DELAY); 1834 1835 // Get PPID of each service, and verify they're identical 1836 int ppid1a = conn1a.getPpid(); 1837 int ppid1b = conn1b.getPpid(); 1838 int ppid2 = conn2.getPpid(); 1839 1840 assertEquals(ppid1a, ppid1b); 1841 assertEquals(ppid1b, ppid2); 1842 // Find the app zygote process hosting these 1843 String result = SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 1844 "ps -p " + Integer.toString(ppid1a) + " -o NAME="); 1845 result = result.replaceAll("\\s+", ""); 1846 assertEquals(result, APP_ZYGOTE_PROCESS_NAME); 1847 appZygotePid = ppid1a; 1848 } finally { 1849 if (conn2 != null) { 1850 mContext.unbindService(conn2); 1851 } 1852 if (conn1b != null) { 1853 mContext.unbindService(conn1b); 1854 } 1855 if (conn1a != null) { 1856 mContext.unbindService(conn1a); 1857 } 1858 } 1859 // Sleep for 2 seconds and bind a service again, see it uses the same Zygote 1860 try { 1861 conn1a = new IsolatedConnection(); 1862 mContext.bindIsolatedService( 1863 mIsolatedService, Context.BIND_AUTO_CREATE, "1", mContextMainExecutor, conn1a); 1864 1865 conn1a.waitForService(DELAY); 1866 1867 int ppid1a = conn1a.getPpid(); 1868 assertEquals(appZygotePid, ppid1a); 1869 } finally { 1870 if (conn1a != null) { 1871 mContext.unbindService(conn1a); 1872 } 1873 } 1874 // Sleep for 10 seconds, verify the app_zygote is gone 1875 Thread.sleep(10000); 1876 String result = SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 1877 "ps -p " + Integer.toString(appZygotePid) + " -o NAME="); 1878 result = result.replaceAll("\\s+", ""); 1879 assertEquals("", result); 1880 } 1881 1882 /** 1883 * Test that the system properly orders processes bound by an activity within the 1884 * LRU list. 1885 */ 1886 // TODO(b/131059432): Re-enable the test after that bug is fixed. 1887 @FlakyTest 1888 @MediumTest testActivityServiceBindingLru()1889 public void testActivityServiceBindingLru() throws Exception { 1890 // Bring up the activity we will hang services off of. 1891 runLaunchpad(LaunchpadActivity.ACTIVITY_PREPARE); 1892 1893 final Activity a = getRunningActivity(); 1894 1895 final int CONN_1_1_W = 0; 1896 final int CONN_1_1_S = 1; 1897 final int CONN_1_2_W = 2; 1898 final int CONN_1_2_S = 3; 1899 final int CONN_2_1_W = 4; 1900 final int CONN_2_1_S = 5; 1901 final int CONN_2_2_W = 6; 1902 final int CONN_2_2_S = 7; 1903 final int CONN_2_3_W = 8; 1904 final int CONN_2_3_S = 9; 1905 1906 // We are going to have both weak and strong references to services, so we can allow 1907 // some to go down in the LRU list. 1908 final IsolatedConnectionInfo[] connections = new IsolatedConnectionInfo[] { 1909 new IsolatedConnectionInfo(1, 1, BINDING_WEAK), 1910 new IsolatedConnectionInfo(1, 1, BINDING_STRONG), 1911 new IsolatedConnectionInfo(1, 2, BINDING_WEAK), 1912 new IsolatedConnectionInfo(1, 2, BINDING_STRONG), 1913 new IsolatedConnectionInfo(2, 1, BINDING_WEAK), 1914 new IsolatedConnectionInfo(2, 1, BINDING_STRONG), 1915 new IsolatedConnectionInfo(2, 2, BINDING_WEAK), 1916 new IsolatedConnectionInfo(2, 2, BINDING_STRONG), 1917 new IsolatedConnectionInfo(2, 3, BINDING_WEAK), 1918 new IsolatedConnectionInfo(2, 3, BINDING_STRONG), 1919 }; 1920 1921 final int[] REV_GROUP_1_STRONG = new int[] { 1922 CONN_1_2_S, CONN_1_1_S 1923 }; 1924 1925 final int[] REV_GROUP_2_STRONG = new int[] { 1926 CONN_2_3_S, CONN_2_2_S, CONN_2_1_S 1927 }; 1928 1929 final int[] MIXED_GROUP_3_STRONG = new int[] { 1930 CONN_2_3_S, CONN_1_1_S, CONN_2_1_S, CONN_2_2_S 1931 }; 1932 1933 boolean passed = false; 1934 1935 try { 1936 // Start the group 1 processes as weak. 1937 doBind(a, connections, 1, BINDING_WEAK); 1938 doUpdateServiceGroup(a, connections, 1, BINDING_WEAK); 1939 1940 // Wait for them to come up. 1941 doWaitForService(connections, 1, BINDING_WEAK); 1942 1943 // Now fully bind to the services. 1944 doBind(a, connections, 1, BINDING_STRONG); 1945 doWaitForService(connections, 1, BINDING_STRONG); 1946 1947 verifyLruOrder(new LruOrderItem[] { 1948 new LruOrderItem(Process.myUid(), 0), 1949 new LruOrderItem(connections[CONN_1_1_W], 0), 1950 new LruOrderItem(connections[CONN_1_2_W], 0), 1951 }); 1952 1953 // Now remove the full binding, leaving only the weak. 1954 doUnbind(a, connections, 1, BINDING_STRONG); 1955 1956 // Start the group 2 processes as weak. 1957 doBind(a, connections, 2, BINDING_WEAK); 1958 1959 // Wait for them to come up. 1960 doWaitForService(connections, 2, BINDING_WEAK); 1961 1962 // Set the group and index. In this case we do it after we know the process 1963 // is started, to make sure setting it directly works. 1964 doUpdateServiceGroup(a, connections, 2, BINDING_WEAK); 1965 1966 // Now fully bind to group 2 1967 doBind(a, connections, REV_GROUP_2_STRONG); 1968 1969 verifyLruOrder(new LruOrderItem[] { 1970 new LruOrderItem(Process.myUid(), 0), 1971 new LruOrderItem(connections[CONN_2_1_W], 0), 1972 new LruOrderItem(connections[CONN_2_2_W], 0), 1973 new LruOrderItem(connections[CONN_2_3_W], 0), 1974 new LruOrderItem(connections[CONN_1_1_W], LruOrderItem.FLAG_SKIP_UNKNOWN), 1975 new LruOrderItem(connections[CONN_1_2_W], 0), 1976 }); 1977 1978 // Bring group 1 back to the foreground, but in the opposite order. 1979 doBind(a, connections, REV_GROUP_1_STRONG); 1980 1981 verifyLruOrder(new LruOrderItem[] { 1982 new LruOrderItem(Process.myUid(), 0), 1983 new LruOrderItem(connections[CONN_1_1_W], 0), 1984 new LruOrderItem(connections[CONN_1_2_W], 0), 1985 new LruOrderItem(connections[CONN_2_1_W], LruOrderItem.FLAG_SKIP_UNKNOWN), 1986 new LruOrderItem(connections[CONN_2_2_W], 0), 1987 new LruOrderItem(connections[CONN_2_3_W], 0), 1988 }); 1989 1990 // Now remove all full bindings, keeping only weak. 1991 doUnbind(a, connections, 1, BINDING_STRONG); 1992 doUnbind(a, connections, 2, BINDING_STRONG); 1993 1994 // Change the grouping and importance to make sure that gets reflected. 1995 connections[CONN_1_1_W].setGroup(3); 1996 connections[CONN_1_1_W].setImportance(1); 1997 connections[CONN_2_1_W].setGroup(3); 1998 connections[CONN_2_1_W].setImportance(2); 1999 connections[CONN_2_2_W].setGroup(3); 2000 connections[CONN_2_2_W].setImportance(3); 2001 connections[CONN_2_3_W].setGroup(3); 2002 connections[CONN_2_3_W].setImportance(4); 2003 2004 doUpdateServiceGroup(a, connections, 3, BINDING_WEAK); 2005 2006 // Now bind them back up in an interesting order. 2007 doBind(a, connections, MIXED_GROUP_3_STRONG); 2008 2009 verifyLruOrder(new LruOrderItem[] { 2010 new LruOrderItem(Process.myUid(), 0), 2011 new LruOrderItem(connections[CONN_1_1_W], 0), 2012 new LruOrderItem(connections[CONN_2_1_W], 0), 2013 new LruOrderItem(connections[CONN_2_2_W], 0), 2014 new LruOrderItem(connections[CONN_2_3_W], 0), 2015 new LruOrderItem(connections[CONN_1_2_W], LruOrderItem.FLAG_SKIP_UNKNOWN), 2016 }); 2017 2018 passed = true; 2019 2020 } finally { 2021 if (!passed) { 2022 List<ProcessRecordProto> procs = getLruProcesses(); 2023 Log.i("XXXXXXXX", "Processes:"); 2024 for (int i = procs.size() - 1; i >= 0; i--) { 2025 ProcessRecordProto proc = procs.get(i); 2026 logProc(i, proc); 2027 } 2028 } 2029 doUnbind(a, connections, -1, BINDING_ANY); 2030 } 2031 } 2032 } 2033