1 /*
2  * Copyright (C) 2017 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 android.Manifest;
20 import android.accessibilityservice.AccessibilityService;
21 import android.app.Activity;
22 import android.app.ActivityManager;
23 import android.app.AppOpsManager;
24 import android.app.Instrumentation;
25 import android.app.KeyguardManager;
26 import android.app.cts.android.app.cts.tools.ServiceConnectionHandler;
27 import android.app.cts.android.app.cts.tools.ServiceProcessController;
28 import android.app.cts.android.app.cts.tools.SyncOrderedBroadcast;
29 import android.app.cts.android.app.cts.tools.UidImportanceListener;
30 import android.app.cts.android.app.cts.tools.WaitForBroadcast;
31 import android.app.cts.android.app.cts.tools.WatchUidRunner;
32 import android.content.ComponentName;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.pm.ApplicationInfo;
36 import android.content.pm.PackageManager;
37 import android.content.res.Configuration;
38 import android.os.IBinder;
39 import android.os.Parcel;
40 import android.os.PowerManager;
41 import android.os.RemoteException;
42 import android.os.SystemClock;
43 import android.server.am.WindowManagerState;
44 import android.support.test.InstrumentationRegistry;
45 import android.support.test.uiautomator.BySelector;
46 import android.support.test.uiautomator.UiDevice;
47 import android.support.test.uiautomator.UiSelector;
48 import android.test.InstrumentationTestCase;
49 import android.util.Log;
50 import android.view.accessibility.AccessibilityEvent;
51 
52 import com.android.compatibility.common.util.SystemUtil;
53 
54 public class ActivityManagerProcessStateTest extends InstrumentationTestCase {
55     private static final String TAG = ActivityManagerProcessStateTest.class.getName();
56 
57     private static final String STUB_PACKAGE_NAME = "android.app.stubs";
58     private static final int WAIT_TIME = 2000;
59     // A secondary test activity from another APK.
60     static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
61     static final String SIMPLE_SERVICE = ".SimpleService";
62     static final String SIMPLE_SERVICE2 = ".SimpleService2";
63     static final String SIMPLE_RECEIVER_START_SERVICE = ".SimpleReceiverStartService";
64     static final String SIMPLE_ACTIVITY_START_SERVICE = ".SimpleActivityStartService";
65     public static String ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT =
66             "com.android.cts.launcherapps.simpleapp.SimpleActivityStartService.RESULT";
67 
68     // APKs for testing heavy weight app interactions.
69     static final String CANT_SAVE_STATE_1_PACKAGE_NAME = "com.android.test.cantsavestate1";
70     static final String CANT_SAVE_STATE_2_PACKAGE_NAME = "com.android.test.cantsavestate2";
71 
72     // Actions
73     static final String ACTION_START_FOREGROUND = "com.android.test.action.START_FOREGROUND";
74     static final String ACTION_STOP_FOREGROUND = "com.android.test.action.STOP_FOREGROUND";
75 
76     private static final int TEMP_WHITELIST_DURATION_MS = 2000;
77 
78     private Context mContext;
79     private Instrumentation mInstrumentation;
80     private Intent mServiceIntent;
81     private Intent mServiceStartForegroundIntent;
82     private Intent mServiceStopForegroundIntent;
83     private Intent mService2Intent;
84     private Intent mMainProcess[];
85     private Intent mAllProcesses[];
86 
87     @Override
setUp()88     protected void setUp() throws Exception {
89         super.setUp();
90         mInstrumentation = getInstrumentation();
91         mContext = mInstrumentation.getContext();
92         mServiceIntent = new Intent();
93         mServiceIntent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE);
94         mServiceStartForegroundIntent = new Intent(mServiceIntent);
95         mServiceStartForegroundIntent.setAction(ACTION_START_FOREGROUND);
96         mServiceStopForegroundIntent = new Intent(mServiceIntent);
97         mServiceStopForegroundIntent.setAction(ACTION_STOP_FOREGROUND);
98         mService2Intent = new Intent();
99         mService2Intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE2);
100         mMainProcess = new Intent[1];
101         mMainProcess[0] = mServiceIntent;
102         mAllProcesses = new Intent[2];
103         mAllProcesses[0] = mServiceIntent;
104         mAllProcesses[1] = mService2Intent;
105         mContext.stopService(mServiceIntent);
106         mContext.stopService(mService2Intent);
107         removeTestAppFromWhitelists();
108     }
109 
removeTestAppFromWhitelists()110     private void removeTestAppFromWhitelists() throws Exception {
111         executeShellCmd("cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME);
112         executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
113     }
114 
executeShellCmd(String cmd)115     private String executeShellCmd(String cmd) throws Exception {
116         final String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
117         Log.d(TAG, String.format("Output for '%s': %s", cmd, result));
118         return result;
119     }
120 
isScreenInteractive()121     private boolean isScreenInteractive() {
122         final PowerManager powerManager =
123                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
124         return powerManager.isInteractive();
125     }
126 
isKeyguardLocked()127     private boolean isKeyguardLocked() {
128         final KeyguardManager keyguardManager =
129                 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
130         return keyguardManager.isKeyguardLocked();
131     }
132 
waitForAppFocus(String waitForApp, long waitTime)133     private void waitForAppFocus(String waitForApp, long waitTime) {
134         long waitUntil = SystemClock.elapsedRealtime() + waitTime;
135         while (true) {
136             WindowManagerState wms = new WindowManagerState();
137             wms.computeState();
138             String appName = wms.getFocusedApp();
139             if (appName != null) {
140                 ComponentName comp = ComponentName.unflattenFromString(appName);
141                 if (waitForApp.equals(comp.getPackageName())) {
142                     break;
143                 }
144             }
145             if (SystemClock.elapsedRealtime() > waitUntil) {
146                 throw new IllegalStateException("Timed out waiting for focus on app "
147                         + waitForApp + ", last was " + appName);
148             }
149             Log.i(TAG, "Waiting for app focus, current: " + appName);
150             try {
151                 Thread.sleep(100);
152             } catch (InterruptedException e) {
153             }
154         };
155     }
156 
startActivityAndWaitForShow(final Intent intent)157     private void startActivityAndWaitForShow(final Intent intent) throws Exception {
158         getInstrumentation().getUiAutomation().executeAndWaitForEvent(
159                 () -> {
160                     try {
161                         mContext.startActivity(intent);
162                     } catch (Exception e) {
163                         fail("Cannot start activity: " + intent);
164                     }
165                 }, (AccessibilityEvent event) -> event.getEventType()
166                         == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
167                 , WAIT_TIME);
168     }
169 
maybeClick(UiDevice device, UiSelector sel)170     private void maybeClick(UiDevice device, UiSelector sel) {
171         try { device.findObject(sel).click(); } catch (Throwable ignored) { }
172     }
173 
maybeClick(UiDevice device, BySelector sel)174     private void maybeClick(UiDevice device, BySelector sel) {
175         try { device.findObject(sel).click(); } catch (Throwable ignored) { }
176     }
177 
178     /**
179      * Test basic state changes as processes go up and down due to services running in them.
180      */
testUidImportanceListener()181     public void testUidImportanceListener() throws Exception {
182         final Parcel data = Parcel.obtain();
183         ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent,
184                 WAIT_TIME);
185         ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent,
186                 WAIT_TIME);
187 
188         ActivityManager am = mContext.getSystemService(ActivityManager.class);
189 
190         ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
191                 SIMPLE_PACKAGE_NAME, 0);
192         UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
193                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);
194 
195         InstrumentationRegistry.getInstrumentation().getUiAutomation().revokeRuntimePermission(
196                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
197         boolean gotException = false;
198         try {
199             uidForegroundListener.register();
200         } catch (SecurityException e) {
201             gotException = true;
202         }
203         assertTrue("Expected SecurityException thrown", gotException);
204 
205         InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
206                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
207         /*
208         Log.d("XXXX", "Invoke: " + cmd);
209         Log.d("XXXX", "Result: " + result);
210         Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
211                 + STUB_PACKAGE_NAME));
212         */
213         uidForegroundListener.register();
214 
215         UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
216                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, WAIT_TIME);
217         uidGoneListener.register();
218 
219         WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
220                 WAIT_TIME);
221 
222         try {
223             // First kill the processes to start out in a stable state.
224             conn.bind();
225             conn2.bind();
226             IBinder service1 = conn.getServiceIBinder();
227             IBinder service2 = conn2.getServiceIBinder();
228             conn.unbind();
229             conn2.unbind();
230             try {
231                 service1.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
232             } catch (RemoteException e) {
233             }
234             try {
235                 service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
236             } catch (RemoteException e) {
237             }
238             service1 = service2 = null;
239 
240             // Wait for uid's processes to go away.
241             uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
242                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
243             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
244                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
245 
246             // And wait for the uid report to be gone.
247             uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null);
248 
249             // Now bind and see if we get told about the uid coming in to the foreground.
250             conn.bind();
251             uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
252                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE);
253             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
254                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
255 
256             // Also make sure the uid state reports are as expected.  Wait for active because
257             // there may be some intermediate states as the process comes up.
258             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
259             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
260             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
261 
262             // Pull out the service IBinder for a kludy hack...
263             IBinder service = conn.getServiceIBinder();
264 
265             // Now unbind and see if we get told about it going to the background.
266             conn.unbind();
267             uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
268                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
269             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
270                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
271 
272             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
273             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
274 
275             // Now kill the process and see if we are told about it being gone.
276             try {
277                 service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
278             } catch (RemoteException e) {
279                 // It is okay if it is already gone for some reason.
280             }
281 
282             uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
283                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
284             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
285                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
286 
287             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
288             uidWatcher.expect(WatchUidRunner.CMD_GONE, null);
289 
290             // Now we are going to try different combinations of binding to two processes to
291             // see if they are correctly combined together for the app.
292 
293             // Bring up both services.
294             conn.bind();
295             conn2.bind();
296             uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
297                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE);
298             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
299                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
300 
301             // Also make sure the uid state reports are as expected.
302             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
303             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
304             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
305 
306             // Bring down one service, app state should remain foreground.
307             conn2.unbind();
308             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
309                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
310 
311             // Bring down other service, app state should now be cached.  (If the processes both
312             // actually get killed immediately, this is also not a correctly behaving system.)
313             conn.unbind();
314             uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
315                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
316             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
317                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
318 
319             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
320             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
321 
322             // Bring up one service, this should be sufficient to become foreground.
323             conn2.bind();
324             uidForegroundListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
325                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE);
326             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
327                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
328 
329             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
330             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
331 
332             // Bring up other service, should remain foreground.
333             conn.bind();
334             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
335                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
336 
337             // Bring down one service, should remain foreground.
338             conn.unbind();
339             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
340                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
341 
342             // And bringing down other service should put us back to cached.
343             conn2.unbind();
344             uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
345                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
346             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
347                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
348 
349             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
350             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
351         } finally {
352             data.recycle();
353             uidWatcher.finish();
354             uidForegroundListener.unregister();
355             uidGoneListener.unregister();
356         }
357     }
358 
359     /**
360      * Test that background check correctly prevents idle services from running but allows
361      * whitelisted apps to bypass the check.
362      */
testBackgroundCheckService()363     public void testBackgroundCheckService() throws Exception {
364         final Parcel data = Parcel.obtain();
365         Intent serviceIntent = new Intent();
366         serviceIntent.setClassName(SIMPLE_PACKAGE_NAME,
367                 SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE);
368         ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, serviceIntent,
369                 WAIT_TIME);
370 
371         ActivityManager am = mContext.getSystemService(ActivityManager.class);
372 
373         InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
374                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
375         /*
376         Log.d("XXXX", "Invoke: " + cmd);
377         Log.d("XXXX", "Result: " + result);
378         Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
379                 + STUB_PACKAGE_NAME));
380         */
381 
382         ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
383                 SIMPLE_PACKAGE_NAME, 0);
384 
385         UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
386                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);
387         uidForegroundListener.register();
388         UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
389                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY, WAIT_TIME);
390         uidGoneListener.register();
391 
392         WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
393                 WAIT_TIME);
394 
395         // First kill the process to start out in a stable state.
396         mContext.stopService(serviceIntent);
397         conn.bind();
398         IBinder service = conn.getServiceIBinder();
399         conn.unbind();
400         try {
401             service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
402         } catch (RemoteException e) {
403         }
404         service = null;
405 
406         // Wait for uid's process to go away.
407         uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
408                 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
409         assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
410                 am.getPackageImportance(SIMPLE_PACKAGE_NAME));
411 
412         // And wait for the uid report to be gone.
413         uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null);
414 
415         String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
416         String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
417 
418         // This is a side-effect of the app op command.
419         uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
420         uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "NONE");
421 
422         // We don't want to wait for the uid to actually go idle, we can force it now.
423         cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
424         result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
425 
426         // Make sure app is not yet on whitelist
427         cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
428         result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
429 
430         // We will use this to monitor when the service is running.
431         conn.startMonitoring();
432 
433         try {
434             // Try starting the service.  Should fail!
435             boolean failed = false;
436             try {
437                 mContext.startService(serviceIntent);
438             } catch (IllegalStateException e) {
439                 failed = true;
440             }
441             if (!failed) {
442                 fail("Service was allowed to start while in the background");
443             }
444 
445             // Put app on temporary whitelist to see if this allows the service start.
446             cmd = String.format("cmd deviceidle tempwhitelist -d %d %s",
447                     TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME);
448             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
449 
450             // Try starting the service now that the app is whitelisted...  should work!
451             mContext.startService(serviceIntent);
452             conn.waitForConnect();
453 
454             // Also make sure the uid state reports are as expected.
455             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
456             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
457             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
458 
459             // Good, now stop the service and give enough time to get off the temp whitelist.
460             mContext.stopService(serviceIntent);
461             conn.waitForDisconnect();
462 
463             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
464             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
465 
466             executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
467 
468             // Going off the temp whitelist causes a spurious proc state report...  that's
469             // not ideal, but okay.
470             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
471 
472             // We don't want to wait for the uid to actually go idle, we can force it now.
473             cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
474             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
475 
476             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
477             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
478 
479             // Now that we should be off the temp whitelist, make sure we again can't start.
480             failed = false;
481             try {
482                 mContext.startService(serviceIntent);
483             } catch (IllegalStateException e) {
484                 failed = true;
485             }
486             if (!failed) {
487                 fail("Service was allowed to start while in the background");
488             }
489 
490             // Now put app on whitelist, should allow service to run.
491             cmd = "cmd deviceidle whitelist +" + SIMPLE_PACKAGE_NAME;
492             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
493 
494             // Try starting the service now that the app is whitelisted...  should work!
495             mContext.startService(serviceIntent);
496             conn.waitForConnect();
497 
498             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
499             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
500 
501             // Okay, bring down the service.
502             mContext.stopService(serviceIntent);
503             conn.waitForDisconnect();
504 
505             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
506             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
507 
508         } finally {
509             mContext.stopService(serviceIntent);
510             conn.stopMonitoring();
511 
512             uidWatcher.finish();
513 
514             cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
515             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
516             cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
517             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
518 
519             uidGoneListener.unregister();
520             uidForegroundListener.unregister();
521 
522             data.recycle();
523         }
524     }
525 
526     /**
527      * Test that background check behaves correctly after a process is no longer foreground:
528      * first allowing a service to be started, then stopped by the system when idle.
529      */
testBackgroundCheckStopsService()530     public void testBackgroundCheckStopsService() throws Exception {
531         final Parcel data = Parcel.obtain();
532         ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent,
533                 WAIT_TIME);
534         ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent,
535                 WAIT_TIME);
536 
537         ActivityManager am = mContext.getSystemService(ActivityManager.class);
538 
539         InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
540                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
541         /*
542         Log.d("XXXX", "Invoke: " + cmd);
543         Log.d("XXXX", "Result: " + result);
544         Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
545                 + STUB_PACKAGE_NAME));
546         */
547 
548         ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
549                 SIMPLE_PACKAGE_NAME, 0);
550 
551         UidImportanceListener uidServiceListener = new UidImportanceListener(mContext,
552                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);
553         uidServiceListener.register();
554         UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
555                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED, WAIT_TIME);
556         uidGoneListener.register();
557 
558         WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
559                 WAIT_TIME);
560 
561         // First kill the process to start out in a stable state.
562         mContext.stopService(mServiceIntent);
563         mContext.stopService(mService2Intent);
564         conn.bind();
565         conn2.bind();
566         IBinder service = conn.getServiceIBinder();
567         IBinder service2 = conn2.getServiceIBinder();
568         conn.unbind();
569         conn2.unbind();
570         try {
571             service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
572         } catch (RemoteException e) {
573         }
574         try {
575             service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
576         } catch (RemoteException e) {
577         }
578         service = service2 = null;
579 
580         // Wait for uid's process to go away.
581         uidGoneListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
582                 ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
583         assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE,
584                 am.getPackageImportance(SIMPLE_PACKAGE_NAME));
585 
586         // And wait for the uid report to be gone.
587         uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null, WAIT_TIME);
588 
589         String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
590         String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
591 
592         // This is a side-effect of the app op command.
593         uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
594         uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_NONEXISTENT);
595 
596         // We don't want to wait for the uid to actually go idle, we can force it now.
597         cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
598         result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
599 
600         // Make sure app is not yet on whitelist
601         cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
602         result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
603 
604         // We will use this to monitor when the service is running.
605         conn.startMonitoring();
606 
607         try {
608             // Try starting the service.  Should fail!
609             boolean failed = false;
610             try {
611                 mContext.startService(mServiceIntent);
612             } catch (IllegalStateException e) {
613                 failed = true;
614             }
615             if (!failed) {
616                 fail("Service was allowed to start while in the background");
617             }
618 
619             // First poke the process into the foreground, so we can avoid background check.
620             conn2.bind();
621             conn2.waitForConnect();
622 
623             // Wait for process state to reflect running service.
624             uidServiceListener.waitForValue(
625                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
626                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
627             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
628                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
629 
630             // Also make sure the uid state reports are as expected.
631             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
632             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
633             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
634 
635             conn2.unbind();
636 
637             // Wait for process to recover back down to being cached.
638             uidServiceListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
639                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
640             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
641                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
642 
643             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
644             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
645 
646             // Try starting the service now that the app is waiting to idle...  should work!
647             mContext.startService(mServiceIntent);
648             conn.waitForConnect();
649 
650             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
651             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
652 
653             // And also start the second service.
654             conn2.startMonitoring();
655             mContext.startService(mService2Intent);
656             conn2.waitForConnect();
657 
658             // Force app to go idle now
659             cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
660             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
661 
662             // Wait for services to be stopped by system.
663             uidServiceListener.waitForValue(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
664                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
665             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
666                     am.getPackageImportance(SIMPLE_PACKAGE_NAME));
667 
668             // And service should be stopped by system, so just make sure it is disconnected.
669             conn.waitForDisconnect();
670             conn2.waitForDisconnect();
671 
672             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
673             // There may be a transient 'SVC' proc state here.
674             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
675             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
676 
677         } finally {
678             mContext.stopService(mServiceIntent);
679             mContext.stopService(mService2Intent);
680             conn.cleanup();
681             conn2.cleanup();
682 
683             uidWatcher.finish();
684 
685             cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
686             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
687             cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
688             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
689 
690             uidGoneListener.unregister();
691             uidServiceListener.unregister();
692 
693             data.recycle();
694         }
695     }
696 
697     /**
698      * Test the background check doesn't allow services to be started from broadcasts except
699      * when in the correct states.
700      */
testBackgroundCheckBroadcastService()701     public void testBackgroundCheckBroadcastService() throws Exception {
702         final Intent broadcastIntent = new Intent();
703         broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
704         broadcastIntent.setClassName(SIMPLE_PACKAGE_NAME,
705                 SIMPLE_PACKAGE_NAME + SIMPLE_RECEIVER_START_SERVICE);
706 
707         final ServiceProcessController controller = new ServiceProcessController(mContext,
708                 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
709         final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
710                 mServiceIntent, WAIT_TIME);
711         final WatchUidRunner uidWatcher = controller.getUidWatcher();
712 
713         try {
714             // First kill the process to start out in a stable state.
715             controller.ensureProcessGone();
716 
717             // Do initial setup.
718             controller.denyBackgroundOp();
719             controller.makeUidIdle();
720             controller.removeFromWhitelist();
721 
722             // We will use this to monitor when the service is running.
723             conn.startMonitoring();
724 
725             // Try sending broadcast to start the service.  Should fail!
726             SyncOrderedBroadcast br = new SyncOrderedBroadcast();
727             broadcastIntent.putExtra("service", mServiceIntent);
728             br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
729             int brCode = br.getReceivedCode();
730             if (brCode != Activity.RESULT_CANCELED) {
731                 fail("Didn't fail starting service, result=" + brCode);
732             }
733 
734             // Track the uid proc state changes from the broadcast (but not service execution)
735             uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null, WAIT_TIME);
736             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
737             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER, WAIT_TIME);
738             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME);
739             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME);
740 
741             // Put app on temporary whitelist to see if this allows the service start.
742             controller.tempWhitelist(TEMP_WHITELIST_DURATION_MS);
743 
744             // Being on the whitelist means the uid is now active.
745             uidWatcher.expect(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
746             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY, WAIT_TIME);
747 
748             // Try starting the service now that the app is whitelisted...  should work!
749             br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
750             brCode = br.getReceivedCode();
751             if (brCode != Activity.RESULT_FIRST_USER) {
752                 fail("Failed starting service, result=" + brCode);
753             }
754             conn.waitForConnect();
755 
756             // Also make sure the uid state reports are as expected.
757             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
758             // We are going to wait until 'SVC', because we may see an intermediate 'RCVR'
759             // proc state depending on timing.
760             uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
761 
762             // Good, now stop the service and give enough time to get off the temp whitelist.
763             mContext.stopService(mServiceIntent);
764             conn.waitForDisconnect();
765 
766             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
767             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
768 
769             controller.removeFromTempWhitelist();
770 
771             // Going off the temp whitelist causes a spurious proc state report...  that's
772             // not ideal, but okay.
773             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
774 
775             // We don't want to wait for the uid to actually go idle, we can force it now.
776             controller.makeUidIdle();
777 
778             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
779 
780             // Make sure the process is gone so we start over fresh.
781             controller.ensureProcessGone();
782 
783             // Now that we should be off the temp whitelist, make sure we again can't start.
784             br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
785             brCode = br.getReceivedCode();
786             if (brCode != Activity.RESULT_CANCELED) {
787                 fail("Didn't fail starting service, result=" + brCode);
788             }
789 
790             // Track the uid proc state changes from the broadcast (but not service execution)
791             uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null);
792             // There could be a transient 'cached' state here before 'uncached' if uid state
793             // changes are dispatched before receiver is started.
794             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
795             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER);
796             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
797             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
798 
799             // Now put app on whitelist, should allow service to run.
800             controller.addToWhitelist();
801 
802             // Try starting the service now that the app is whitelisted...  should work!
803             br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
804             brCode = br.getReceivedCode();
805             if (brCode != Activity.RESULT_FIRST_USER) {
806                 fail("Failed starting service, result=" + brCode);
807             }
808             conn.waitForConnect();
809 
810             // Also make sure the uid state reports are as expected.
811             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
812             uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
813 
814             // Okay, bring down the service.
815             mContext.stopService(mServiceIntent);
816             conn.waitForDisconnect();
817 
818             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
819             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
820 
821         } finally {
822             mContext.stopService(mServiceIntent);
823             conn.stopMonitoringIfNeeded();
824             controller.cleanup();
825         }
826     }
827 
828     /**
829      * Test that background check does allow services to be started from activities.
830      */
testBackgroundCheckActivityService()831     public void testBackgroundCheckActivityService() throws Exception {
832         final Intent activityIntent = new Intent();
833         activityIntent.setClassName(SIMPLE_PACKAGE_NAME,
834                 SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_START_SERVICE);
835         activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
836 
837         final ServiceProcessController controller = new ServiceProcessController(mContext,
838                 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
839         final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
840                 mServiceIntent, WAIT_TIME);
841         final WatchUidRunner uidWatcher = controller.getUidWatcher();
842 
843         try {
844             // First kill the process to start out in a stable state.
845             controller.ensureProcessGone();
846 
847             // Do initial setup.
848             controller.denyBackgroundOp();
849             controller.makeUidIdle();
850             controller.removeFromWhitelist();
851 
852             // We will use this to monitor when the service is running.
853             conn.startMonitoring();
854 
855             // Try starting activity that will start the service.  This should be okay.
856             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
857             waiter.prepare(ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT);
858             activityIntent.putExtra("service", mServiceIntent);
859             mContext.startActivity(activityIntent);
860             Intent resultIntent = waiter.doWait(WAIT_TIME);
861             int brCode = resultIntent.getIntExtra("result", Activity.RESULT_CANCELED);
862             if (brCode != Activity.RESULT_FIRST_USER) {
863                 fail("Failed starting service, result=" + brCode);
864             }
865             conn.waitForConnect();
866 
867             final String expectedActivityState = (isScreenInteractive() && !isKeyguardLocked())
868                     ? WatchUidRunner.STATE_TOP : WatchUidRunner.STATE_TOP_SLEEPING;
869             // Also make sure the uid state reports are as expected.
870             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
871             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
872             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, expectedActivityState);
873             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
874 
875             // Okay, bring down the service.
876             mContext.stopService(mServiceIntent);
877             conn.waitForDisconnect();
878 
879             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
880             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
881 
882             // App isn't yet idle, so we should be able to start the service again.
883             mContext.startService(mServiceIntent);
884             conn.waitForConnect();
885             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
886             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
887 
888             // And now fast-forward to the app going idle, service should be stopped.
889             controller.makeUidIdle();
890             uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null);
891 
892             conn.waitForDisconnect();
893             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
894             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
895 
896             // No longer should be able to start service.
897             boolean failed = false;
898             try {
899                 mContext.startService(mServiceIntent);
900             } catch (IllegalStateException e) {
901                 failed = true;
902             }
903             if (!failed) {
904                 fail("Service was allowed to start while in the background");
905             }
906 
907         } finally {
908             mContext.stopService(mServiceIntent);
909             conn.stopMonitoringIfNeeded();
910             controller.cleanup();
911         }
912     }
913 
914     /**
915      * Test that the foreground service app op does prevent the foreground state.
916      */
testForegroundServiceAppOp()917     public void testForegroundServiceAppOp() throws Exception {
918         final ServiceProcessController controller = new ServiceProcessController(mContext,
919                 getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
920         final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
921                 mServiceIntent, WAIT_TIME);
922         final WatchUidRunner uidWatcher = controller.getUidWatcher();
923 
924         try {
925             // First kill the process to start out in a stable state.
926             controller.ensureProcessGone();
927 
928             // Do initial setup.
929             controller.makeUidIdle();
930             controller.removeFromWhitelist();
931             controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");
932 
933             // Put app on whitelist, to allow service to run.
934             controller.addToWhitelist();
935 
936             // We will use this to monitor when the service is running.
937             conn.startMonitoring();
938 
939             // -------- START SERVICE AND THEN SUCCESSFULLY GO TO FOREGROUND
940 
941             // Now start the service and wait for it to come up.
942             mContext.startService(mServiceStartForegroundIntent);
943             conn.waitForConnect();
944 
945             // Also make sure the uid state reports are as expected.
946             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
947             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
948             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
949             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
950 
951             // Now take it out of foreground and confirm.
952             mContext.startService(mServiceStopForegroundIntent);
953             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
954 
955             // Good, now stop the service and wait for it to go away.
956             mContext.stopService(mServiceStartForegroundIntent);
957             conn.waitForDisconnect();
958 
959             // There may be a transient STATE_SERVICE we don't care about, so waitFor.
960             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
961             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
962 
963             // We don't want to wait for the uid to actually go idle, we can force it now.
964             controller.makeUidIdle();
965             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
966 
967             // Make sure the process is gone so we start over fresh.
968             controller.ensureProcessGone();
969 
970             // -------- START SERVICE AND BLOCK GOING TO FOREGROUND
971 
972             // Now we will deny the app op and ensure the service can't become foreground.
973             controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore");
974 
975             // Now start the service and wait for it to come up.
976             mContext.startService(mServiceStartForegroundIntent);
977             conn.waitForConnect();
978 
979             // Also make sure the uid state reports are as expected.
980             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
981             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
982 
983             // Good, now stop the service and wait for it to go away.
984             mContext.stopService(mServiceStartForegroundIntent);
985             conn.waitForDisconnect();
986 
987             // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE.
988             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
989             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
990 
991             // Make sure the uid is idle (it should be anyway, it never went active here).
992             controller.makeUidIdle();
993 
994             // Make sure the process is gone so we start over fresh.
995             controller.ensureProcessGone();
996 
997             // -------- DIRECT START FOREGROUND SERVICE SUCCESSFULLY
998 
999             controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");
1000 
1001             // Now start the service and wait for it to come up.
1002             mContext.startForegroundService(mServiceStartForegroundIntent);
1003             conn.waitForConnect();
1004 
1005             // Make sure it becomes a foreground service.  The process state changes here
1006             // are weird looking because we first need to force the app out of idle to allow
1007             // it to start the service.
1008             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
1009             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1010             uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1011 
1012             // Good, now stop the service and wait for it to go away.
1013             mContext.stopService(mServiceStartForegroundIntent);
1014             conn.waitForDisconnect();
1015 
1016             // There may be a transient STATE_SERVICE we don't care about, so waitFor.
1017             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1018             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1019 
1020             // We don't want to wait for the uid to actually go idle, we can force it now.
1021             controller.makeUidIdle();
1022             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
1023 
1024             // Make sure the process is gone so we start over fresh.
1025             controller.ensureProcessGone();
1026 
1027             // -------- DIRECT START FOREGROUND SERVICE BLOCKED
1028 
1029             // Now we will deny the app op and ensure the service can't become foreground.
1030             controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore");
1031 
1032             // But we will put it on the whitelist so the service is still allowed to start.
1033             controller.addToWhitelist();
1034 
1035             // Now start the service and wait for it to come up.
1036             mContext.startForegroundService(mServiceStartForegroundIntent);
1037             conn.waitForConnect();
1038 
1039             // In this case we only get to run it as a regular service.
1040             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1041             uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
1042 
1043             // Good, now stop the service and wait for it to go away.
1044             mContext.stopService(mServiceStartForegroundIntent);
1045             conn.waitForDisconnect();
1046 
1047             // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE.
1048             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
1049             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1050 
1051             // Make sure the uid is idle (it should be anyway, it never went active here).
1052             controller.makeUidIdle();
1053 
1054             // Make sure the process is gone so we start over fresh.
1055             controller.ensureProcessGone();
1056 
1057             // -------- XXX NEED TO TEST NON-WHITELIST CASE WHERE NOTHING HAPPENS
1058 
1059         } finally {
1060             mContext.stopService(mServiceStartForegroundIntent);
1061             conn.stopMonitoringIfNeeded();
1062             controller.cleanup();
1063             controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");
1064             controller.removeFromWhitelist();
1065         }
1066     }
1067 
supportsCantSaveState()1068     private boolean supportsCantSaveState() {
1069         if (mContext.getPackageManager().hasSystemFeature(
1070                 PackageManager.FEATURE_CANT_SAVE_STATE)) {
1071             return true;
1072         }
1073 
1074         // Most types of devices need to support this.
1075         int mode = mContext.getResources().getConfiguration().uiMode
1076                 & Configuration.UI_MODE_TYPE_MASK;
1077         if (mode != Configuration.UI_MODE_TYPE_WATCH
1078                 && mode != Configuration.UI_MODE_TYPE_APPLIANCE) {
1079             // Most devices must support the can't save state feature.
1080             throw new IllegalStateException("Devices that are not watches or appliances must "
1081                     + "support FEATURE_CANT_SAVE_STATE");
1082         }
1083         return false;
1084     }
1085 
1086     /**
1087      * Test that a single "can't save state" app has the proper process management
1088      * semantics.
1089      */
testCantSaveStateLaunchAndBackground()1090     public void testCantSaveStateLaunchAndBackground() throws Exception {
1091         if (!supportsCantSaveState()) {
1092             return;
1093         }
1094 
1095         final Intent activityIntent = new Intent();
1096         activityIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
1097         activityIntent.setAction(Intent.ACTION_MAIN);
1098         activityIntent.addCategory(Intent.CATEGORY_LAUNCHER);
1099         activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1100 
1101         final Intent homeIntent = new Intent();
1102         homeIntent.setAction(Intent.ACTION_MAIN);
1103         homeIntent.addCategory(Intent.CATEGORY_HOME);
1104         homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1105 
1106         ActivityManager am = mContext.getSystemService(ActivityManager.class);
1107 
1108         InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
1109                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
1110 
1111         // We don't want to wait for the uid to actually go idle, we can force it now.
1112         String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
1113         String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1114 
1115         ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
1116                 CANT_SAVE_STATE_1_PACKAGE_NAME, 0);
1117 
1118         // This test is also using UidImportanceListener to make sure the correct
1119         // heavy-weight state is reported there.
1120         UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
1121                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
1122                 WAIT_TIME);
1123         uidForegroundListener.register();
1124         UidImportanceListener uidBackgroundListener = new UidImportanceListener(mContext,
1125                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE-1,
1126                 WAIT_TIME);
1127         uidBackgroundListener.register();
1128 
1129         WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
1130                 WAIT_TIME);
1131 
1132         try {
1133             // Start the heavy-weight app, should launch like a normal app.
1134             mContext.startActivity(activityIntent);
1135 
1136             // Wait for process state to reflect running activity.
1137             uidForegroundListener.waitForValue(
1138                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
1139                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
1140             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
1141                     am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));
1142 
1143             // Also make sure the uid state reports are as expected.
1144             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
1145             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1146             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1147 
1148             // Now go to home, leaving the app.  It should be put in the heavy weight state.
1149             mContext.startActivity(homeIntent);
1150 
1151             // Wait for process to go down to background heavy-weight.
1152             uidBackgroundListener.waitForValue(
1153                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE,
1154                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE);
1155             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE,
1156                     am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));
1157 
1158             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
1159             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);
1160 
1161             // While in background, should go in to normal idle state.
1162             // Force app to go idle now
1163             cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
1164             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1165             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
1166 
1167             // Switch back to heavy-weight app to see if it correctly returns to foreground.
1168             mContext.startActivity(activityIntent);
1169 
1170             // Wait for process state to reflect running activity.
1171             uidForegroundListener.waitForValue(
1172                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
1173                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
1174             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,
1175                     am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));
1176 
1177             // Also make sure the uid state reports are as expected.
1178             uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
1179             uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1180             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1181 
1182             waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
1183 
1184             // Exit activity, check to see if we are now cached.
1185             getInstrumentation().getUiAutomation().performGlobalAction(
1186                     AccessibilityService.GLOBAL_ACTION_BACK);
1187 
1188             // Wait for process to become cached
1189             uidBackgroundListener.waitForValue(
1190                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
1191                     ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
1192             assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED,
1193                     am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));
1194 
1195             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
1196             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
1197 
1198             // While in background, should go in to normal idle state.
1199             // Force app to go idle now
1200             cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
1201             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1202             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
1203 
1204         } finally {
1205             uidWatcher.finish();
1206             uidForegroundListener.unregister();
1207             uidBackgroundListener.unregister();
1208         }
1209     }
1210 
1211     /**
1212      * Test that switching between two "can't save state" apps is handled properly.
1213      */
testCantSaveStateLaunchAndSwitch()1214     public void testCantSaveStateLaunchAndSwitch() throws Exception {
1215         if (!supportsCantSaveState()) {
1216             return;
1217         }
1218 
1219         final Intent activity1Intent = new Intent();
1220         activity1Intent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
1221         activity1Intent.setAction(Intent.ACTION_MAIN);
1222         activity1Intent.addCategory(Intent.CATEGORY_LAUNCHER);
1223         activity1Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1224 
1225         final Intent activity2Intent = new Intent();
1226         activity2Intent.setPackage(CANT_SAVE_STATE_2_PACKAGE_NAME);
1227         activity2Intent.setAction(Intent.ACTION_MAIN);
1228         activity2Intent.addCategory(Intent.CATEGORY_LAUNCHER);
1229         activity2Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1230 
1231         final Intent homeIntent = new Intent();
1232         homeIntent.setAction(Intent.ACTION_MAIN);
1233         homeIntent.addCategory(Intent.CATEGORY_HOME);
1234         homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1235 
1236         ActivityManager am = mContext.getSystemService(ActivityManager.class);
1237         UiDevice device = UiDevice.getInstance(getInstrumentation());
1238 
1239         InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
1240                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
1241 
1242         // We don't want to wait for the uid to actually go idle, we can force it now.
1243         String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
1244         String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1245         cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME;
1246         result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1247 
1248         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1249                 CANT_SAVE_STATE_1_PACKAGE_NAME, 0);
1250         WatchUidRunner uid1Watcher = new WatchUidRunner(getInstrumentation(), app1Info.uid,
1251                 WAIT_TIME);
1252 
1253         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
1254                 CANT_SAVE_STATE_2_PACKAGE_NAME, 0);
1255         WatchUidRunner uid2Watcher = new WatchUidRunner(getInstrumentation(), app2Info.uid,
1256                 WAIT_TIME);
1257 
1258         try {
1259             // Start the first heavy-weight app, should launch like a normal app.
1260             mContext.startActivity(activity1Intent);
1261 
1262             // Make sure the uid state reports are as expected.
1263             uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
1264             uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1265             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1266 
1267             // Now go to home, leaving the app.  It should be put in the heavy weight state.
1268             mContext.startActivity(homeIntent);
1269 
1270             // Wait for process to go down to background heavy-weight.
1271             uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
1272             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);
1273 
1274             // Start the second heavy-weight app, should ask us what to do with the two apps
1275             startActivityAndWaitForShow(activity2Intent);
1276 
1277             // First, let's try returning to the original app.
1278             maybeClick(device, new UiSelector().resourceId("android:id/switch_old"));
1279             device.waitForIdle();
1280 
1281             // App should now be back in foreground.
1282             uid1Watcher.expect(WatchUidRunner.CMD_UNCACHED, null);
1283             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1284 
1285             // Return to home.
1286             mContext.startActivity(homeIntent);
1287             uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
1288             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);
1289 
1290             // Again try starting second heavy-weight app to get prompt.
1291             startActivityAndWaitForShow(activity2Intent);
1292 
1293             // Now we'll switch to the new app.
1294             maybeClick(device, new UiSelector().resourceId("android:id/switch_new"));
1295             device.waitForIdle();
1296 
1297             // The original app should now become cached.
1298             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
1299 
1300             // And the new app should start.
1301             uid2Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
1302             uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1303             uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1304 
1305             // Make sure the original app is idle for cleanliness
1306             cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
1307             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1308             uid1Watcher.expect(WatchUidRunner.CMD_IDLE, null);
1309 
1310             // Return to home.
1311             mContext.startActivity(homeIntent);
1312             uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1313             uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);
1314 
1315             // Try starting the first heavy weight app, but return to the existing second.
1316             startActivityAndWaitForShow(activity1Intent);
1317             maybeClick(device, new UiSelector().resourceId("android:id/switch_old"));
1318             device.waitForIdle();
1319             uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1320             uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1321 
1322             // Return to home.
1323             mContext.startActivity(homeIntent);
1324             uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1325             uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);
1326 
1327             // Again start the first heavy weight app, this time actually switching to it
1328             startActivityAndWaitForShow(activity1Intent);
1329             maybeClick(device, new UiSelector().resourceId("android:id/switch_new"));
1330             device.waitForIdle();
1331 
1332             // The second app should now become cached.
1333             uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
1334 
1335             // And the first app should start.
1336             uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
1337             uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
1338             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1339 
1340             // Exit activity, check to see if we are now cached.
1341             waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
1342             getInstrumentation().getUiAutomation().performGlobalAction(
1343                     AccessibilityService.GLOBAL_ACTION_BACK);
1344             uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
1345             uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
1346 
1347             // Make both apps idle for cleanliness.
1348             cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
1349             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1350             cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME;
1351             result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
1352 
1353         } finally {
1354             uid2Watcher.finish();
1355             uid1Watcher.finish();
1356         }
1357     }
1358 }
1359