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