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