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