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