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