• 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.assertTrue;
26 import static org.junit.Assert.fail;
27 
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.ServiceConnection;
32 import android.content.pm.PackageManager;
33 import android.os.IBinder;
34 import android.os.Process;
35 import android.util.Log;
36 
37 import androidx.test.InstrumentationRegistry;
38 
39 import org.junit.After;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.junit.runners.JUnit4;
44 
45 
46 /**
47  * CTS for {@link android.os.Process}.
48  *
49  * We have more test in cts/tests/process/ too.
50  */
51 @RunWith(JUnit4.class)
52 public class ProcessTest {
53 
54     public static final int THREAD_PRIORITY_HIGHEST = -20;
55     private static final String NONE_EXISITENT_NAME = "abcdefcg";
56     private static final String WRONG_CACHE_NAME = "cache_abcdefg";
57     private static final String PROCESS_SHELL= "shell";
58     private static final String PROCESS_CACHE= "cache";
59     private static final String REMOTE_SERVICE = "android.app.REMOTESERVICE";
60     private static final int APP_UID = 10001;
61     private static final int SANDBOX_SDK_UID = 20001;
62     private static final int ISOLATED_PROCESS_UID = 99037;
63     private static final int APP_ZYGOTE_ISOLATED_UID = 90123;
64     private static final String TAG = "ProcessTest";
65     private ISecondary mSecondaryService = null;
66     private Intent mIntent;
67     private Object mSync;
68     private boolean mHasConnected;
69     private boolean mHasDisconnected;
70     private ServiceConnection mSecondaryConnection;
71     private Context mContext;
72 
73     @Before
setUp()74     public void setUp() throws Exception {
75         mContext = InstrumentationRegistry.getContext();
76         mSync = new Object();
77         mSecondaryConnection = new ServiceConnection() {
78             public void onServiceConnected(ComponentName className,
79                     IBinder service) {
80                 // Connecting to a secondary interface is the same as any
81                 // other interface.
82                 android.util.Log.d(TAG, "connected");
83                 mSecondaryService = ISecondary.Stub.asInterface(service);
84                 synchronized (mSync) {
85                     mHasConnected = true;
86                     mSync.notify();
87                 }
88             }
89             public void onServiceDisconnected(ComponentName className) {
90                 Log.d(TAG, "disconnected");
91                 mSecondaryService = null;
92                 synchronized (mSync) {
93                     mHasDisconnected = true;
94                     mSync.notify();
95                 }
96             }
97         };
98         mIntent = new Intent(REMOTE_SERVICE);
99         mIntent.setPackage(mContext.getPackageName());
100         mContext.startService(mIntent);
101 
102         Intent secondaryIntent = new Intent(ISecondary.class.getName());
103         secondaryIntent.setPackage(mContext.getPackageName());
104         mContext.bindService(secondaryIntent, mSecondaryConnection,
105                 Context.BIND_AUTO_CREATE);
106         synchronized (mSync) {
107             if (!mHasConnected) {
108                 try {
109                     mSync.wait();
110                 } catch (InterruptedException e) {
111                 }
112             }
113         }
114     }
115 
116     @After
tearDown()117     public void tearDown() throws Exception {
118         if (mIntent != null) {
119             mContext.stopService(mIntent);
120         }
121         if (mSecondaryConnection != null) {
122             mContext.unbindService(mSecondaryConnection);
123         }
124     }
125 
126     @Test
testMiscMethods()127     public void testMiscMethods() {
128         /*
129          * Test setThreadPriority(int) and setThreadPriority(int, int)
130          * 1.Set the priority of the calling thread, based on Linux priorities level,
131          * from -20 for highest scheduling priority to 19 for lowest scheduling priority.
132          * 2.Throws IllegalArgumentException if tid does not exist.
133          */
134         int myTid = Process.myTid();
135 
136         int priority = Process.getThreadPriority(myTid);
137         assertTrue(priority >= THREAD_PRIORITY_HIGHEST
138                 && priority <= Process.THREAD_PRIORITY_LOWEST);
139 
140         Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
141         assertEquals(Process.THREAD_PRIORITY_AUDIO, Process.getThreadPriority(myTid));
142 
143         Process.setThreadPriority(myTid, Process.THREAD_PRIORITY_LOWEST);
144         assertEquals(Process.THREAD_PRIORITY_LOWEST, Process.getThreadPriority(myTid));
145 
146         Process.setThreadPriority(myTid, THREAD_PRIORITY_HIGHEST);
147         assertEquals(THREAD_PRIORITY_HIGHEST, Process.getThreadPriority(myTid));
148 
149         int invalidPriority = THREAD_PRIORITY_HIGHEST - 1;
150         Process.setThreadPriority(myTid, invalidPriority);
151         assertEquals(THREAD_PRIORITY_HIGHEST, Process.getThreadPriority(myTid));
152 
153         try {
154             Process.setThreadPriority(-1, Process.THREAD_PRIORITY_DEFAULT);
155             fail("Should throw IllegalArgumentException");
156         } catch (IllegalArgumentException e) {
157             // expect
158         } // Hard to address logic of throws SecurityException
159 
160         /*
161          * Returns the UID assigned to a particular user name, or -1 if there is
162          * none.  If the given string consists of only numbers, it is converted
163          * directly to a uid.
164          */
165         assertTrue(Process.getUidForName(PROCESS_SHELL) > 0);
166         assertEquals(-1, Process.getUidForName(NONE_EXISITENT_NAME));
167         assertEquals(0, Process.getUidForName("0"));
168 
169         /*
170          * Returns the GID assigned to a particular user name, or -1 if there is
171          * none.  If the given string consists of only numbers, it is converted
172          * directly to a gid.
173          */
174         assertTrue(Process.getGidForName(PROCESS_CACHE) > 0);
175         assertEquals(-1, Process.getGidForName(WRONG_CACHE_NAME));
176         assertEquals(0, Process.getGidForName("0"));
177 
178         assertTrue(Process.myUid() >= 0);
179 
180         assertNotEquals(null, Process.getExclusiveCores());
181     }
182 
183     /**
184      * Test point of killProcess(int)
185      * Only the process running the caller's packages/application
186      * and any additional processes created by that app be able to kill each other's processes.
187      */
188     @Test
testKillProcess()189     public void testKillProcess() throws Exception {
190         long time = 0;
191         int servicePid = 0;
192         try {
193             servicePid = mSecondaryService.getPid();
194             time = mSecondaryService.getElapsedCpuTime();
195         } finally {
196             mContext.stopService(mIntent);
197             mIntent = null;
198         }
199 
200         assertTrue(time > 0);
201         assertTrue(servicePid != Process.myPid());
202 
203         Process.killProcess(servicePid);
204         synchronized (mSync) {
205             if (!mHasDisconnected) {
206                 try {
207                     mSync.wait();
208                 } catch (InterruptedException e) {
209                 }
210             }
211         }
212         assertTrue(mHasDisconnected);
213     }
214 
215     /**
216      * Test myPid() point.
217      * Returns the identifier of this process, which can be used with
218      * {@link #killProcess} and {@link #sendSignal}.
219      * Test sendSignal(int) point.
220      * Send a signal to the given process.
221      */
222     @Test
testSendSignal()223     public void testSendSignal() throws Exception {
224         int servicePid = 0;
225         try {
226             servicePid = mSecondaryService.getPid();
227         } finally {
228             mContext.stopService(mIntent);
229             mIntent = null;
230         }
231         assertTrue(servicePid != 0);
232         assertTrue(Process.myPid() != servicePid);
233         Process.sendSignal(servicePid, Process.SIGNAL_KILL);
234         synchronized (mSync) {
235             if (!mHasDisconnected) {
236                 try {
237                     mSync.wait();
238                 } catch (InterruptedException e) {
239                 }
240             }
241         }
242         assertTrue(mHasDisconnected);
243     }
244 
245     /**
246      * Tests APIs related to sdk sandbox uids.
247      */
248     @Test
testSdkSandboxUids()249     public void testSdkSandboxUids() {
250         assertEquals(SANDBOX_SDK_UID, Process.toSdkSandboxUid(APP_UID));
251         assertEquals(APP_UID, Process.getAppUidForSdkSandboxUid(SANDBOX_SDK_UID));
252 
253         assertFalse(Process.isSdkSandboxUid(APP_UID));
254         assertTrue(Process.isSdkSandboxUid(SANDBOX_SDK_UID));
255 
256         assertFalse(Process.isSdkSandbox());
257     }
258 
259     /**
260      * Tests that the reserved UID is not taken by an actual package.
261      */
262     @Test
testReservedVirtualUid()263     public void testReservedVirtualUid() {
264         PackageManager pm = mContext.getPackageManager();
265         final String name = pm.getNameForUid(Process.SDK_SANDBOX_VIRTUAL_UID);
266         assertNull(name);
267 
268         // PackageManager#getPackagesForUid requires android.permission.INTERACT_ACROSS_USERS for
269         // cross-user calls.
270         runWithShellPermissionIdentity(() -> {
271             final String[] packages = pm.getPackagesForUid(Process.SDK_SANDBOX_VIRTUAL_UID);
272             assertNull(packages);
273         });
274     }
275 
276     /**
277      * Tests for {@link Process#isIsolatedUid(int)} (int)} API.
278      */
279     @Test
testIsolatedProccesUids()280     public void testIsolatedProccesUids() {
281         assertTrue(Process.isIsolatedUid(ISOLATED_PROCESS_UID));
282         assertTrue(Process.isIsolatedUid(APP_ZYGOTE_ISOLATED_UID));
283         // A random UID before the  FIRST_APPLICATION_UID is not an isolated process uid.
284         assertFalse(Process.isIsolatedUid(57));
285         // Sdk Sandbox UID is not an isolated process uid
286         assertFalse(Process.isIsolatedUid(SANDBOX_SDK_UID));
287         // App uid is not an isolated process uid
288         assertFalse(Process.isIsolatedUid(APP_UID));
289     }
290 }
291