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 17 #ifndef ANDROID_MEDIA_ECO_SERVICE_H_ 18 #define ANDROID_MEDIA_ECO_SERVICE_H_ 19 20 #include <aidl/android/media/eco/BnECOService.h> 21 #include <android/binder_manager.h> 22 #include <android/binder_process.h> 23 #include <utils/Log.h> 24 #include <utils/Mutex.h> 25 26 #include <list> 27 28 #include "eco/ECODebug.h" 29 #include "eco/ECOSession.h" 30 31 namespace android { 32 namespace media { 33 namespace eco { 34 35 using aidl::android::media::eco::BnECOService; 36 using aidl::android::media::eco::ECOData; 37 using aidl::android::media::eco::ECODataStatus; 38 using android::media::eco::ECOSession; 39 using ndk::ScopedAStatus; 40 41 /** 42 * ECO (Encoder Camera Optimization) service. 43 * 44 * ECOService creates and manages EcoSession to relay feedback information between one or multiple 45 * ECOServiceStatsProvider and ECOServiceInfoListener. The relationship can be many-to-many. In 46 * general, ECOServiceStatsProvider extracts information from an encoder for a given encoding 47 * session. EcoSession then relays the encoder information to any subscribed 48 * ECOServiceInfoListener. 49 * 50 * Internally, ECOService creates an ECOSession for each encoding session. Upon start, both 51 * ECOServiceStatsProvider and ECOServiceInfoListener should call obtainSession to get the 52 * ECOSession instance. After that, ECOServiceStatsProvider should push Stats to ECOSession and 53 * ECOServiceInfoListener should listen to the info from ECOSession. Upon finish, both 54 * ECOServiceStatsProvider and ECOServiceInfoListener should remove themselves from ECOSession. 55 * Then ECOService will safely destroy the ECOSession. 56 */ 57 class ECOService : public BnECOService { 58 using ::ndk::ICInterface::dump; 59 60 public: 61 ECOService(); 62 63 virtual ~ECOService() = default; 64 65 virtual ScopedAStatus obtainSession(int32_t width, int32_t height, bool isCameraRecording, 66 std::shared_ptr<IECOSession>* _aidl_return); 67 68 virtual ScopedAStatus getNumOfSessions(int32_t* _aidl_return); 69 70 virtual ScopedAStatus getSessions(std::vector<::ndk::SpAIBinder>* _aidl_return); 71 instantiate()72 static status_t instantiate() { 73 std::shared_ptr<ECOService> service = ::ndk::SharedRefBase::make<ECOService>(); 74 binder_status_t status = 75 AServiceManager_addService(service->asBinder().get(), getServiceName()); 76 ABinderProcess_startThreadPool(); 77 return (status == EX_NONE) ? STATUS_OK : STATUS_UNKNOWN_ERROR; 78 } 79 80 // Implementation of BinderService<T> getServiceName()81 static char const* getServiceName() { return "media.ecoservice"; } 82 83 // IBinder::DeathRecipient implementation 84 virtual void binderDied(const std::weak_ptr<AIBinder>& who); 85 86 virtual status_t dump(int fd, const std::vector<std::string>& args); 87 88 private: 89 // Lock guarding ECO service state 90 Mutex mServiceLock; 91 92 struct SessionConfig { 93 int32_t mWidth; 94 int32_t mHeight; 95 bool mIsCameraRecording; 96 SessionConfigSessionConfig97 SessionConfig(int w, int h, bool isCameraRecording) 98 : mWidth(w), mHeight(h), mIsCameraRecording(isCameraRecording) {} 99 100 bool operator==(const SessionConfig& cfg) { 101 return mWidth == cfg.mWidth && mHeight == cfg.mHeight && 102 mIsCameraRecording == cfg.mIsCameraRecording; 103 } 104 }; 105 106 friend bool operator==(const SessionConfig& p1, const SessionConfig& p2) { 107 return p1.mWidth == p2.mWidth && p1.mHeight == p2.mHeight && 108 p1.mIsCameraRecording == p2.mIsCameraRecording; 109 } 110 111 // Hash function for mSessionConfigToSessionMap. 112 // TODO(hkuang): Add test for this hash function. 113 struct SessionConfigHash { operatorSessionConfigHash114 size_t operator()(const SessionConfig& cfg) const { 115 // Generate a hash by bit shifting and concatenation. 116 return cfg.mWidth | (cfg.mHeight << 16) | ((int32_t)cfg.mIsCameraRecording << 31); 117 } 118 }; 119 120 // Map from SessionConfig to session. 121 std::unordered_map<SessionConfig, std::weak_ptr<ECOSession>, SessionConfigHash> 122 mSessionConfigToSessionMap; 123 124 using MapIterType = std::unordered_map<SessionConfig, std::weak_ptr<ECOSession>, 125 SessionConfigHash>::iterator; 126 127 // A helpful function to traverse the mSessionConfigToSessionMap, remove the entry that 128 // does not exist any more and call |callback| when the entry is valid. 129 void SanitizeSession(const std::function<void(MapIterType it)>& callback); 130 }; 131 132 } // namespace eco 133 } // namespace media 134 } // namespace android 135 136 #endif // ANDROID_MEDIA_ECO_SERVICE_H_ 137