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