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