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