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