1 /* 2 * Copyright 2015 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 package com.android.server.camera; 17 18 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; 19 import static android.os.Build.VERSION_CODES.M; 20 21 import static com.android.internal.util.FrameworkStatsLog.CAMERA_FEATURE_COMBINATION_QUERY_EVENT__STATUS_CODE__OK; 22 import static com.android.internal.util.FrameworkStatsLog.CAMERA_FEATURE_COMBINATION_QUERY_EVENT__STATUS_CODE__ERROR_ILLEGAL_ARGUMENT; 23 import static com.android.internal.util.FrameworkStatsLog.CAMERA_FEATURE_COMBINATION_QUERY_EVENT__STATUS_CODE__ERROR_INVALID_OPERATION; 24 25 import android.annotation.IntDef; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.TestApi; 29 import android.app.ActivityManager; 30 import android.app.ActivityTaskManager; 31 import android.app.admin.DevicePolicyManager; 32 import android.app.compat.CompatChanges; 33 import android.compat.annotation.ChangeId; 34 import android.compat.annotation.Disabled; 35 import android.compat.annotation.Overridable; 36 import android.content.BroadcastReceiver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.content.pm.ActivityInfo; 41 import android.content.pm.PackageManager; 42 import android.content.pm.ParceledListSlice; 43 import android.content.res.Configuration; 44 import android.graphics.ImageFormat; 45 import android.graphics.Rect; 46 import android.hardware.CameraExtensionSessionStats; 47 import android.hardware.CameraFeatureCombinationStats; 48 import android.hardware.CameraSessionStats; 49 import android.hardware.CameraStreamStats; 50 import android.hardware.ICameraService; 51 import android.hardware.ICameraServiceProxy; 52 import android.hardware.camera2.CameraCharacteristics; 53 import android.hardware.camera2.CameraMetadata; 54 import android.hardware.camera2.CaptureRequest; 55 import android.hardware.devicestate.DeviceStateManager; 56 import android.hardware.devicestate.DeviceStateManager.FoldStateListener; 57 import android.hardware.display.DisplayManager; 58 import android.hardware.usb.UsbDevice; 59 import android.hardware.usb.UsbManager; 60 import android.hidl.manager.V1_0.IServiceManager; 61 import android.media.AudioManager; 62 import android.nfc.NfcAdapter; 63 import android.nfc.NfcManager; 64 import android.os.Binder; 65 import android.os.Handler; 66 import android.os.HandlerExecutor; 67 import android.os.IBinder; 68 import android.os.Message; 69 import android.os.Process; 70 import android.os.RemoteException; 71 import android.os.ResultReceiver; 72 import android.os.ServiceDebugInfo; 73 import android.os.ServiceManager; 74 import android.os.ShellCallback; 75 import android.os.ShellCommand; 76 import android.os.SystemClock; 77 import android.os.SystemProperties; 78 import android.os.UserHandle; 79 import android.os.UserManager; 80 import android.stats.camera.nano.CameraProtos.CameraStreamProto; 81 import android.util.ArrayMap; 82 import android.util.ArraySet; 83 import android.util.Log; 84 import android.util.Range; 85 import android.util.Slog; 86 import android.view.Display; 87 import android.view.IDisplayWindowListener; 88 import android.view.Surface; 89 import android.view.WindowManagerGlobal; 90 91 import com.android.framework.protobuf.nano.MessageNano; 92 import com.android.internal.R; 93 import com.android.internal.annotations.GuardedBy; 94 import com.android.internal.camera.flags.Flags; 95 import com.android.internal.util.FrameworkStatsLog; 96 import com.android.server.LocalServices; 97 import com.android.server.ServiceThread; 98 import com.android.server.SystemService; 99 import com.android.server.am.StackTracesDumpHelper; 100 import com.android.server.wm.WindowManagerInternal; 101 102 import java.io.FileDescriptor; 103 import java.io.PrintWriter; 104 import java.lang.annotation.Retention; 105 import java.lang.annotation.RetentionPolicy; 106 import java.util.ArrayList; 107 import java.util.Arrays; 108 import java.util.Collection; 109 import java.util.Collections; 110 import java.util.HashSet; 111 import java.util.List; 112 import java.util.Set; 113 import java.util.concurrent.CompletableFuture; 114 import java.util.concurrent.ScheduledThreadPoolExecutor; 115 import java.util.concurrent.TimeUnit; 116 117 /** 118 * CameraServiceProxy is the system_server analog to the camera service running in cameraserver. 119 * 120 * @hide 121 */ 122 public class CameraServiceProxy extends SystemService 123 implements Handler.Callback, IBinder.DeathRecipient { 124 private static final String TAG = "CameraService_proxy"; 125 private static final boolean DEBUG = false; 126 127 /** 128 * This must match the ICameraService.aidl definition 129 */ 130 private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera"; 131 132 public static final String CAMERA_SERVICE_PROXY_BINDER_NAME = "media.camera.proxy"; 133 134 /** 135 * When enabled this change id forces the packages it is applied to override the default 136 * camera rotate & crop behavior and always return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE . 137 * The default behavior along with all possible override combinations is discussed in the table 138 * below. 139 */ 140 @ChangeId 141 @Overridable 142 @Disabled 143 @TestApi 144 public static final long OVERRIDE_CAMERA_ROTATE_AND_CROP_DEFAULTS = 189229956L; // buganizer id 145 146 /** 147 * When enabled this change id forces the packages it is applied to ignore the current value of 148 * 'android:resizeableActivity' as well as target SDK equal to or below M and consider the 149 * activity as non-resizeable. In this case, the value of camera rotate & crop will only depend 150 * on the needed compensation considering the current display rotation. 151 */ 152 @ChangeId 153 @Overridable 154 @Disabled 155 @TestApi 156 public static final long OVERRIDE_CAMERA_RESIZABLE_AND_SDK_CHECK = 191513214L; // buganizer id 157 158 /** 159 * Possible override combinations 160 * 161 * |OVERRIDE |OVERRIDE_ 162 * |CAMERA_ |CAMERA_ 163 * |ROTATE_ |RESIZEABLE_ 164 * |AND_CROP_ |AND_SDK_ 165 * |DEFAULTS |CHECK 166 * _________________________________________________ 167 * Default Behavior | D |D 168 * _________________________________________________ 169 * Ignore SDK&Resize | D |E 170 * _________________________________________________ 171 * SCALER_ROTATE_AND_CROP_NONE | E |D, E 172 * _________________________________________________ 173 * Where: 174 * E -> Override enabled 175 * D -> Override disabled 176 * Default behavior -> Rotate&crop will be calculated depending on the required 177 * compensation necessary for the current display rotation. 178 * Additionally the app must either target M (or below) 179 * or is declared as non-resizeable. 180 * Ignore SDK&Resize -> The Rotate&crop value will depend on the required 181 * compensation for the current display rotation. 182 * SCALER_ROTATE_AND_CROP_NONE -> Always return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE 183 */ 184 185 // Handler message codes 186 private static final int MSG_SWITCH_USER = 1; 187 private static final int MSG_NOTIFY_DEVICE_STATE = 2; 188 189 private static final int RETRY_DELAY_TIME = 20; //ms 190 private static final int RETRY_TIMES = 60; 191 192 @IntDef(flag = true, prefix = { "DEVICE_STATE_" }, value = { 193 ICameraService.DEVICE_STATE_BACK_COVERED, 194 ICameraService.DEVICE_STATE_FRONT_COVERED, 195 ICameraService.DEVICE_STATE_FOLDED 196 }) 197 @Retention(RetentionPolicy.SOURCE) 198 @interface DeviceStateFlags {} 199 200 // Maximum entries to keep in usage history before dumping out 201 private static final int MAX_USAGE_HISTORY = 20; 202 // Number of stream statistics being dumped for each camera session 203 // Must be equal to number of CameraStreamProto in CameraActionEvent 204 private static final int MAX_STREAM_STATISTICS = 5; 205 206 private static final float MIN_PREVIEW_FPS = 30.0f; 207 private static final float MAX_PREVIEW_FPS = 60.0f; 208 209 private final Context mContext; 210 private final ServiceThread mHandlerThread; 211 private final Handler mHandler; 212 private UserManager mUserManager; 213 214 private final Object mLock = new Object(); 215 private Set<Integer> mEnabledCameraUsers; 216 private int mLastUser; 217 // The current set of device state flags. May be different from mLastReportedDeviceState if the 218 // native camera service has not been notified of the change. 219 @GuardedBy("mLock") 220 @DeviceStateFlags 221 private int mDeviceState; 222 // The most recent device state flags reported to the native camera server. 223 @GuardedBy("mLock") 224 @DeviceStateFlags 225 private int mLastReportedDeviceState; 226 227 private ICameraService mCameraServiceRaw; 228 229 // Map of currently active camera IDs 230 private final ArrayMap<String, CameraUsageEvent> mActiveCameraUsage = new ArrayMap<>(); 231 private final List<CameraEvent> mCameraEventHistory = new ArrayList<CameraEvent>(); 232 233 private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc"; 234 private static final IBinder nfcInterfaceToken = new Binder(); 235 236 private final boolean mNotifyNfc; 237 238 private ScheduledThreadPoolExecutor mLogWriterService = new ScheduledThreadPoolExecutor( 239 /*corePoolSize*/ 1); 240 241 /** 242 * Interface to track camera analytics 243 */ 244 private interface CameraEvent { logSelf()245 void logSelf(); 246 } 247 248 /** 249 * Structure to track camera usage 250 */ 251 private static class CameraUsageEvent implements CameraEvent { 252 public final String mCameraId; 253 public final int mCameraFacing; 254 public final String mClientName; 255 public final int mAPILevel; 256 public final boolean mIsNdk; 257 public final int mAction; 258 public final int mLatencyMs; 259 public final int mOperatingMode; 260 261 private boolean mCompleted; 262 public int mInternalReconfigure; 263 public long mRequestCount; 264 public long mResultErrorCount; 265 public boolean mDeviceError; 266 public List<CameraStreamStats> mStreamStats; 267 public String mUserTag; 268 public int mVideoStabilizationMode; 269 public boolean mUsedUltraWide; 270 public boolean mUsedZoomOverride; 271 public Range<Integer> mMostRequestedFpsRange; 272 public final long mLogId; 273 public final int mSessionIndex; 274 275 private long mDurationOrStartTimeMs; // Either start time, or duration once completed 276 public CameraExtensionSessionStats mExtSessionStats = null; 277 CameraUsageEvent(String cameraId, int facing, String clientName, int apiLevel, boolean isNdk, int action, int latencyMs, int operatingMode, boolean deviceError, long logId, int sessionIdx)278 CameraUsageEvent(String cameraId, int facing, String clientName, int apiLevel, 279 boolean isNdk, int action, int latencyMs, int operatingMode, boolean deviceError, 280 long logId, int sessionIdx) { 281 mCameraId = cameraId; 282 mCameraFacing = facing; 283 mClientName = clientName; 284 mAPILevel = apiLevel; 285 mDurationOrStartTimeMs = SystemClock.elapsedRealtime(); 286 mCompleted = false; 287 mIsNdk = isNdk; 288 mAction = action; 289 mLatencyMs = latencyMs; 290 mOperatingMode = operatingMode; 291 mDeviceError = deviceError; 292 mLogId = logId; 293 mSessionIndex = sessionIdx; 294 mMostRequestedFpsRange = new Range<Integer>(0, 0); 295 } 296 markCompleted(int internalReconfigure, long requestCount, long resultErrorCount, boolean deviceError, List<CameraStreamStats> streamStats, String userTag, int videoStabilizationMode, boolean usedUltraWide, boolean usedZoomOverride, Range<Integer> mostRequestedFpsRange, CameraExtensionSessionStats extStats)297 public void markCompleted(int internalReconfigure, long requestCount, 298 long resultErrorCount, boolean deviceError, 299 List<CameraStreamStats> streamStats, String userTag, 300 int videoStabilizationMode, boolean usedUltraWide, 301 boolean usedZoomOverride, Range<Integer> mostRequestedFpsRange, 302 CameraExtensionSessionStats extStats) { 303 if (mCompleted) { 304 return; 305 } 306 mCompleted = true; 307 mDurationOrStartTimeMs = SystemClock.elapsedRealtime() - mDurationOrStartTimeMs; 308 mInternalReconfigure = internalReconfigure; 309 mRequestCount = requestCount; 310 mResultErrorCount = resultErrorCount; 311 mDeviceError = deviceError; 312 mStreamStats = streamStats; 313 mUserTag = userTag; 314 mVideoStabilizationMode = videoStabilizationMode; 315 mUsedUltraWide = usedUltraWide; 316 mUsedZoomOverride = usedZoomOverride; 317 mExtSessionStats = extStats; 318 mMostRequestedFpsRange = mostRequestedFpsRange; 319 if (CameraServiceProxy.DEBUG) { 320 Slog.v(TAG, "A camera facing " + cameraFacingToString(mCameraFacing) + 321 " was in use by " + mClientName + " for " + 322 mDurationOrStartTimeMs + " ms"); 323 } 324 } 325 326 /** 327 * Return duration of camera usage event, or 0 if the event is not done 328 */ getDuration()329 public long getDuration() { 330 return mCompleted ? mDurationOrStartTimeMs : 0; 331 } 332 logSelf()333 public void logSelf() { 334 int facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__UNKNOWN; 335 switch(mCameraFacing) { 336 case CameraSessionStats.CAMERA_FACING_BACK: 337 facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__BACK; 338 break; 339 case CameraSessionStats.CAMERA_FACING_FRONT: 340 facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__FRONT; 341 break; 342 case CameraSessionStats.CAMERA_FACING_EXTERNAL: 343 facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__EXTERNAL; 344 break; 345 default: 346 Slog.w(TAG, "Unknown camera facing: " + mCameraFacing); 347 } 348 349 int extensionType = FrameworkStatsLog.CAMERA_ACTION_EVENT__EXT_TYPE__EXTENSION_NONE; 350 boolean extensionIsAdvanced = false; 351 int extensionCaptureFormat = ImageFormat.UNKNOWN; 352 if (mExtSessionStats != null) { 353 switch (mExtSessionStats.type) { 354 case CameraExtensionSessionStats.Type.EXTENSION_AUTOMATIC: 355 extensionType = FrameworkStatsLog 356 .CAMERA_ACTION_EVENT__EXT_TYPE__EXTENSION_AUTOMATIC; 357 break; 358 case CameraExtensionSessionStats.Type.EXTENSION_FACE_RETOUCH: 359 extensionType = FrameworkStatsLog 360 .CAMERA_ACTION_EVENT__EXT_TYPE__EXTENSION_FACE_RETOUCH; 361 break; 362 case CameraExtensionSessionStats.Type.EXTENSION_BOKEH: 363 extensionType = 364 FrameworkStatsLog.CAMERA_ACTION_EVENT__EXT_TYPE__EXTENSION_BOKEH; 365 break; 366 case CameraExtensionSessionStats.Type.EXTENSION_HDR: 367 extensionType = 368 FrameworkStatsLog.CAMERA_ACTION_EVENT__EXT_TYPE__EXTENSION_HDR; 369 break; 370 case CameraExtensionSessionStats.Type.EXTENSION_NIGHT: 371 extensionType = 372 FrameworkStatsLog.CAMERA_ACTION_EVENT__EXT_TYPE__EXTENSION_NIGHT; 373 break; 374 default: 375 Slog.w(TAG, "Unknown extension type: " + mExtSessionStats.type); 376 } 377 extensionIsAdvanced = mExtSessionStats.isAdvanced; 378 if (Flags.analytics24q3()) { 379 extensionCaptureFormat = mExtSessionStats.captureFormat; 380 } 381 } 382 383 int streamCount = 0; 384 if (mStreamStats != null) { 385 streamCount = mStreamStats.size(); 386 } 387 if (CameraServiceProxy.DEBUG) { 388 String ultrawideDebug = ", wideAngleUsage " + mUsedUltraWide; 389 String zoomOverrideDebug = ", zoomOverrideUsage " + mUsedZoomOverride; 390 String mostRequestedFpsRangeDebug = Flags.analytics24q3() 391 ? ", mostRequestedFpsRange " + mMostRequestedFpsRange 392 : ""; 393 String extensionCaptureFormatDebug = Flags.analytics24q3() 394 ? " extensionCaptureFormat " + mExtSessionStats.captureFormat 395 : ""; 396 397 Slog.v(TAG, "CAMERA_ACTION_EVENT: action " + mAction 398 + " clientName " + mClientName 399 + ", duration " + getDuration() 400 + ", APILevel " + mAPILevel 401 + ", cameraId " + mCameraId 402 + ", facing " + facing 403 + ", isNdk " + mIsNdk 404 + ", latencyMs " + mLatencyMs 405 + ", operatingMode " + mOperatingMode 406 + ", internalReconfigure " + mInternalReconfigure 407 + ", requestCount " + mRequestCount 408 + ", resultErrorCount " + mResultErrorCount 409 + ", deviceError " + mDeviceError 410 + ", streamCount is " + streamCount 411 + ", userTag is " + mUserTag 412 + ", videoStabilizationMode " + mVideoStabilizationMode 413 + ultrawideDebug 414 + zoomOverrideDebug 415 + mostRequestedFpsRangeDebug 416 + ", logId " + mLogId 417 + ", sessionIndex " + mSessionIndex 418 + ", mExtSessionStats {type " + extensionType 419 + " isAdvanced " + extensionIsAdvanced 420 + extensionCaptureFormatDebug + "}"); 421 } 422 423 // Convert from CameraStreamStats to CameraStreamProto 424 CameraStreamProto[] streamProtos = new CameraStreamProto[MAX_STREAM_STATISTICS]; 425 for (int i = 0; i < MAX_STREAM_STATISTICS; i++) { 426 streamProtos[i] = new CameraStreamProto(); 427 if (i < streamCount) { 428 CameraStreamStats streamStats = mStreamStats.get(i); 429 streamProtos[i].width = streamStats.getWidth(); 430 streamProtos[i].height = streamStats.getHeight(); 431 streamProtos[i].format = streamStats.getFormat(); 432 streamProtos[i].dataSpace = streamStats.getDataSpace(); 433 streamProtos[i].usage = streamStats.getUsage(); 434 streamProtos[i].requestCount = streamStats.getRequestCount(); 435 streamProtos[i].errorCount = streamStats.getErrorCount(); 436 streamProtos[i].firstCaptureLatencyMillis = streamStats.getStartLatencyMs(); 437 streamProtos[i].maxHalBuffers = streamStats.getMaxHalBuffers(); 438 streamProtos[i].maxAppBuffers = streamStats.getMaxAppBuffers(); 439 streamProtos[i].histogramType = streamStats.getHistogramType(); 440 streamProtos[i].histogramBins = streamStats.getHistogramBins(); 441 streamProtos[i].histogramCounts = streamStats.getHistogramCounts(); 442 streamProtos[i].dynamicRangeProfile = streamStats.getDynamicRangeProfile(); 443 streamProtos[i].streamUseCase = streamStats.getStreamUseCase(); 444 streamProtos[i].colorSpace = streamStats.getColorSpace(); 445 446 if (CameraServiceProxy.DEBUG) { 447 String histogramTypeName = 448 cameraHistogramTypeToString(streamProtos[i].histogramType); 449 Slog.v(TAG, "Stream " + i + ": width " + streamProtos[i].width 450 + ", height " + streamProtos[i].height 451 + ", format " + streamProtos[i].format 452 + ", maxPreviewFps " + streamStats.getMaxPreviewFps() 453 + ", dataSpace " + streamProtos[i].dataSpace 454 + ", usage " + streamProtos[i].usage 455 + ", requestCount " + streamProtos[i].requestCount 456 + ", errorCount " + streamProtos[i].errorCount 457 + ", firstCaptureLatencyMillis " 458 + streamProtos[i].firstCaptureLatencyMillis 459 + ", maxHalBuffers " + streamProtos[i].maxHalBuffers 460 + ", maxAppBuffers " + streamProtos[i].maxAppBuffers 461 + ", histogramType " + histogramTypeName 462 + ", histogramBins " 463 + Arrays.toString(streamProtos[i].histogramBins) 464 + ", histogramCounts " 465 + Arrays.toString(streamProtos[i].histogramCounts) 466 + ", dynamicRangeProfile " + streamProtos[i].dynamicRangeProfile 467 + ", streamUseCase " + streamProtos[i].streamUseCase 468 + ", colorSpace " + streamProtos[i].colorSpace); 469 } 470 } 471 } 472 FrameworkStatsLog.write(FrameworkStatsLog.CAMERA_ACTION_EVENT, getDuration(), 473 mAPILevel, mClientName, facing, mCameraId, mAction, mIsNdk, 474 mLatencyMs, mOperatingMode, mInternalReconfigure, 475 mRequestCount, mResultErrorCount, mDeviceError, 476 streamCount, MessageNano.toByteArray(streamProtos[0]), 477 MessageNano.toByteArray(streamProtos[1]), 478 MessageNano.toByteArray(streamProtos[2]), 479 MessageNano.toByteArray(streamProtos[3]), 480 MessageNano.toByteArray(streamProtos[4]), 481 mUserTag, mVideoStabilizationMode, 482 mLogId, mSessionIndex, 483 extensionType, extensionIsAdvanced, mUsedUltraWide, 484 mUsedZoomOverride, 485 mMostRequestedFpsRange.getLower(), mMostRequestedFpsRange.getUpper(), 486 extensionCaptureFormat); 487 488 } 489 } 490 /** 491 * Structure to track feature combination query 492 */ 493 private static class CameraFeatureCombinationQueryEvent implements CameraEvent { 494 private CameraFeatureCombinationStats mFeatureCombinationStats; 495 CameraFeatureCombinationQueryEvent(CameraFeatureCombinationStats featureCombinationStats)496 CameraFeatureCombinationQueryEvent(CameraFeatureCombinationStats featureCombinationStats) { 497 mFeatureCombinationStats = featureCombinationStats; 498 } 499 logSelf()500 public void logSelf() { 501 int statusCode = -1; 502 switch (mFeatureCombinationStats.mStatus) { 503 case 0: 504 statusCode = CAMERA_FEATURE_COMBINATION_QUERY_EVENT__STATUS_CODE__OK; 505 break; 506 case ICameraService.ERROR_ILLEGAL_ARGUMENT: 507 statusCode = CAMERA_FEATURE_COMBINATION_QUERY_EVENT__STATUS_CODE__ERROR_ILLEGAL_ARGUMENT; 508 break; 509 case ICameraService.ERROR_INVALID_OPERATION: 510 statusCode = CAMERA_FEATURE_COMBINATION_QUERY_EVENT__STATUS_CODE__ERROR_INVALID_OPERATION; 511 break; 512 default: 513 break; 514 } 515 if (statusCode == -1) { 516 Slog.w(TAG, "Unknown feature combination query status code: " 517 + mFeatureCombinationStats.mStatus); 518 return; 519 } 520 521 if (CameraServiceProxy.DEBUG) { 522 Slog.v(TAG, "CAMERA_FEATURE_COMBINATION_QUERY_EVENT: uid " 523 + mFeatureCombinationStats.mUid 524 + ", cameraId " + mFeatureCombinationStats.mCameraId 525 + ", queryType " + mFeatureCombinationStats.mQueryType 526 + ", featureCombination " + mFeatureCombinationStats.mFeatureCombination 527 + ", status " + statusCode); 528 } 529 FrameworkStatsLog.write(FrameworkStatsLog.CAMERA_FEATURE_COMBINATION_QUERY_EVENT, 530 mFeatureCombinationStats.mUid, 531 mFeatureCombinationStats.mCameraId, 532 mFeatureCombinationStats.mQueryType, 533 mFeatureCombinationStats.mFeatureCombination, 534 statusCode); 535 } 536 } 537 538 private final class DisplayWindowListener extends IDisplayWindowListener.Stub { 539 540 @Override onDisplayConfigurationChanged(int displayId, Configuration newConfig)541 public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { 542 ICameraService cs = getCameraServiceRawLocked(); 543 if (cs == null) return; 544 545 try { 546 cs.notifyDisplayConfigurationChange(); 547 } catch (RemoteException e) { 548 Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e); 549 // Not much we can do if camera service is dead. 550 } 551 } 552 553 @Override onDisplayAdded(int displayId)554 public void onDisplayAdded(int displayId) { } 555 556 @Override onDisplayRemoved(int displayId)557 public void onDisplayRemoved(int displayId) { } 558 559 @Override onFixedRotationStarted(int displayId, int newRotation)560 public void onFixedRotationStarted(int displayId, int newRotation) { } 561 562 @Override onFixedRotationFinished(int displayId)563 public void onFixedRotationFinished(int displayId) { } 564 565 @Override onKeepClearAreasChanged(int displayId, List<Rect> restricted, List<Rect> unrestricted)566 public void onKeepClearAreasChanged(int displayId, List<Rect> restricted, 567 List<Rect> unrestricted) { } 568 569 @Override onDesktopModeEligibleChanged(int displayId)570 public void onDesktopModeEligibleChanged(int displayId) { } 571 } 572 573 574 private final DisplayWindowListener mDisplayWindowListener = new DisplayWindowListener(); 575 576 public static final class TaskInfo { 577 public int frontTaskId; 578 public boolean isResizeable; 579 public boolean isFixedOrientationLandscape; 580 public boolean isFixedOrientationPortrait; 581 public int displayId; 582 public int userId; 583 } 584 585 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 586 @Override 587 public void onReceive(Context context, Intent intent) { 588 final String action = intent.getAction(); 589 if (action == null) return; 590 591 switch (action) { 592 case Intent.ACTION_USER_ADDED: 593 case Intent.ACTION_USER_REMOVED: 594 case Intent.ACTION_USER_INFO_CHANGED: 595 case Intent.ACTION_MANAGED_PROFILE_ADDED: 596 case Intent.ACTION_MANAGED_PROFILE_REMOVED: 597 synchronized(mLock) { 598 // Return immediately if we haven't seen any users start yet 599 if (mEnabledCameraUsers == null) return; 600 switchUserLocked(mLastUser); 601 } 602 break; 603 case UsbManager.ACTION_USB_DEVICE_ATTACHED: 604 case UsbManager.ACTION_USB_DEVICE_DETACHED: 605 synchronized (mLock) { 606 UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, android.hardware.usb.UsbDevice.class); 607 if (device != null) { 608 notifyUsbDeviceHotplugLocked(device, 609 action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)); 610 } 611 } 612 break; 613 default: 614 break; // do nothing 615 } 616 617 } 618 }; 619 isMOrBelow(Context ctx, String packageName)620 private static boolean isMOrBelow(Context ctx, String packageName) { 621 try { 622 return ctx.getPackageManager().getPackageInfo( 623 packageName, 0).applicationInfo.targetSdkVersion <= M; 624 } catch (PackageManager.NameNotFoundException e) { 625 Slog.e(TAG,"Package name not found!"); 626 } 627 return false; 628 } 629 630 /** 631 * Estimate the app crop-rotate-scale compensation value. 632 */ getCropRotateScale(@onNull Context ctx, @NonNull String packageName, @Nullable TaskInfo taskInfo, int displayRotation, int lensFacing, boolean ignoreResizableAndSdkCheck)633 public static int getCropRotateScale(@NonNull Context ctx, @NonNull String packageName, 634 @Nullable TaskInfo taskInfo, int displayRotation, int lensFacing, 635 boolean ignoreResizableAndSdkCheck) { 636 if (taskInfo == null) { 637 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 638 } 639 640 // When config_isWindowManagerCameraCompatTreatmentEnabled is true, 641 // DisplayRotationCompatPolicy in WindowManager force rotates fullscreen activities with 642 // fixed orientation to align them with the natural orientation of the device. 643 if (ctx.getResources().getBoolean( 644 R.bool.config_isWindowManagerCameraCompatTreatmentEnabled)) { 645 Slog.v(TAG, "Disable Rotate and Crop to avoid conflicts with" 646 + " WM force rotation treatment."); 647 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 648 } 649 650 // External cameras do not need crop-rotate-scale. 651 if (lensFacing != CameraMetadata.LENS_FACING_FRONT 652 && lensFacing != CameraMetadata.LENS_FACING_BACK) { 653 Log.v(TAG, "lensFacing=" + lensFacing + ". Crop-rotate-scale is disabled."); 654 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 655 } 656 657 // In case the activity behavior is not explicitly overridden, enable the 658 // crop-rotate-scale workaround if the app targets M (or below) or is not 659 // resizeable. 660 if (!ignoreResizableAndSdkCheck && !isMOrBelow(ctx, packageName) && 661 taskInfo.isResizeable) { 662 Slog.v(TAG, 663 "The activity is N or above and claims to support resizeable-activity. " 664 + "Crop-rotate-scale is disabled."); 665 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 666 } 667 668 if (!taskInfo.isFixedOrientationPortrait && !taskInfo.isFixedOrientationLandscape) { 669 Log.v(TAG, "Non-fixed orientation activity. Crop-rotate-scale is disabled."); 670 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 671 } 672 673 int rotationDegree; 674 switch (displayRotation) { 675 case Surface.ROTATION_0: 676 rotationDegree = 0; 677 break; 678 case Surface.ROTATION_90: 679 rotationDegree = 90; 680 break; 681 case Surface.ROTATION_180: 682 rotationDegree = 180; 683 break; 684 case Surface.ROTATION_270: 685 rotationDegree = 270; 686 break; 687 default: 688 Log.e(TAG, "Unsupported display rotation: " + displayRotation); 689 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 690 } 691 692 Slog.v(TAG, 693 "Display.getRotation()=" + rotationDegree 694 + " isFixedOrientationPortrait=" + taskInfo.isFixedOrientationPortrait 695 + " isFixedOrientationLandscape=" + 696 taskInfo.isFixedOrientationLandscape); 697 // We are trying to estimate the necessary rotation compensation for clients that 698 // don't handle various display orientations. 699 // The logic that is missing on client side is similar to the reference code 700 // in {@link android.hardware.Camera#setDisplayOrientation} where "info.orientation" 701 // is already applied in "CameraUtils::getRotationTransform". 702 // Care should be taken to reverse the rotation direction depending on the camera 703 // lens facing. 704 if (rotationDegree == 0) { 705 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 706 } 707 if (lensFacing == CameraCharacteristics.LENS_FACING_FRONT) { 708 // Switch direction for front facing cameras 709 rotationDegree = 360 - rotationDegree; 710 } 711 712 switch (rotationDegree) { 713 case 90: 714 return CaptureRequest.SCALER_ROTATE_AND_CROP_90; 715 case 270: 716 return CaptureRequest.SCALER_ROTATE_AND_CROP_270; 717 case 180: 718 return CaptureRequest.SCALER_ROTATE_AND_CROP_180; 719 case 0: 720 default: 721 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 722 } 723 } 724 725 private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() { 726 @Override 727 public int getRotateAndCropOverride(String packageName, int lensFacing, int userId) { 728 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) { 729 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " + 730 " camera service UID!"); 731 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 732 } 733 734 TaskInfo taskInfo = null; 735 ParceledListSlice<ActivityManager.RecentTaskInfo> recentTasks = null; 736 737 try { 738 // Get 2 recent tasks in case we are running in split mode 739 recentTasks = ActivityTaskManager.getService().getRecentTasks(/*maxNum*/2, 740 /*flags*/ 0, userId); 741 } catch (RemoteException e) { 742 Log.e(TAG, "Failed to query recent tasks!"); 743 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 744 } 745 746 if ((recentTasks != null) && (!recentTasks.getList().isEmpty())) { 747 for (ActivityManager.RecentTaskInfo task : recentTasks.getList()) { 748 if (task.topActivityInfo != null && packageName.equals( 749 task.topActivityInfo.packageName)) { 750 taskInfo = new TaskInfo(); 751 taskInfo.frontTaskId = task.taskId; 752 taskInfo.isResizeable = 753 (task.topActivityInfo.resizeMode != RESIZE_MODE_UNRESIZEABLE); 754 taskInfo.displayId = task.displayId; 755 taskInfo.userId = task.userId; 756 taskInfo.isFixedOrientationLandscape = 757 ActivityInfo.isFixedOrientationLandscape( 758 task.topActivityInfo.screenOrientation); 759 taskInfo.isFixedOrientationPortrait = 760 ActivityInfo.isFixedOrientationPortrait( 761 task.topActivityInfo.screenOrientation); 762 break; 763 } 764 } 765 766 if (taskInfo == null) { 767 Log.e(TAG, "Recent tasks don't include camera client package name: " + 768 packageName); 769 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 770 } 771 } else { 772 Log.e(TAG, "Recent task list is empty!"); 773 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 774 } 775 776 // TODO: Modify the sensor orientation in camera characteristics along with any 3A 777 // regions in capture requests/results to account for thea physical rotation. The 778 // former is somewhat tricky as it assumes that camera clients always check for the 779 // current value by retrieving the camera characteristics from the camera device. 780 if ((taskInfo != null) && (CompatChanges.isChangeEnabled( 781 OVERRIDE_CAMERA_ROTATE_AND_CROP_DEFAULTS, packageName, 782 UserHandle.getUserHandleForUid(taskInfo.userId)))) { 783 Slog.v(TAG, "OVERRIDE_CAMERA_ROTATE_AND_CROP_DEFAULTS enabled!"); 784 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 785 } 786 boolean ignoreResizableAndSdkCheck = false; 787 if ((taskInfo != null) && (CompatChanges.isChangeEnabled( 788 OVERRIDE_CAMERA_RESIZABLE_AND_SDK_CHECK, packageName, 789 UserHandle.getUserHandleForUid(taskInfo.userId)))) { 790 Slog.v(TAG, "OVERRIDE_CAMERA_RESIZABLE_AND_SDK_CHECK enabled!"); 791 ignoreResizableAndSdkCheck = true; 792 } 793 794 DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); 795 int displayRotation; 796 if (displayManager != null) { 797 Display display = displayManager.getDisplay(taskInfo.displayId); 798 if (display == null) { 799 Slog.e(TAG, "Invalid display id: " + taskInfo.displayId); 800 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 801 } 802 803 displayRotation = display.getRotation(); 804 } else { 805 Slog.e(TAG, "Failed to query display manager!"); 806 return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE; 807 } 808 809 return getCropRotateScale(mContext, packageName, taskInfo, displayRotation, 810 lensFacing, ignoreResizableAndSdkCheck); 811 } 812 813 /** 814 * Placeholder method to fetch the system state for autoframing. 815 * TODO: b/260617354 816 */ 817 @Override 818 public int getAutoframingOverride(String packageName) { 819 return CaptureRequest.CONTROL_AUTOFRAMING_OFF; 820 } 821 822 @Override 823 public void pingForUserUpdate() { 824 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) { 825 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " + 826 " camera service UID!"); 827 return; 828 } 829 notifySwitchWithRetries(RETRY_TIMES); 830 notifyDeviceStateWithRetries(RETRY_TIMES); 831 } 832 833 @Override 834 public void notifyCameraState(CameraSessionStats cameraState) { 835 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) { 836 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " + 837 " camera service UID!"); 838 return; 839 } 840 String state = cameraStateToString(cameraState.getNewCameraState()); 841 String facingStr = cameraFacingToString(cameraState.getFacing()); 842 if (DEBUG) { 843 Slog.v(TAG, "Camera " + cameraState.getCameraId() 844 + " facing " + facingStr + " state now " + state 845 + " for client " + cameraState.getClientName() 846 + " API Level " + cameraState.getApiLevel()); 847 } 848 849 updateActivityCount(cameraState); 850 } 851 852 @Override 853 public void notifyFeatureCombinationStats(CameraFeatureCombinationStats featureCombStats) { 854 if (!Flags.analytics24q3()) { 855 return; 856 } 857 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) { 858 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " 859 + " camera service UID!"); 860 return; 861 } 862 863 if (DEBUG) { 864 String combinationTypeStr = cameraFeatureCombinationTypeToString( 865 featureCombStats.mQueryType); 866 String combinationStr = cameraFeatureCombinationToString( 867 featureCombStats.mFeatureCombination); 868 Slog.v(TAG, "Camera " + featureCombStats.mCameraId 869 + " query " + combinationTypeStr 870 + " combination " + combinationStr 871 + " for client UID " + featureCombStats.mUid 872 + " returns " + featureCombStats.mStatus); 873 } 874 875 updateFeatureCombinationQuery(featureCombStats); 876 } 877 878 @Override 879 public boolean isCameraDisabled(int userId) { 880 if (Binder.getCallingUid() != Process.CAMERASERVER_UID) { 881 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() 882 + " doesn't match expected camera service UID!"); 883 return false; 884 } 885 final long ident = Binder.clearCallingIdentity(); 886 try { 887 DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); 888 if (dpm == null) { 889 Slog.e(TAG, "Failed to get the device policy manager service"); 890 return false; 891 } 892 try { 893 return dpm.getCameraDisabled(null, userId); 894 } catch (Exception e) { 895 e.printStackTrace(); 896 return false; 897 } 898 } finally { 899 Binder.restoreCallingIdentity(ident); 900 } 901 } 902 903 @Override 904 public void notifyWatchdog(int pid, boolean isNativePid) { 905 dumpStackTraces(pid, isNativePid); 906 } 907 908 @Override 909 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 910 String[] args, ShellCallback callback, ResultReceiver resultReceiver) 911 throws RemoteException { 912 new CSPShellCmd(CameraServiceProxy.this) 913 .exec(this, in, out, err, args, callback, resultReceiver); 914 } 915 916 private static class CSPShellCmd extends ShellCommand { 917 private static final String TAG = "CSPShellCmd"; 918 private static final String USAGE = """ 919 usage: cmd media.camera.proxy SUBCMD [args] 920 921 SUBCMDs: 922 dump_events: Write out all collected camera usage events to statsd. 923 Does not print to terminal. 924 help: You're reading it. 925 """; 926 927 private final CameraServiceProxy mCameraServiceProxy; 928 929 CSPShellCmd(CameraServiceProxy proxy) { 930 mCameraServiceProxy = proxy; 931 } 932 933 @Override 934 public int onCommand(String cmd) { 935 if (cmd == null) { 936 return handleDefaultCommands(cmd); 937 } 938 final PrintWriter pw = getOutPrintWriter(); 939 try { 940 switch (cmd.replace('-', '_')) { 941 case "dump_events": 942 int eventCount = mCameraServiceProxy.getUsageEventCount(); 943 mCameraServiceProxy.dumpCameraEvents(); 944 pw.println("Camera usage events dumped: " + eventCount); 945 break; 946 default: 947 return handleDefaultCommands(cmd); 948 } 949 } catch (Exception e) { 950 Slog.e(mCameraServiceProxy.TAG, "Error running shell command", e); 951 return 1; 952 } 953 return 0; 954 } 955 956 @Override 957 public void onHelp() { 958 getOutPrintWriter().println(USAGE); 959 } 960 } 961 }; 962 963 private final FoldStateListener mFoldStateListener; 964 CameraServiceProxy(Context context)965 public CameraServiceProxy(Context context) { 966 super(context); 967 mContext = context; 968 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false); 969 mHandlerThread.start(); 970 mHandler = new Handler(mHandlerThread.getLooper(), this); 971 972 mNotifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0) > 0; 973 if (DEBUG) Slog.v(TAG, "Notify NFC behavior is " + (mNotifyNfc ? "active" : "disabled")); 974 // Don't keep any extra logging threads if not needed 975 mLogWriterService.setKeepAliveTime(1, TimeUnit.SECONDS); 976 mLogWriterService.allowCoreThreadTimeOut(true); 977 978 mFoldStateListener = new FoldStateListener(mContext, folded -> { 979 if (folded) { 980 setDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED); 981 } else { 982 clearDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED); 983 } 984 }); 985 } 986 987 /** 988 * Sets the device state bits set within {@code deviceStateFlags} leaving all other bits the 989 * same. 990 * <p> 991 * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}. 992 * 993 * @param deviceStateFlags a bitmask of the device state bits that should be set. 994 * 995 * @see #clearDeviceStateFlags(int) 996 */ setDeviceStateFlags(@eviceStateFlags int deviceStateFlags)997 private void setDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) { 998 synchronized (mLock) { 999 mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE); 1000 mDeviceState |= deviceStateFlags; 1001 if (mDeviceState != mLastReportedDeviceState) { 1002 notifyDeviceStateWithRetriesLocked(RETRY_TIMES); 1003 } 1004 } 1005 } 1006 1007 /** 1008 * Clears the device state bits set within {@code deviceStateFlags} leaving all other bits the 1009 * same. 1010 * <p> 1011 * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}. 1012 * 1013 * @param deviceStateFlags a bitmask of the device state bits that should be cleared. 1014 * 1015 * @see #setDeviceStateFlags(int) 1016 */ clearDeviceStateFlags(@eviceStateFlags int deviceStateFlags)1017 private void clearDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) { 1018 synchronized (mLock) { 1019 mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE); 1020 mDeviceState &= ~deviceStateFlags; 1021 if (mDeviceState != mLastReportedDeviceState) { 1022 notifyDeviceStateWithRetriesLocked(RETRY_TIMES); 1023 } 1024 } 1025 } 1026 1027 @Override handleMessage(Message msg)1028 public boolean handleMessage(Message msg) { 1029 switch(msg.what) { 1030 case MSG_SWITCH_USER: { 1031 notifySwitchWithRetries(msg.arg1); 1032 } break; 1033 case MSG_NOTIFY_DEVICE_STATE: { 1034 notifyDeviceStateWithRetries(msg.arg1); 1035 } break; 1036 default: { 1037 Slog.e(TAG, "CameraServiceProxy error, invalid message: " + msg.what); 1038 } break; 1039 } 1040 return true; 1041 } 1042 1043 @Override onStart()1044 public void onStart() { 1045 mUserManager = UserManager.get(mContext); 1046 if (mUserManager == null) { 1047 // Should never see this unless someone messes up the SystemServer service boot order. 1048 throw new IllegalStateException("UserManagerService must start before" + 1049 " CameraServiceProxy!"); 1050 } 1051 1052 IntentFilter filter = new IntentFilter(); 1053 filter.addAction(Intent.ACTION_USER_ADDED); 1054 filter.addAction(Intent.ACTION_USER_REMOVED); 1055 filter.addAction(Intent.ACTION_USER_INFO_CHANGED); 1056 filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); 1057 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); 1058 filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 1059 filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 1060 mContext.registerReceiver(mIntentReceiver, filter); 1061 1062 publishBinderService(CAMERA_SERVICE_PROXY_BINDER_NAME, mCameraServiceProxy); 1063 publishLocalService(CameraServiceProxy.class, this); 1064 } 1065 1066 @Override onBootPhase(int phase)1067 public void onBootPhase(int phase) { 1068 if (phase == PHASE_BOOT_COMPLETED) { 1069 CameraStatsJobService.schedule(mContext); 1070 1071 try { 1072 int[] displayIds = WindowManagerGlobal.getWindowManagerService() 1073 .registerDisplayWindowListener(mDisplayWindowListener); 1074 for (int i = 0; i < displayIds.length; i++) { 1075 mDisplayWindowListener.onDisplayAdded(displayIds[i]); 1076 } 1077 } catch (RemoteException e) { 1078 Log.e(TAG, "Failed to register display window listener!"); 1079 } 1080 1081 mContext.getSystemService(DeviceStateManager.class) 1082 .registerCallback(new HandlerExecutor(mHandler), mFoldStateListener); 1083 } 1084 } 1085 1086 @Override onUserStarting(@onNull TargetUser user)1087 public void onUserStarting(@NonNull TargetUser user) { 1088 synchronized(mLock) { 1089 if (mEnabledCameraUsers == null) { 1090 // Initialize cameraserver, or update cameraserver if we are recovering 1091 // from a crash. 1092 switchUserLocked(user.getUserIdentifier()); 1093 } 1094 } 1095 } 1096 1097 @Override onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)1098 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 1099 synchronized(mLock) { 1100 switchUserLocked(to.getUserIdentifier()); 1101 } 1102 } 1103 1104 /** 1105 * Handle the death of the native camera service 1106 */ 1107 @Override binderDied()1108 public void binderDied() { 1109 if (DEBUG) Slog.w(TAG, "Native camera service has died"); 1110 synchronized(mLock) { 1111 mCameraServiceRaw = null; 1112 1113 // All cameras reset to idle on camera service death 1114 boolean wasEmpty = mActiveCameraUsage.isEmpty(); 1115 mActiveCameraUsage.clear(); 1116 1117 if ( mNotifyNfc && !wasEmpty ) { 1118 notifyNfcService(/*enablePolling*/ true); 1119 } 1120 } 1121 } 1122 1123 private class EventWriterTask implements Runnable { 1124 private List<CameraEvent> mEventList; 1125 private static final long WRITER_SLEEP_MS = 100; 1126 EventWriterTask(List<CameraEvent> eventList)1127 EventWriterTask(List<CameraEvent> eventList) { 1128 mEventList = eventList; 1129 } 1130 1131 @Override run()1132 public void run() { 1133 if (mEventList != null) { 1134 for (CameraEvent event : mEventList) { 1135 event.logSelf(); 1136 try { 1137 Thread.sleep(WRITER_SLEEP_MS); 1138 } catch (InterruptedException e) {} 1139 } 1140 mEventList.clear(); 1141 } 1142 } 1143 } 1144 1145 /** 1146 * Get camera usage event count 1147 */ getUsageEventCount()1148 int getUsageEventCount() { 1149 synchronized (mLock) { 1150 return mCameraEventHistory.size(); 1151 } 1152 } 1153 1154 /** 1155 * Dump camera events to log. 1156 * Package-private 1157 */ dumpCameraEvents()1158 void dumpCameraEvents() { 1159 synchronized(mLock) { 1160 // Randomize order of events so that it's not meaningful 1161 Collections.shuffle(mCameraEventHistory); 1162 mLogWriterService.execute(new EventWriterTask( 1163 new ArrayList(mCameraEventHistory))); 1164 1165 mCameraEventHistory.clear(); 1166 } 1167 final long ident = Binder.clearCallingIdentity(); 1168 try { 1169 CameraStatsJobService.schedule(mContext); 1170 } finally { 1171 Binder.restoreCallingIdentity(ident); 1172 } 1173 } 1174 1175 @Nullable getCameraServiceRawLocked()1176 private ICameraService getCameraServiceRawLocked() { 1177 if (mCameraServiceRaw == null) { 1178 IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME); 1179 if (cameraServiceBinder == null) { 1180 return null; 1181 } 1182 try { 1183 cameraServiceBinder.linkToDeath(this, /*flags*/ 0); 1184 } catch (RemoteException e) { 1185 Slog.w(TAG, "Could not link to death of native camera service"); 1186 return null; 1187 } 1188 1189 mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder); 1190 } 1191 return mCameraServiceRaw; 1192 } 1193 switchUserLocked(int userHandle)1194 private void switchUserLocked(int userHandle) { 1195 Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle); 1196 mLastUser = userHandle; 1197 if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) { 1198 // Some user handles have been added or removed, update cameraserver. 1199 mEnabledCameraUsers = currentUserHandles; 1200 notifySwitchWithRetriesLocked(RETRY_TIMES); 1201 } 1202 } 1203 isAutomotive()1204 private boolean isAutomotive() { 1205 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 1206 } 1207 getEnabledUserHandles(int currentUserHandle)1208 private Set<Integer> getEnabledUserHandles(int currentUserHandle) { 1209 int[] userProfiles = mUserManager.getEnabledProfileIds(currentUserHandle); 1210 Set<Integer> handles = new ArraySet<>(userProfiles.length); 1211 1212 for (int id : userProfiles) { 1213 handles.add(id); 1214 } 1215 1216 if (Flags.cameraHsumPermission()) { 1217 // If the device is running in headless system user mode then allow 1218 // User 0 to access camera only for automotive form factor. 1219 if (UserManager.isHeadlessSystemUserMode() && isAutomotive()) { 1220 handles.add(UserHandle.USER_SYSTEM); 1221 } 1222 } 1223 1224 return handles; 1225 } 1226 notifySwitchWithRetries(int retries)1227 private void notifySwitchWithRetries(int retries) { 1228 synchronized(mLock) { 1229 notifySwitchWithRetriesLocked(retries); 1230 } 1231 } 1232 notifySwitchWithRetriesLocked(int retries)1233 private void notifySwitchWithRetriesLocked(int retries) { 1234 if (mEnabledCameraUsers == null) { 1235 return; 1236 } 1237 if (notifyCameraserverLocked(ICameraService.EVENT_USER_SWITCHED, mEnabledCameraUsers)) { 1238 retries = 0; 1239 } 1240 if (retries <= 0) { 1241 return; 1242 } 1243 Slog.i(TAG, "Could not notify camera service of user switch, retrying..."); 1244 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null), 1245 RETRY_DELAY_TIME); 1246 } 1247 notifyCameraserverLocked(int eventType, Set<Integer> updatedUserHandles)1248 private boolean notifyCameraserverLocked(int eventType, Set<Integer> updatedUserHandles) { 1249 // Forward the user switch event to the native camera service running in the cameraserver 1250 // process. 1251 ICameraService cameraService = getCameraServiceRawLocked(); 1252 if (cameraService == null) { 1253 Slog.w(TAG, "Could not notify cameraserver, camera service not available."); 1254 return false; 1255 } 1256 1257 try { 1258 mCameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles)); 1259 } catch (RemoteException e) { 1260 Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e); 1261 // Not much we can do if camera service is dead. 1262 return false; 1263 } 1264 return true; 1265 } 1266 notifyDeviceStateWithRetries(int retries)1267 private void notifyDeviceStateWithRetries(int retries) { 1268 synchronized (mLock) { 1269 notifyDeviceStateWithRetriesLocked(retries); 1270 } 1271 } 1272 notifyDeviceStateWithRetriesLocked(int retries)1273 private void notifyDeviceStateWithRetriesLocked(int retries) { 1274 if (notifyDeviceStateChangeLocked(mDeviceState)) { 1275 return; 1276 } 1277 if (retries <= 0) { 1278 return; 1279 } 1280 Slog.i(TAG, "Could not notify camera service of device state change, retrying..."); 1281 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_NOTIFY_DEVICE_STATE, retries - 1, 1282 0, null), RETRY_DELAY_TIME); 1283 } 1284 notifyDeviceStateChangeLocked(@eviceStateFlags int deviceState)1285 private boolean notifyDeviceStateChangeLocked(@DeviceStateFlags int deviceState) { 1286 // Forward the state to the native camera service running in the cameraserver process. 1287 ICameraService cameraService = getCameraServiceRawLocked(); 1288 if (cameraService == null) { 1289 Slog.w(TAG, "Could not notify cameraserver, camera service not available."); 1290 return false; 1291 } 1292 1293 try { 1294 mCameraServiceRaw.notifyDeviceStateChange(deviceState); 1295 } catch (RemoteException e) { 1296 Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e); 1297 // Not much we can do if camera service is dead. 1298 return false; 1299 } 1300 mLastReportedDeviceState = deviceState; 1301 return true; 1302 } 1303 notifyUsbDeviceHotplugLocked(@onNull UsbDevice device, boolean attached)1304 private boolean notifyUsbDeviceHotplugLocked(@NonNull UsbDevice device, boolean attached) { 1305 // Only handle external USB camera devices 1306 if (device.getHasVideoCapture()) { 1307 // Forward the usb hotplug event to the native camera service running in the 1308 // cameraserver 1309 // process. 1310 ICameraService cameraService = getCameraServiceRawLocked(); 1311 if (cameraService == null) { 1312 Slog.w(TAG, "Could not notify cameraserver, camera service not available."); 1313 return false; 1314 } 1315 1316 try { 1317 int eventType = attached ? ICameraService.EVENT_USB_DEVICE_ATTACHED 1318 : ICameraService.EVENT_USB_DEVICE_DETACHED; 1319 mCameraServiceRaw.notifySystemEvent(eventType, new int[]{device.getDeviceId()}); 1320 } catch (RemoteException e) { 1321 Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e); 1322 // Not much we can do if camera service is dead. 1323 return false; 1324 } 1325 return true; 1326 } 1327 return false; 1328 } 1329 getMinFps(CameraSessionStats cameraState)1330 private float getMinFps(CameraSessionStats cameraState) { 1331 float maxFps = cameraState.getMaxPreviewFps(); 1332 return Math.max(Math.min(maxFps, MAX_PREVIEW_FPS), MIN_PREVIEW_FPS); 1333 } 1334 updateActivityCount(CameraSessionStats cameraState)1335 private void updateActivityCount(CameraSessionStats cameraState) { 1336 String cameraId = cameraState.getCameraId(); 1337 int newCameraState = cameraState.getNewCameraState(); 1338 int facing = cameraState.getFacing(); 1339 String clientName = cameraState.getClientName(); 1340 int apiLevel = cameraState.getApiLevel(); 1341 boolean isNdk = cameraState.isNdk(); 1342 int sessionType = cameraState.getSessionType(); 1343 int internalReconfigureCount = cameraState.getInternalReconfigureCount(); 1344 int latencyMs = cameraState.getLatencyMs(); 1345 long requestCount = cameraState.getRequestCount(); 1346 long resultErrorCount = cameraState.getResultErrorCount(); 1347 boolean deviceError = cameraState.getDeviceErrorFlag(); 1348 List<CameraStreamStats> streamStats = cameraState.getStreamStats(); 1349 String userTag = cameraState.getUserTag(); 1350 int videoStabilizationMode = cameraState.getVideoStabilizationMode(); 1351 boolean usedUltraWide = cameraState.getUsedUltraWide(); 1352 boolean usedZoomOverride = cameraState.getUsedZoomOverride(); 1353 long logId = cameraState.getLogId(); 1354 int sessionIdx = cameraState.getSessionIndex(); 1355 CameraExtensionSessionStats extSessionStats = cameraState.getExtensionSessionStats(); 1356 Range<Integer> mostRequestedFpsRange = Flags.analytics24q3() 1357 ? cameraState.getMostRequestedFpsRange() 1358 : new Range<Integer>(0, 0); 1359 1360 synchronized(mLock) { 1361 // Update active camera list and notify NFC if necessary 1362 boolean wasEmpty = mActiveCameraUsage.isEmpty(); 1363 switch (newCameraState) { 1364 case CameraSessionStats.CAMERA_STATE_OPEN: 1365 // Notify the audio subsystem about the facing of the most-recently opened 1366 // camera This can be used to select the best audio tuning in case video 1367 // recording with that camera will happen. Since only open events are used, if 1368 // multiple cameras are opened at once, the one opened last will be used to 1369 // select audio tuning. 1370 AudioManager audioManager = getContext().getSystemService(AudioManager.class); 1371 if (audioManager != null) { 1372 // Map external to front for audio tuning purposes 1373 String facingStr = (facing == CameraSessionStats.CAMERA_FACING_BACK) ? 1374 "back" : "front"; 1375 String facingParameter = "cameraFacing=" + facingStr; 1376 audioManager.setParameters(facingParameter); 1377 } 1378 CameraUsageEvent openEvent = new CameraUsageEvent( 1379 cameraId, facing, clientName, apiLevel, isNdk, 1380 FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__OPEN, 1381 latencyMs, sessionType, deviceError, logId, sessionIdx); 1382 mCameraEventHistory.add(openEvent); 1383 break; 1384 case CameraSessionStats.CAMERA_STATE_ACTIVE: 1385 // Check current active camera IDs to see if this package is already talking to 1386 // some camera 1387 boolean alreadyActivePackage = false; 1388 for (int i = 0; i < mActiveCameraUsage.size(); i++) { 1389 if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) { 1390 alreadyActivePackage = true; 1391 break; 1392 } 1393 } 1394 // If not already active, notify window manager about this new package using a 1395 // camera 1396 if (!alreadyActivePackage) { 1397 WindowManagerInternal wmi = 1398 LocalServices.getService(WindowManagerInternal.class); 1399 float minFps = getMinFps(cameraState); 1400 wmi.addRefreshRateRangeForPackage(clientName, 1401 minFps, MAX_PREVIEW_FPS); 1402 } 1403 1404 // Update activity events 1405 CameraUsageEvent newEvent = new CameraUsageEvent( 1406 cameraId, facing, clientName, apiLevel, isNdk, 1407 FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__SESSION, 1408 latencyMs, sessionType, deviceError, logId, sessionIdx); 1409 CameraUsageEvent oldEvent = mActiveCameraUsage.put(cameraId, newEvent); 1410 if (oldEvent != null) { 1411 Slog.w(TAG, "Camera " + cameraId + " was already marked as active"); 1412 oldEvent.markCompleted(/*internalReconfigure*/0, /*requestCount*/0, 1413 /*resultErrorCount*/0, /*deviceError*/false, streamStats, 1414 /*userTag*/"", /*videoStabilizationMode*/-1, /*usedUltraWide*/false, 1415 /*usedZoomOverride*/false, new Range<Integer>(0, 0), 1416 new CameraExtensionSessionStats()); 1417 mCameraEventHistory.add(oldEvent); 1418 } 1419 break; 1420 case CameraSessionStats.CAMERA_STATE_IDLE: 1421 case CameraSessionStats.CAMERA_STATE_CLOSED: 1422 CameraUsageEvent doneEvent = mActiveCameraUsage.remove(cameraId); 1423 if (doneEvent != null) { 1424 1425 doneEvent.markCompleted(internalReconfigureCount, requestCount, 1426 resultErrorCount, deviceError, streamStats, userTag, 1427 videoStabilizationMode, usedUltraWide, usedZoomOverride, 1428 mostRequestedFpsRange, extSessionStats); 1429 mCameraEventHistory.add(doneEvent); 1430 // Do not double count device error 1431 deviceError = false; 1432 1433 // Check current active camera IDs to see if this package is still 1434 // talking to some camera 1435 boolean stillActivePackage = false; 1436 for (int i = 0; i < mActiveCameraUsage.size(); i++) { 1437 if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) { 1438 stillActivePackage = true; 1439 break; 1440 } 1441 } 1442 // If not longer active, notify window manager about this package being done 1443 // with camera 1444 if (!stillActivePackage) { 1445 WindowManagerInternal wmi = 1446 LocalServices.getService(WindowManagerInternal.class); 1447 wmi.removeRefreshRateRangeForPackage(clientName); 1448 } 1449 } 1450 1451 if (newCameraState == CameraSessionStats.CAMERA_STATE_CLOSED) { 1452 CameraUsageEvent closeEvent = new CameraUsageEvent( 1453 cameraId, facing, clientName, apiLevel, isNdk, 1454 FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__CLOSE, 1455 latencyMs, sessionType, deviceError, logId, sessionIdx); 1456 mCameraEventHistory.add(closeEvent); 1457 } 1458 1459 if (mCameraEventHistory.size() > MAX_USAGE_HISTORY) { 1460 dumpCameraEvents(); 1461 } 1462 1463 break; 1464 } 1465 boolean isEmpty = mActiveCameraUsage.isEmpty(); 1466 if ( mNotifyNfc && (wasEmpty != isEmpty) ) { 1467 notifyNfcService(isEmpty); 1468 } 1469 } 1470 } 1471 updateFeatureCombinationQuery(CameraFeatureCombinationStats featureCombStats)1472 private void updateFeatureCombinationQuery(CameraFeatureCombinationStats featureCombStats) { 1473 synchronized (mLock) { 1474 CameraFeatureCombinationQueryEvent e = 1475 new CameraFeatureCombinationQueryEvent(featureCombStats); 1476 mCameraEventHistory.add(e); 1477 1478 if (mCameraEventHistory.size() > MAX_USAGE_HISTORY) { 1479 dumpCameraEvents(); 1480 } 1481 } 1482 } 1483 notifyNfcService(boolean enablePolling)1484 private void notifyNfcService(boolean enablePolling) { 1485 NfcManager nfcManager = mContext.getSystemService(NfcManager.class); 1486 if (nfcManager == null) { 1487 Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); 1488 return; 1489 } 1490 NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter(); 1491 if (nfcAdapter == null) { 1492 Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); 1493 return; 1494 } 1495 if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling); 1496 nfcAdapter.setReaderModePollingEnabled(enablePolling); 1497 } 1498 toArray(Collection<Integer> c)1499 private static int[] toArray(Collection<Integer> c) { 1500 int len = c.size(); 1501 int[] ret = new int[len]; 1502 int idx = 0; 1503 for (Integer i : c) { 1504 ret[idx++] = i; 1505 } 1506 return ret; 1507 } 1508 cameraStateToString(int newCameraState)1509 private static String cameraStateToString(int newCameraState) { 1510 switch (newCameraState) { 1511 case CameraSessionStats.CAMERA_STATE_OPEN: return "CAMERA_STATE_OPEN"; 1512 case CameraSessionStats.CAMERA_STATE_ACTIVE: return "CAMERA_STATE_ACTIVE"; 1513 case CameraSessionStats.CAMERA_STATE_IDLE: return "CAMERA_STATE_IDLE"; 1514 case CameraSessionStats.CAMERA_STATE_CLOSED: return "CAMERA_STATE_CLOSED"; 1515 default: break; 1516 } 1517 return "CAMERA_STATE_UNKNOWN"; 1518 } 1519 cameraFacingToString(int cameraFacing)1520 private static String cameraFacingToString(int cameraFacing) { 1521 switch (cameraFacing) { 1522 case CameraSessionStats.CAMERA_FACING_BACK: return "CAMERA_FACING_BACK"; 1523 case CameraSessionStats.CAMERA_FACING_FRONT: return "CAMERA_FACING_FRONT"; 1524 case CameraSessionStats.CAMERA_FACING_EXTERNAL: return "CAMERA_FACING_EXTERNAL"; 1525 default: break; 1526 } 1527 return "CAMERA_FACING_UNKNOWN"; 1528 } 1529 cameraHistogramTypeToString(int cameraHistogramType)1530 private static String cameraHistogramTypeToString(int cameraHistogramType) { 1531 switch (cameraHistogramType) { 1532 case CameraStreamStats.HISTOGRAM_TYPE_CAPTURE_LATENCY: 1533 return "HISTOGRAM_TYPE_CAPTURE_LATENCY"; 1534 default: 1535 break; 1536 } 1537 return "HISTOGRAM_TYPE_UNKNOWN"; 1538 } 1539 cameraFeatureCombinationTypeToString(int featureCombinationType)1540 private static String cameraFeatureCombinationTypeToString(int featureCombinationType) { 1541 switch (featureCombinationType) { 1542 case CameraFeatureCombinationStats.QueryType.QUERY_FEATURE_COMBINATION: 1543 return "QUERY_FEATURE_COMBINATION"; 1544 case CameraFeatureCombinationStats.QueryType.QUERY_SESSION_CHARACTERISTICS: 1545 return "QUERY_SESSION_CHARACTERISTICS"; 1546 default: 1547 break; 1548 } 1549 return "FEATURE_COMBINATION_TYPE_UNKNOWN"; 1550 } 1551 cameraFeatureCombinationToString(long featureCombination)1552 private static String cameraFeatureCombinationToString(long featureCombination) { 1553 StringBuilder combinationStr = new StringBuilder("{"); 1554 if ((featureCombination & CameraFeatureCombinationStats.CAMERA_FEATURE_60_FPS) != 0) { 1555 combinationStr.append("60fps "); 1556 } 1557 if ((featureCombination & CameraFeatureCombinationStats.CAMERA_FEATURE_STABILIZATION) 1558 != 0) { 1559 combinationStr.append("stabilization "); 1560 } 1561 if ((featureCombination & CameraFeatureCombinationStats.CAMERA_FEATURE_HLG10) != 0) { 1562 combinationStr.append("hlg10 "); 1563 } 1564 if ((featureCombination & CameraFeatureCombinationStats.CAMERA_FEATURE_JPEG) != 0) { 1565 combinationStr.append("jpeg "); 1566 } 1567 if ((featureCombination & CameraFeatureCombinationStats.CAMERA_FEATURE_JPEG_R) != 0) { 1568 combinationStr.append("jpeg_r "); 1569 } 1570 if ((featureCombination & CameraFeatureCombinationStats.CAMERA_FEATURE_4K) != 0) { 1571 combinationStr.append("4k "); 1572 } 1573 combinationStr.append("}"); 1574 1575 return combinationStr.toString(); 1576 } 1577 1578 // Which native services to dump into dropbox's stack traces 1579 private static final String[] NATIVE_SERVICES_OF_INTEREST = new String[] { 1580 "/system/bin/cameraserver", 1581 }; 1582 1583 // Which AIDL interfaces to dump into dropbox's stack traces 1584 private static final String[] AIDL_INTERFACE_PREFIXES_OF_INTEREST = new String[] { 1585 "android.hardware.camera.provider.ICameraProvider/", 1586 }; 1587 1588 // Which HIDL interfaces to dump into dropbox's stack traces 1589 public static final List<String> HIDL_INTERFACES_OF_INTEREST = Arrays.asList( 1590 "android.hardware.camera.provider@2.4::ICameraProvider" 1591 ); 1592 addHidlInterfacesOfInterest(Set<Integer> pids)1593 private static void addHidlInterfacesOfInterest(Set<Integer> pids) { 1594 try { 1595 IServiceManager serviceManager = IServiceManager.getService(); 1596 ArrayList<IServiceManager.InstanceDebugInfo> dump = 1597 serviceManager.debugDump(); 1598 for (IServiceManager.InstanceDebugInfo info : dump) { 1599 if (info.pid == IServiceManager.PidConstant.NO_PID) { 1600 continue; 1601 } 1602 1603 if (HIDL_INTERFACES_OF_INTEREST.contains(info.interfaceName)) { 1604 pids.add(info.pid); 1605 } 1606 } 1607 } catch (RemoteException e) { 1608 Slog.w(TAG, "Remote exception while querying HIDL service manager", e); 1609 } 1610 } 1611 matchesAidlInterfacePrefixes( String[] interfacePrefixes, String interfaceName)1612 private static boolean matchesAidlInterfacePrefixes( 1613 String[] interfacePrefixes, String interfaceName) { 1614 for (String prefix : interfacePrefixes) { 1615 if (interfaceName.startsWith(prefix)) { 1616 return true; 1617 } 1618 } 1619 return false; 1620 } 1621 addAidlInterfacesOfInterest(Set<Integer> pids)1622 private static void addAidlInterfacesOfInterest(Set<Integer> pids) { 1623 ServiceDebugInfo[] infos = ServiceManager.getServiceDebugInfo(); 1624 if (infos == null) return; 1625 1626 for (ServiceDebugInfo info : infos) { 1627 if (matchesAidlInterfacePrefixes( 1628 AIDL_INTERFACE_PREFIXES_OF_INTEREST, info.name)) { 1629 pids.add(info.debugPid); 1630 } 1631 } 1632 } 1633 1634 /** 1635 * Find the camera native Pids to dump stack traces. 1636 */ getRelevantNativePids()1637 private static Set<Integer> getRelevantNativePids() { 1638 HashSet<Integer> pids = new HashSet<Integer>(); 1639 addHidlInterfacesOfInterest(pids); 1640 addAidlInterfacesOfInterest(pids); 1641 1642 int[] nativePids = Process.getPidsForCommands(NATIVE_SERVICES_OF_INTEREST); 1643 if (nativePids != null) { 1644 for (int i : nativePids) { 1645 pids.add(i); 1646 } 1647 } 1648 1649 return pids; 1650 } 1651 1652 /** 1653 * A helper function to call StackTracesDumpHelper.dumpStackTraces(). 1654 */ dumpStackTraces(int pid, boolean isNativePid)1655 private static void dumpStackTraces(int pid, boolean isNativePid) { 1656 ArrayList<Integer> dalvikPids = new ArrayList<>(); 1657 ArrayList<Integer> nativePids = new ArrayList<>(); 1658 if (isNativePid) { 1659 nativePids.add(pid); 1660 } else { 1661 dalvikPids.add(pid); 1662 } 1663 1664 nativePids.addAll(getRelevantNativePids()); 1665 1666 StackTracesDumpHelper.dumpStackTraces(dalvikPids, 1667 /* processCpuTracker= */null, /* lastPids= */null, 1668 CompletableFuture.completedFuture(nativePids), 1669 /* logExceptionCreatingFile= */null, /* subject= */null, 1670 /* criticalEventSection= */null, /* extraHeaders= */ null, 1671 Runnable::run, /* latencyTracker= */null); 1672 } 1673 } 1674