• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.cts;
18 
19 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotEquals;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertThrows;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28 
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.ServiceConnection;
33 import android.content.pm.PackageManager;
34 import android.os.IBinder;
35 import android.os.Process;
36 import android.platform.test.annotations.AppModeNonSdkSandbox;
37 import android.platform.test.annotations.AppModeSdkSandbox;
38 import android.platform.test.annotations.DisabledOnRavenwood;
39 import android.platform.test.annotations.RequiresFlagsEnabled;
40 import android.platform.test.flag.junit.CheckFlagsRule;
41 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
42 import android.platform.test.ravenwood.RavenwoodRule;
43 import android.util.Log;
44 
45 import androidx.test.InstrumentationRegistry;
46 import androidx.test.runner.AndroidJUnit4;
47 
48 import com.android.sdksandbox.flags.Flags;
49 
50 import org.junit.After;
51 import org.junit.Before;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 
56 /**
57  * CTS for {@link Process}.
58  *
59  * We have more test in cts/tests/process/ too.
60  */
61 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).")
62 @RunWith(AndroidJUnit4.class)
63 public class ProcessTest {
64     // Required for RequiresFlagsEnabled and RequiresFlagsDisabled annotations to take effect.
65     @Rule
66     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
67 
68     public static final int THREAD_PRIORITY_HIGHEST = -20;
69     private static final String NONE_EXISITENT_NAME = "abcdefcg";
70     private static final String WRONG_CACHE_NAME = "cache_abcdefg";
71     private static final String PROCESS_SHELL= "shell";
72     private static final String PROCESS_CACHE= "cache";
73     private static final String REMOTE_SERVICE = "android.app.REMOTESERVICE";
74     private static final int APP_UID = 10001;
75     private static final int FIRST_SDK_SANDBOX_UID = 20000;
76     private static final int LAST_SDK_SANDBOX_UID = 29999;
77     private static final int SANDBOX_SDK_UID = 20001;
78     private static final int ISOLATED_PROCESS_UID = 99037;
79     private static final int APP_ZYGOTE_ISOLATED_UID = 90123;
80     private static final String TAG = "ProcessTest";
81     private ISecondary mSecondaryService = null;
82     private Intent mIntent;
83     private Object mSync;
84     private boolean mHasConnected;
85     private boolean mHasDisconnected;
86     private ServiceConnection mSecondaryConnection;
87     private Context mContext;
88 
89     @Before
setUp()90     public void setUp() throws Exception {
91         if (RavenwoodRule.isOnRavenwood()) return;
92         mContext = InstrumentationRegistry.getContext();
93         mSync = new Object();
94         mSecondaryConnection = new ServiceConnection() {
95             public void onServiceConnected(ComponentName className,
96                     IBinder service) {
97                 // Connecting to a secondary interface is the same as any
98                 // other interface.
99                 android.util.Log.d(TAG, "connected");
100                 mSecondaryService = ISecondary.Stub.asInterface(service);
101                 synchronized (mSync) {
102                     mHasConnected = true;
103                     mSync.notify();
104                 }
105             }
106             public void onServiceDisconnected(ComponentName className) {
107                 Log.d(TAG, "disconnected");
108                 mSecondaryService = null;
109                 synchronized (mSync) {
110                     mHasDisconnected = true;
111                     mSync.notify();
112                 }
113             }
114         };
115         mIntent = new Intent(REMOTE_SERVICE);
116         mIntent.setPackage(mContext.getPackageName());
117         mContext.startService(mIntent);
118 
119         Intent secondaryIntent = new Intent(ISecondary.class.getName());
120         secondaryIntent.setPackage(mContext.getPackageName());
121         mContext.bindService(secondaryIntent, mSecondaryConnection,
122                 Context.BIND_AUTO_CREATE);
123         synchronized (mSync) {
124             if (!mHasConnected) {
125                 try {
126                     mSync.wait();
127                 } catch (InterruptedException e) {
128                 }
129             }
130         }
131     }
132 
133     @After
tearDown()134     public void tearDown() throws Exception {
135         if (RavenwoodRule.isOnRavenwood()) return;
136         if (mIntent != null) {
137             mContext.stopService(mIntent);
138         }
139         if (mSecondaryConnection != null) {
140             mContext.unbindService(mSecondaryConnection);
141         }
142     }
143 
144     @Test
145     @DisabledOnRavenwood(reason = "Requires kernel support")
testMiscMethods()146     public void testMiscMethods() {
147         /*
148          * Test setThreadPriority(int) and setThreadPriority(int, int)
149          * 1.Set the priority of the calling thread, based on Linux priorities level,
150          * from -20 for highest scheduling priority to 19 for lowest scheduling priority.
151          * 2.Throws IllegalArgumentException if tid does not exist.
152          */
153         int myTid = Process.myTid();
154 
155         int priority = Process.getThreadPriority(myTid);
156         assertTrue(priority >= THREAD_PRIORITY_HIGHEST
157                 && priority <= Process.THREAD_PRIORITY_LOWEST);
158 
159         Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
160         assertEquals(Process.THREAD_PRIORITY_AUDIO, Process.getThreadPriority(myTid));
161 
162         Process.setThreadPriority(myTid, Process.THREAD_PRIORITY_LOWEST);
163         assertEquals(Process.THREAD_PRIORITY_LOWEST, Process.getThreadPriority(myTid));
164 
165         Process.setThreadPriority(myTid, THREAD_PRIORITY_HIGHEST);
166         assertEquals(THREAD_PRIORITY_HIGHEST, Process.getThreadPriority(myTid));
167 
168         int invalidPriority = THREAD_PRIORITY_HIGHEST - 1;
169         Process.setThreadPriority(myTid, invalidPriority);
170         assertEquals(THREAD_PRIORITY_HIGHEST, Process.getThreadPriority(myTid));
171 
172         try {
173             Process.setThreadPriority(-1, Process.THREAD_PRIORITY_DEFAULT);
174             fail("Should throw IllegalArgumentException");
175         } catch (IllegalArgumentException e) {
176             // expect
177         } // Hard to address logic of throws SecurityException
178 
179         /*
180          * Returns the UID assigned to a particular user name, or -1 if there is
181          * none.  If the given string consists of only numbers, it is converted
182          * directly to a uid.
183          */
184         assertTrue(Process.getUidForName(PROCESS_SHELL) > 0);
185         assertEquals(-1, Process.getUidForName(NONE_EXISITENT_NAME));
186         assertEquals(0, Process.getUidForName("0"));
187 
188         /*
189          * Returns the GID assigned to a particular user name, or -1 if there is
190          * none.  If the given string consists of only numbers, it is converted
191          * directly to a gid.
192          */
193         assertTrue(Process.getGidForName(PROCESS_CACHE) > 0);
194         assertEquals(-1, Process.getGidForName(WRONG_CACHE_NAME));
195         assertEquals(0, Process.getGidForName("0"));
196 
197         assertTrue(Process.myUid() >= 0);
198 
199         assertNotEquals(null, Process.getExclusiveCores());
200     }
201 
202     /**
203      * Test point of killProcess(int)
204      * Only the process running the caller's packages/application
205      * and any additional processes created by that app be able to kill each other's processes.
206      */
207     @Test
208     @DisabledOnRavenwood(reason = "Requires kernel support")
testKillProcess()209     public void testKillProcess() throws Exception {
210         long time = 0;
211         int servicePid = 0;
212         try {
213             servicePid = mSecondaryService.getPid();
214             time = mSecondaryService.getElapsedCpuTime();
215         } finally {
216             mContext.stopService(mIntent);
217             mIntent = null;
218         }
219 
220         assertTrue(time > 0);
221         assertTrue(servicePid != Process.myPid());
222 
223         Process.killProcess(servicePid);
224         synchronized (mSync) {
225             if (!mHasDisconnected) {
226                 try {
227                     mSync.wait();
228                 } catch (InterruptedException e) {
229                 }
230             }
231         }
232         assertTrue(mHasDisconnected);
233     }
234 
235     /**
236      * Test myPid() point.
237      * Returns the identifier of this process, which can be used with
238      * {@link #killProcess} and {@link #sendSignal}.
239      * Test sendSignal(int) point.
240      * Send a signal to the given process.
241      */
242     @Test
243     @DisabledOnRavenwood(reason = "Requires kernel support")
testSendSignal()244     public void testSendSignal() throws Exception {
245         int servicePid = 0;
246         try {
247             servicePid = mSecondaryService.getPid();
248         } finally {
249             mContext.stopService(mIntent);
250             mIntent = null;
251         }
252         assertTrue(servicePid != 0);
253         assertTrue(Process.myPid() != servicePid);
254         Process.sendSignal(servicePid, Process.SIGNAL_KILL);
255         synchronized (mSync) {
256             if (!mHasDisconnected) {
257                 try {
258                     mSync.wait();
259                 } catch (InterruptedException e) {
260                 }
261             }
262         }
263         assertTrue(mHasDisconnected);
264     }
265 
266     /**
267      * Tests {@link Process#isSdkSandbox() (boolean)} API.
268      */
269     @Test
270     @AppModeNonSdkSandbox
testIsSdkSandbox()271     public void testIsSdkSandbox() {
272         assertFalse(Process.isSdkSandbox());
273     }
274 
275     /**
276      * Tests for {@link Process#isSdkSandboxUid() (boolean)} API.
277      */
278     @Test
testIsSdkSandboxUid_UidNotSandboxUid()279     public void testIsSdkSandboxUid_UidNotSandboxUid() {
280         assertFalse(Process.isSdkSandboxUid(APP_UID));
281     }
282 
283     /**
284      * Tests for the following APIs
285      * {@link Process#isSdkSandboxUid() (boolean)}
286      */
287     @Test
testSdkSandboxUids()288     public void testSdkSandboxUids() {
289         for (int i = FIRST_SDK_SANDBOX_UID; i <= LAST_SDK_SANDBOX_UID; i++) {
290             assertTrue(Process.isSdkSandboxUid(i));
291         }
292     }
293 
294     /**
295      * Tests for {@link Process#getAppUidForSdkSandboxUid(int) (int)} API.
296      */
297     @Test
testGetAppUidForSdkSandboxUid()298     public void testGetAppUidForSdkSandboxUid() {
299         assertEquals(APP_UID, Process.getAppUidForSdkSandboxUid(SANDBOX_SDK_UID));
300     }
301 
302     @Test
testGetAppUidForSdkSandboxUid_invalidInput()303     public void testGetAppUidForSdkSandboxUid_invalidInput() {
304         IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
305                 () -> Process.getAppUidForSdkSandboxUid(-1));
306         assertEquals(exception.getMessage(), "Input UID is not an SDK sandbox UID");
307     }
308 
309     @Test
testToSdkSandboxUid()310     public void testToSdkSandboxUid() {
311         assertEquals(SANDBOX_SDK_UID, Process.toSdkSandboxUid(APP_UID));
312     }
313 
314     /**
315      * Tests for {@link Process#getSdkSandboxUidForAppUid(int) (int)} API
316      */
317     @Test
318     @RequiresFlagsEnabled(Flags.FLAG_SDK_SANDBOX_UID_TO_APP_UID_API)
testGetSdkSandboxUidForAppUid()319     public void testGetSdkSandboxUidForAppUid() {
320         assertEquals(SANDBOX_SDK_UID, Process.getSdkSandboxUidForAppUid(APP_UID));
321     }
322 
323     @Test
324     @RequiresFlagsEnabled(Flags.FLAG_SDK_SANDBOX_UID_TO_APP_UID_API)
testGetSdkSandboxUidForAppUid_invalidInput()325     public void testGetSdkSandboxUidForAppUid_invalidInput() {
326         IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
327                 () -> Process.getSdkSandboxUidForAppUid(-1));
328         assertEquals(exception.getMessage(), "Input UID is not an app UID");
329     }
330 
331 
332     /**
333      * Tests that the reserved UID is not taken by an actual package.
334      */
335     @Test
336     @DisabledOnRavenwood(blockedBy = PackageManager.class)
testReservedVirtualUid()337     public void testReservedVirtualUid() {
338         PackageManager pm = mContext.getPackageManager();
339         final String name = pm.getNameForUid(Process.SDK_SANDBOX_VIRTUAL_UID);
340         assertNull(name);
341 
342         // PackageManager#getPackagesForUid requires android.permission.INTERACT_ACROSS_USERS for
343         // cross-user calls.
344         runWithShellPermissionIdentity(() -> {
345             final String[] packages = pm.getPackagesForUid(Process.SDK_SANDBOX_VIRTUAL_UID);
346             assertNull(packages);
347         });
348     }
349 
350     /**
351      * Tests for {@link Process#isIsolatedUid(int)} (int)} API.
352      */
353     @Test
testIsolatedProccesUids()354     public void testIsolatedProccesUids() {
355         assertTrue(Process.isIsolatedUid(ISOLATED_PROCESS_UID));
356         assertTrue(Process.isIsolatedUid(APP_ZYGOTE_ISOLATED_UID));
357         // A random UID before the  FIRST_APPLICATION_UID is not an isolated process uid.
358         assertFalse(Process.isIsolatedUid(57));
359         // Sdk Sandbox UID is not an isolated process uid
360         assertFalse(Process.isIsolatedUid(SANDBOX_SDK_UID));
361         // App uid is not an isolated process uid
362         assertFalse(Process.isIsolatedUid(APP_UID));
363     }
364 
365     @Test
testApplicationUids()366     public void testApplicationUids() {
367         assertTrue(Process.isApplicationUid(Process.FIRST_APPLICATION_UID));
368         assertTrue(Process.isApplicationUid(Process.LAST_APPLICATION_UID));
369         assertFalse(Process.isApplicationUid(Process.ROOT_UID));
370         assertFalse(Process.isApplicationUid(Process.PHONE_UID));
371         assertFalse(Process.isApplicationUid(Process.INVALID_UID));
372     }
373 
374     @Test
testIs64Bit()375     public void testIs64Bit() {
376         // We're not concerned with the answer, just that it works
377         Process.is64Bit();
378     }
379 }
380