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