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 <hidl/HidlTransportSupport.h>
17 #include <log/log.h>
18 #include <utils/SystemClock.h>
19 
20 #include "AnalyzeUseCase.h"
21 #include "ConfigManager.h"
22 
23 using android::hardware::configureRpcThreadpool;
24 using android::hardware::joinRpcThreadpool;
25 
26 namespace android {
27 namespace automotive {
28 namespace evs {
29 namespace support {
30 
AnalyzeUseCase(string cameraId,BaseAnalyzeCallback * callback)31 AnalyzeUseCase::AnalyzeUseCase(string cameraId, BaseAnalyzeCallback* callback)
32               : BaseUseCase(vector<string>(1, cameraId)),
33                 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 =
62                 mResourceManager->obtainStreamHandler(cameraId);
63             if (mStreamHandler.get() == nullptr) {
64                 ALOGE("Failed to get a valid StreamHandler for %s",
65                       cameraId.c_str());
66                 return false;
67             }
68 
69             mIsInitialized = true;
70             return true;
71         }
72     }
73 
74     ALOGE("Cannot find a match camera. Exiting");
75     return false;
76 }
77 
startVideoStream()78 bool AnalyzeUseCase::startVideoStream() {
79     ALOGD("AnalyzeUseCase::startVideoStream");
80 
81     // Initialize the use case.
82     if (!mIsInitialized && !initialize()) {
83         ALOGE("There is an error while initializing the use case. Exiting");
84         return false;
85     }
86 
87     ALOGD("Attach callback to StreamHandler");
88     if (mAnalyzeCallback != nullptr) {
89         mStreamHandler->attachAnalyzeCallback(mAnalyzeCallback);
90     }
91 
92     mStreamHandler->startStream();
93 
94     return true;
95 }
96 
stopVideoStream()97 void AnalyzeUseCase::stopVideoStream() {
98     ALOGD("AnalyzeUseCase::stopVideoStream");
99 
100     if (mStreamHandler == nullptr) {
101         ALOGE("Failed to detach render callback since stream handler is null");
102 
103         // Something may go wrong. Instead of to return this method right away,
104         // we want to finish the remaining logic of this method to try to
105         // release other resources.
106     } else {
107         mStreamHandler->detachAnalyzeCallback();
108     }
109 
110     if (mResourceManager == nullptr) {
111         ALOGE("Failed to release resources since resource manager is null");
112     } else {
113         mResourceManager->releaseStreamHandler(mCameraIds[0]);
114     }
115 
116     mStreamHandler = nullptr;
117 
118     // TODO(b/130246434): with the current logic, the initialize method will
119     // be triggered every time when a pair of
120     // stopVideoStream/startVideoStream is called. We might want to move
121     // some heavy work away from initialize method so increase the
122     // performance.
123 
124     // Sets mIsInitialzed to false so the initialize method will be
125     // triggered when startVideoStream is called again.
126     mIsInitialized = false;
127 }
128 
129 // TODO(b/130246434): For both Analyze use case and Display use case, return a
130 // pointer instead of an object.
createDefaultUseCase(string cameraId,BaseAnalyzeCallback * callback)131 AnalyzeUseCase AnalyzeUseCase::createDefaultUseCase(
132     string cameraId, BaseAnalyzeCallback* callback) {
133     return AnalyzeUseCase(cameraId, callback);
134 }
135 
136 }  // namespace support
137 }  // namespace evs
138 }  // namespace automotive
139 }  // namespace android
140 
141