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