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