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