1 /* 2 * Copyright (C) 2020 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 com.android.server.am; 18 19 import android.app.ActivityManager; 20 import android.content.Context; 21 import android.os.IBinder; 22 import android.util.ArrayMap; 23 import android.util.ArraySet; 24 25 import com.android.internal.annotations.GuardedBy; 26 27 import java.io.PrintWriter; 28 import java.util.ArrayList; 29 30 /** 31 * The state info of all services in the process. 32 */ 33 final class ProcessServiceRecord { 34 /** 35 * Are there any client services with activities? 36 */ 37 private boolean mHasClientActivities; 38 39 /** 40 * Running any services that are foreground? 41 */ 42 private boolean mHasForegroundServices; 43 44 /** 45 * Service that applied current connectionGroup/Importance. 46 */ 47 private ServiceRecord mConnectionService; 48 49 /** 50 * Last group set by a connection. 51 */ 52 private int mConnectionGroup; 53 54 /** 55 * Last importance set by a connection. 56 */ 57 private int mConnectionImportance; 58 59 /** 60 * Type of foreground service, if there is a foreground service. 61 */ 62 private int mFgServiceTypes; 63 64 /** 65 * Last reported foreground service types. 66 */ 67 private int mRepFgServiceTypes; 68 69 /** 70 * Bound using BIND_ABOVE_CLIENT, so want to be lower. 71 */ 72 private boolean mHasAboveClient; 73 74 /** 75 * Bound using BIND_TREAT_LIKE_ACTIVITY. 76 */ 77 private boolean mTreatLikeActivity; 78 79 /** 80 * Do we need to be executing services in the foreground? 81 */ 82 private boolean mExecServicesFg; 83 84 /** 85 * App is allowed to manage allowlists such as temporary Power Save mode allowlist. 86 */ 87 boolean mAllowlistManager; 88 89 /** 90 * All ServiceRecord running in this process. 91 */ 92 final ArraySet<ServiceRecord> mServices = new ArraySet<>(); 93 94 /** 95 * Services that are currently executing code (need to remain foreground). 96 */ 97 private final ArraySet<ServiceRecord> mExecutingServices = new ArraySet<>(); 98 99 /** 100 * All ConnectionRecord this process holds. 101 */ 102 private final ArraySet<ConnectionRecord> mConnections = new ArraySet<>(); 103 104 /** 105 * A set of UIDs of all bound clients. 106 */ 107 private ArraySet<Integer> mBoundClientUids = new ArraySet<>(); 108 109 final ProcessRecord mApp; 110 111 private final ActivityManagerService mService; 112 ProcessServiceRecord(ProcessRecord app)113 ProcessServiceRecord(ProcessRecord app) { 114 mApp = app; 115 mService = app.mService; 116 } 117 setHasClientActivities(boolean hasClientActivities)118 void setHasClientActivities(boolean hasClientActivities) { 119 mHasClientActivities = hasClientActivities; 120 mApp.getWindowProcessController().setHasClientActivities(hasClientActivities); 121 } 122 hasClientActivities()123 boolean hasClientActivities() { 124 return mHasClientActivities; 125 } 126 setHasForegroundServices(boolean hasForegroundServices, int fgServiceTypes)127 void setHasForegroundServices(boolean hasForegroundServices, int fgServiceTypes) { 128 mHasForegroundServices = hasForegroundServices; 129 mFgServiceTypes = fgServiceTypes; 130 mApp.getWindowProcessController().setHasForegroundServices(hasForegroundServices); 131 } 132 hasForegroundServices()133 boolean hasForegroundServices() { 134 return mHasForegroundServices; 135 } 136 getForegroundServiceTypes()137 int getForegroundServiceTypes() { 138 return mHasForegroundServices ? mFgServiceTypes : 0; 139 } 140 getReportedForegroundServiceTypes()141 int getReportedForegroundServiceTypes() { 142 return mRepFgServiceTypes; 143 } 144 setReportedForegroundServiceTypes(int foregroundServiceTypes)145 void setReportedForegroundServiceTypes(int foregroundServiceTypes) { 146 mRepFgServiceTypes = foregroundServiceTypes; 147 } 148 getConnectionService()149 ServiceRecord getConnectionService() { 150 return mConnectionService; 151 } 152 setConnectionService(ServiceRecord connectionService)153 void setConnectionService(ServiceRecord connectionService) { 154 mConnectionService = connectionService; 155 } 156 getConnectionGroup()157 int getConnectionGroup() { 158 return mConnectionGroup; 159 } 160 setConnectionGroup(int connectionGroup)161 void setConnectionGroup(int connectionGroup) { 162 mConnectionGroup = connectionGroup; 163 } 164 getConnectionImportance()165 int getConnectionImportance() { 166 return mConnectionImportance; 167 } 168 setConnectionImportance(int connectionImportance)169 void setConnectionImportance(int connectionImportance) { 170 mConnectionImportance = connectionImportance; 171 } 172 updateHasAboveClientLocked()173 void updateHasAboveClientLocked() { 174 mHasAboveClient = false; 175 for (int i = mConnections.size() - 1; i >= 0; i--) { 176 ConnectionRecord cr = mConnections.valueAt(i); 177 if ((cr.flags & Context.BIND_ABOVE_CLIENT) != 0) { 178 mHasAboveClient = true; 179 break; 180 } 181 } 182 } 183 setHasAboveClient(boolean hasAboveClient)184 void setHasAboveClient(boolean hasAboveClient) { 185 mHasAboveClient = hasAboveClient; 186 } 187 hasAboveClient()188 boolean hasAboveClient() { 189 return mHasAboveClient; 190 } 191 modifyRawOomAdj(int adj)192 int modifyRawOomAdj(int adj) { 193 if (mHasAboveClient) { 194 // If this process has bound to any services with BIND_ABOVE_CLIENT, 195 // then we need to drop its adjustment to be lower than the service's 196 // in order to honor the request. We want to drop it by one adjustment 197 // level... but there is special meaning applied to various levels so 198 // we will skip some of them. 199 if (adj < ProcessList.FOREGROUND_APP_ADJ) { 200 // System process will not get dropped, ever 201 } else if (adj < ProcessList.VISIBLE_APP_ADJ) { 202 adj = ProcessList.VISIBLE_APP_ADJ; 203 } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) { 204 adj = ProcessList.PERCEPTIBLE_APP_ADJ; 205 } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { 206 adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ; 207 } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) { 208 adj = ProcessList.CACHED_APP_MIN_ADJ; 209 } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) { 210 adj++; 211 } 212 } 213 return adj; 214 } 215 isTreatedLikeActivity()216 boolean isTreatedLikeActivity() { 217 return mTreatLikeActivity; 218 } 219 setTreatLikeActivity(boolean treatLikeActivity)220 void setTreatLikeActivity(boolean treatLikeActivity) { 221 mTreatLikeActivity = treatLikeActivity; 222 } 223 shouldExecServicesFg()224 boolean shouldExecServicesFg() { 225 return mExecServicesFg; 226 } 227 setExecServicesFg(boolean execServicesFg)228 void setExecServicesFg(boolean execServicesFg) { 229 mExecServicesFg = execServicesFg; 230 } 231 232 /** 233 * Records a service as running in the process. Note that this method does not actually start 234 * the service, but records the service as started for bookkeeping. 235 * 236 * @return true if the service was added, false otherwise. 237 */ startService(ServiceRecord record)238 boolean startService(ServiceRecord record) { 239 if (record == null) { 240 return false; 241 } 242 boolean added = mServices.add(record); 243 if (added && record.serviceInfo != null) { 244 mApp.getWindowProcessController().onServiceStarted(record.serviceInfo); 245 } 246 return added; 247 } 248 249 /** 250 * Records a service as stopped. Note that like {@link #startService(ServiceRecord)} this method 251 * does not actually stop the service, but records the service as stopped for bookkeeping. 252 * 253 * @return true if the service was removed, false otherwise. 254 */ stopService(ServiceRecord record)255 boolean stopService(ServiceRecord record) { 256 return mServices.remove(record); 257 } 258 259 /** 260 * The same as calling {@link #stopService(ServiceRecord)} on all current running services. 261 */ stopAllServices()262 void stopAllServices() { 263 mServices.clear(); 264 } 265 266 /** 267 * Returns the number of services added with {@link #startService(ServiceRecord)} and not yet 268 * removed by a call to {@link #stopService(ServiceRecord)} or {@link #stopAllServices()}. 269 * 270 * @see #startService(ServiceRecord) 271 * @see #stopService(ServiceRecord) 272 */ numberOfRunningServices()273 int numberOfRunningServices() { 274 return mServices.size(); 275 } 276 277 /** 278 * Returns the service at the specified {@code index}. 279 * 280 * @see #numberOfRunningServices() 281 */ getRunningServiceAt(int index)282 ServiceRecord getRunningServiceAt(int index) { 283 return mServices.valueAt(index); 284 } 285 startExecutingService(ServiceRecord service)286 void startExecutingService(ServiceRecord service) { 287 mExecutingServices.add(service); 288 } 289 stopExecutingService(ServiceRecord service)290 void stopExecutingService(ServiceRecord service) { 291 mExecutingServices.remove(service); 292 } 293 stopAllExecutingServices()294 void stopAllExecutingServices() { 295 mExecutingServices.clear(); 296 } 297 getExecutingServiceAt(int index)298 ServiceRecord getExecutingServiceAt(int index) { 299 return mExecutingServices.valueAt(index); 300 } 301 numberOfExecutingServices()302 int numberOfExecutingServices() { 303 return mExecutingServices.size(); 304 } 305 addConnection(ConnectionRecord connection)306 void addConnection(ConnectionRecord connection) { 307 mConnections.add(connection); 308 } 309 removeConnection(ConnectionRecord connection)310 void removeConnection(ConnectionRecord connection) { 311 mConnections.remove(connection); 312 } 313 removeAllConnections()314 void removeAllConnections() { 315 mConnections.clear(); 316 } 317 getConnectionAt(int index)318 ConnectionRecord getConnectionAt(int index) { 319 return mConnections.valueAt(index); 320 } 321 numberOfConnections()322 int numberOfConnections() { 323 return mConnections.size(); 324 } 325 addBoundClientUid(int clientUid)326 void addBoundClientUid(int clientUid) { 327 mBoundClientUids.add(clientUid); 328 mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); 329 } 330 updateBoundClientUids()331 void updateBoundClientUids() { 332 if (mServices.isEmpty()) { 333 clearBoundClientUids(); 334 return; 335 } 336 // grab a set of clientUids of all mConnections of all services 337 final ArraySet<Integer> boundClientUids = new ArraySet<>(); 338 final int serviceCount = mServices.size(); 339 for (int j = 0; j < serviceCount; j++) { 340 final ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns = 341 mServices.valueAt(j).getConnections(); 342 final int size = conns.size(); 343 for (int conni = 0; conni < size; conni++) { 344 ArrayList<ConnectionRecord> c = conns.valueAt(conni); 345 for (int i = 0; i < c.size(); i++) { 346 boundClientUids.add(c.get(i).clientUid); 347 } 348 } 349 } 350 mBoundClientUids = boundClientUids; 351 mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); 352 } 353 addBoundClientUidsOfNewService(ServiceRecord sr)354 void addBoundClientUidsOfNewService(ServiceRecord sr) { 355 if (sr == null) { 356 return; 357 } 358 ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns = sr.getConnections(); 359 for (int conni = conns.size() - 1; conni >= 0; conni--) { 360 ArrayList<ConnectionRecord> c = conns.valueAt(conni); 361 for (int i = 0; i < c.size(); i++) { 362 mBoundClientUids.add(c.get(i).clientUid); 363 } 364 } 365 mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); 366 } 367 clearBoundClientUids()368 void clearBoundClientUids() { 369 mBoundClientUids.clear(); 370 mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); 371 } 372 373 @GuardedBy("mService") incServiceCrashCountLocked(long now)374 boolean incServiceCrashCountLocked(long now) { 375 final boolean procIsBoundForeground = mApp.mState.getCurProcState() 376 == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 377 boolean tryAgain = false; 378 // Bump up the crash count of any services currently running in the proc. 379 for (int i = numberOfRunningServices() - 1; i >= 0; i--) { 380 // Any services running in the application need to be placed 381 // back in the pending list. 382 ServiceRecord sr = getRunningServiceAt(i); 383 // If the service was restarted a while ago, then reset crash count, else increment it. 384 if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) { 385 sr.crashCount = 1; 386 } else { 387 sr.crashCount++; 388 } 389 // Allow restarting for started or bound foreground services that are crashing. 390 // This includes wallpapers. 391 if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY 392 && (sr.isForeground || procIsBoundForeground)) { 393 tryAgain = true; 394 } 395 } 396 return tryAgain; 397 } 398 399 @GuardedBy("mService") onCleanupApplicationRecordLocked()400 void onCleanupApplicationRecordLocked() { 401 mTreatLikeActivity = false; 402 mHasAboveClient = false; 403 setHasClientActivities(false); 404 } 405 dump(PrintWriter pw, String prefix, long nowUptime)406 void dump(PrintWriter pw, String prefix, long nowUptime) { 407 if (mHasForegroundServices || mApp.mState.getForcingToImportant() != null) { 408 pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices); 409 pw.print(" forcingToImportant="); pw.println(mApp.mState.getForcingToImportant()); 410 } 411 if (mHasClientActivities || mHasAboveClient || mTreatLikeActivity) { 412 pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities); 413 pw.print(" hasAboveClient="); pw.print(mHasAboveClient); 414 pw.print(" treatLikeActivity="); pw.println(mTreatLikeActivity); 415 } 416 if (mConnectionService != null || mConnectionGroup != 0) { 417 pw.print(prefix); pw.print("connectionGroup="); pw.print(mConnectionGroup); 418 pw.print(" Importance="); pw.print(mConnectionImportance); 419 pw.print(" Service="); pw.println(mConnectionService); 420 } 421 if (mAllowlistManager) { 422 pw.print(prefix); pw.print("allowlistManager="); pw.println(mAllowlistManager); 423 } 424 if (mServices.size() > 0) { 425 pw.print(prefix); pw.println("Services:"); 426 for (int i = 0, size = mServices.size(); i < size; i++) { 427 pw.print(prefix); pw.print(" - "); pw.println(mServices.valueAt(i)); 428 } 429 } 430 if (mExecutingServices.size() > 0) { 431 pw.print(prefix); pw.print("Executing Services (fg="); 432 pw.print(mExecServicesFg); pw.println(")"); 433 for (int i = 0, size = mExecutingServices.size(); i < size; i++) { 434 pw.print(prefix); pw.print(" - "); pw.println(mExecutingServices.valueAt(i)); 435 } 436 } 437 if (mConnections.size() > 0) { 438 pw.print(prefix); pw.println("mConnections:"); 439 for (int i = 0, size = mConnections.size(); i < size; i++) { 440 pw.print(prefix); pw.print(" - "); pw.println(mConnections.valueAt(i)); 441 } 442 } 443 } 444 } 445