• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 
17 package android.hardware.camera2.utils;
18 
19 import android.annotation.NonNull;
20 import android.hardware.CameraExtensionSessionStats;
21 import android.hardware.camera2.CameraManager;
22 import android.util.Log;
23 
24 import java.util.concurrent.ExecutorService;
25 import java.util.concurrent.Executors;
26 
27 /**
28  * Utility class to aggregate metrics specific to Camera Extensions and pass them to
29  * {@link CameraManager}. {@link android.hardware.camera2.CameraExtensionSession} should call
30  * {@link #commit} before closing the session.
31  *
32  * @hide
33  */
34 public class ExtensionSessionStatsAggregator {
35     private static final boolean DEBUG = false;
36     private static final String TAG = ExtensionSessionStatsAggregator.class.getSimpleName();
37 
38     private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
39 
40     private final Object mLock = new Object(); // synchronizes access to all fields of the class
41     private boolean mIsDone = false; // marks the aggregator as "done".
42                                      // Mutations and commits become no-op if this is true.
43     private final CameraExtensionSessionStats mStats;
44 
ExtensionSessionStatsAggregator(@onNull String cameraId, boolean isAdvanced)45     public ExtensionSessionStatsAggregator(@NonNull String cameraId, boolean isAdvanced) {
46         if (DEBUG) {
47             Log.v(TAG, "Creating new Extension Session Stats Aggregator");
48         }
49         mStats = new CameraExtensionSessionStats();
50         mStats.key = "";
51         mStats.cameraId = cameraId;
52         mStats.isAdvanced = isAdvanced;
53     }
54 
55     /**
56      * Set client package name
57      *
58      * @param clientName package name of the client that these stats are associated with.
59      */
setClientName(@onNull String clientName)60     public void setClientName(@NonNull String clientName) {
61         synchronized (mLock) {
62             if (mIsDone) {
63                 return;
64             }
65             if (DEBUG) {
66                 Log.v(TAG, "Setting clientName: " + clientName);
67             }
68             mStats.clientName = clientName;
69         }
70     }
71 
72     /**
73      * Set the capture format.
74      *
75      * @param format Format of requested capture.
76      */
setCaptureFormat(int format)77     public void setCaptureFormat(int format) {
78         synchronized (mLock) {
79             if (mIsDone) {
80                 return;
81             }
82             if (DEBUG) {
83                 Log.v(TAG, "Setting capture format: " + format);
84             }
85             mStats.captureFormat = format;
86         }
87     }
88 
89     /**
90      * Set extension type.
91      *
92      * @param extensionType Type of extension. Must match one of
93      *                      {@code CameraExtensionCharacteristics#EXTENSION_*}
94      */
setExtensionType(int extensionType)95     public void setExtensionType(int extensionType) {
96         synchronized (mLock) {
97             if (mIsDone) {
98                 return;
99             }
100             if (DEBUG) {
101                 Log.v(TAG, "Setting type: " + extensionType);
102             }
103             mStats.type = extensionType;
104         }
105     }
106 
107     /**
108      * Asynchronously commits the stats to CameraManager on a background thread.
109      *
110      * @param isFinal marks the stats as final and prevents any further commits or changes. This
111      *                should be set to true when the stats are considered final for logging,
112      *                for example right before the capture session is about to close
113      */
commit(boolean isFinal)114     public void commit(boolean isFinal) {
115         // Call binder on a background thread to reduce latencies from metrics logging.
116         mExecutor.execute(() -> {
117             synchronized (mLock) {
118                 if (mIsDone) {
119                     return;
120                 }
121                 mIsDone = isFinal;
122                 if (DEBUG) {
123                     Log.v(TAG, "Committing: " + prettyPrintStats(mStats));
124                 }
125                 mStats.key = CameraManager.reportExtensionSessionStats(mStats);
126             }
127         });
128     }
129 
prettyPrintStats(@onNull CameraExtensionSessionStats stats)130     private static String prettyPrintStats(@NonNull CameraExtensionSessionStats stats) {
131         return CameraExtensionSessionStats.class.getSimpleName() + ":\n"
132                 + "  key: '" + stats.key + "'\n"
133                 + "  cameraId: '" + stats.cameraId + "'\n"
134                 + "  clientName: '" + stats.clientName + "'\n"
135                 + "  type: '" + stats.type + "'\n"
136                 + "  isAdvanced: '" + stats.isAdvanced + "'\n"
137                 + "  captureFormat: '" + stats.captureFormat + "'\n";
138     }
139 
140     /**
141      * Return the current statistics key
142      *
143      * @return the current statistics key
144      */
getStatsKey()145     public String getStatsKey() {
146         return mStats.key;
147     }
148 }
149