1 /*
2  * Copyright (C) 2019 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 #include "AnalyzeUseCase.h"
17 
18 #include "ConfigManager.h"
19 
20 #include <hidl/HidlTransportSupport.h>
21 #include <log/log.h>
22 #include <utils/SystemClock.h>
23 
24 using android::hardware::configureRpcThreadpool;
25 using android::hardware::joinRpcThreadpool;
26 
27 namespace android {
28 namespace automotive {
29 namespace evs {
30 namespace support {
31 
AnalyzeUseCase(string cameraId,BaseAnalyzeCallback * callback)32 AnalyzeUseCase::AnalyzeUseCase(string cameraId, BaseAnalyzeCallback* callback) :
33       BaseUseCase(vector<string>(1, cameraId)), mAnalyzeCallback(callback) {}
34 
~AnalyzeUseCase()35 AnalyzeUseCase::~AnalyzeUseCase() {}
36 
initialize()37 bool AnalyzeUseCase::initialize() {
38     // TODO(b/130246434): Move the following ConfigManager and thread pool
39     // logic into ResourceManager, for both display and analyze use case.
40 
41     ConfigManager config;
42     if (!config.initialize("/system/etc/automotive/evs_support_lib/camera_config.json")) {
43         ALOGE("Missing or improper configuration for the EVS application.  Exiting.");
44         return false;
45     }
46 
47     // Set thread pool size to one to avoid concurrent events from the HAL.
48     // This pool will handle the EvsCameraStream callbacks.
49     // Note:  This _will_ run in parallel with the EvsListener run() loop below which
50     // runs the application logic that reacts to the async events.
51     configureRpcThreadpool(1, false /* callerWillJoin */);
52 
53     mResourceManager = ResourceManager::getInstance();
54 
55     ALOGD("Requesting camera list");
56     for (auto&& info : config.getCameras()) {
57         // This use case is currently a single camera use case.
58         // Only one element is available in the camera id list.
59         string cameraId = mCameraIds[0];
60         if (cameraId == info.cameraId) {
61             mStreamHandler = mResourceManager->obtainStreamHandler(cameraId);
62             if (mStreamHandler.get() == nullptr) {
63                 ALOGE("Failed to get a valid StreamHandler for %s", cameraId.c_str());
64                 return false;
65             }
66 
67             mIsInitialized = true;
68             return true;
69         }
70     }
71 
72     ALOGE("Cannot find a match camera. Exiting");
73     return false;
74 }
75 
startVideoStream()76 bool AnalyzeUseCase::startVideoStream() {
77     ALOGD("AnalyzeUseCase::startVideoStream");
78 
79     // Initialize the use case.
80     if (!mIsInitialized && !initialize()) {
81         ALOGE("There is an error while initializing the use case. Exiting");
82         return false;
83     }
84 
85     ALOGD("Attach callback to StreamHandler");
86     if (mAnalyzeCallback != nullptr) {
87         mStreamHandler->attachAnalyzeCallback(mAnalyzeCallback);
88     }
89 
90     mStreamHandler->startStream();
91 
92     return true;
93 }
94 
stopVideoStream()95 void AnalyzeUseCase::stopVideoStream() {
96     ALOGD("AnalyzeUseCase::stopVideoStream");
97 
98     if (mStreamHandler == nullptr) {
99         ALOGE("Failed to detach render callback since stream handler is null");
100 
101         // Something may go wrong. Instead of to return this method right away,
102         // we want to finish the remaining logic of this method to try to
103         // release other resources.
104     } else {
105         mStreamHandler->detachAnalyzeCallback();
106     }
107 
108     if (mResourceManager == nullptr) {
109         ALOGE("Failed to release resources since resource manager is null");
110     } else {
111         mResourceManager->releaseStreamHandler(mCameraIds[0]);
112     }
113 
114     mStreamHandler = nullptr;
115 
116     // TODO(b/130246434): with the current logic, the initialize method will
117     // be triggered every time when a pair of
118     // stopVideoStream/startVideoStream is called. We might want to move
119     // some heavy work away from initialize method so increase the
120     // performance.
121 
122     // Sets mIsInitialzed to false so the initialize method will be
123     // triggered when startVideoStream is called again.
124     mIsInitialized = false;
125 }
126 
127 // TODO(b/130246434): For both Analyze use case and Display use case, return a
128 // pointer instead of an object.
createDefaultUseCase(string cameraId,BaseAnalyzeCallback * callback)129 AnalyzeUseCase AnalyzeUseCase::createDefaultUseCase(string cameraId,
130                                                     BaseAnalyzeCallback* callback) {
131     return AnalyzeUseCase(cameraId, callback);
132 }
133 
134 }  // namespace support
135 }  // namespace evs
136 }  // namespace automotive
137 }  // namespace android
138