|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 //#define LOG_NDEBUG 0 |
|
8 #define LOG_TAG "MediaResourceManagerService" |
|
9 |
|
10 #include <binder/IServiceManager.h> |
|
11 #include <media/stagefright/foundation/AMessage.h> |
|
12 #include <utils/Log.h> |
|
13 |
|
14 #include "MediaResourceManagerClient.h" |
|
15 #include "MediaResourceManagerService.h" |
|
16 |
|
17 namespace android { |
|
18 |
|
19 /* static */ |
|
20 void MediaResourceManagerService::instantiate() { |
|
21 defaultServiceManager()->addService( |
|
22 String16("media.resource_manager"), new MediaResourceManagerService()); |
|
23 } |
|
24 |
|
25 MediaResourceManagerService::MediaResourceManagerService() |
|
26 : mVideoDecoderCount(VIDEO_DECODER_COUNT) |
|
27 { |
|
28 mLooper = new ALooper; |
|
29 mLooper->setName("MediaResourceManagerService"); |
|
30 |
|
31 mReflector = new AHandlerReflector<MediaResourceManagerService>(this); |
|
32 // Register AMessage handler to ALooper. |
|
33 mLooper->registerHandler(mReflector); |
|
34 // Start ALooper thread. |
|
35 mLooper->start(); |
|
36 } |
|
37 |
|
38 MediaResourceManagerService::~MediaResourceManagerService() |
|
39 { |
|
40 // Unregister AMessage handler from ALooper. |
|
41 mLooper->unregisterHandler(mReflector->id()); |
|
42 // Stop ALooper thread. |
|
43 mLooper->stop(); |
|
44 } |
|
45 |
|
46 void MediaResourceManagerService::binderDied(const wp<IBinder>& who) |
|
47 { |
|
48 if (who != NULL) { |
|
49 Mutex::Autolock autoLock(mLock); |
|
50 sp<IBinder> binder = who.promote(); |
|
51 if (binder != NULL) { |
|
52 cancelClientLocked(binder); |
|
53 } |
|
54 } |
|
55 } |
|
56 |
|
57 void MediaResourceManagerService::requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType) |
|
58 { |
|
59 if (resourceType != MediaResourceManagerClient::HW_VIDEO_DECODER) { |
|
60 // Support only HW_VIDEO_DECODER |
|
61 return; |
|
62 } |
|
63 |
|
64 { |
|
65 Mutex::Autolock autoLock(mLock); |
|
66 sp<IBinder> binder = client->asBinder(); |
|
67 mVideoCodecRequestQueue.push_back(binder); |
|
68 binder->linkToDeath(this); |
|
69 } |
|
70 |
|
71 sp<AMessage> notify = |
|
72 new AMessage(kNotifyRequest, mReflector->id()); |
|
73 // Post AMessage to MediaResourceManagerService via ALooper. |
|
74 notify->post(); |
|
75 } |
|
76 |
|
77 status_t MediaResourceManagerService::cancelClient(const sp<IMediaResourceManagerClient>& client) |
|
78 { |
|
79 { |
|
80 Mutex::Autolock autoLock(mLock); |
|
81 sp<IBinder> binder = client->asBinder(); |
|
82 cancelClientLocked(binder); |
|
83 } |
|
84 |
|
85 sp<AMessage> notify = |
|
86 new AMessage(kNotifyRequest, mReflector->id()); |
|
87 // Post AMessage to MediaResourceManagerService via ALooper. |
|
88 notify->post(); |
|
89 |
|
90 return NO_ERROR; |
|
91 } |
|
92 |
|
93 // Called on ALooper thread. |
|
94 void MediaResourceManagerService::onMessageReceived(const sp<AMessage> &msg) |
|
95 { |
|
96 Mutex::Autolock autoLock(mLock); |
|
97 |
|
98 // Exit if no request. |
|
99 if (mVideoCodecRequestQueue.empty()) { |
|
100 return; |
|
101 } |
|
102 |
|
103 // Check if resource is available |
|
104 int found = -1; |
|
105 for (int i=0 ; i<mVideoDecoderCount ; i++) { |
|
106 if (!mVideoDecoderSlots[i].mClient.get()) { |
|
107 found = i; |
|
108 } |
|
109 } |
|
110 |
|
111 // Exit if no resource is available. |
|
112 if (found == -1) { |
|
113 return; |
|
114 } |
|
115 |
|
116 // Assign resource to IMediaResourceManagerClient |
|
117 Fifo::iterator front(mVideoCodecRequestQueue.begin()); |
|
118 mVideoDecoderSlots[found].mClient = *front; |
|
119 mVideoCodecRequestQueue.erase(front); |
|
120 // Notify resource assignment to the client. |
|
121 sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(mVideoDecoderSlots[found].mClient); |
|
122 client->statusChanged(MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED); |
|
123 } |
|
124 |
|
125 void MediaResourceManagerService::cancelClientLocked(const sp<IBinder>& binder) |
|
126 { |
|
127 // Clear the request from request queue. |
|
128 Fifo::iterator it(mVideoCodecRequestQueue.begin()); |
|
129 while (it != mVideoCodecRequestQueue.end()) { |
|
130 if ((*it).get() == binder.get()) { |
|
131 mVideoCodecRequestQueue.erase(it); |
|
132 break; |
|
133 } |
|
134 it++; |
|
135 } |
|
136 |
|
137 // Clear the client from the resource |
|
138 for (int i=0 ; i<mVideoDecoderCount ; i++) { |
|
139 if (mVideoDecoderSlots[i].mClient.get() == binder.get()) { |
|
140 mVideoDecoderSlots[i].mClient = NULL; |
|
141 } |
|
142 } |
|
143 binder->unlinkToDeath(this); |
|
144 } |
|
145 |
|
146 }; // namespace android |
|
147 |