e1d3a908729591071bc0c0baf6106b85b7a34bbe
[platform/core/multimedia/mm-resource-manager.git] / src / lib / mm_resource_manager_priv.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
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 #include "common/mm_resource_manager_utils.h"
18 #include "lib/mm_resource_manager_priv.h"
19 #include "common/mm_resource_manager_dbus.h"
20
21 static GMutex handles_lock;
22 static GPtrArray *handles;
23
24 #define MM_RESOURCE_MANAGER(x) ((mm_resource_manager_s *) (x))
25 #define MM_RESOURCE_MANAGER_CHECK(x) \
26         MM_RM_UNLOCK_RETVM_IF(!__check_rm_handle(x), handles_lock, \
27                 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, \
28                 "Invalid resource manager handle %p", x)
29 #define MM_RESOURCE_MANAGER_RESERVED_RES_ARRAY_SIZE 128
30 #define MM_RESOURCE_MANAGER_RESERVED_HANDLE_ARRAY_SIZE 64
31 #define MM_RESOURCE_MANAGER_RES_NOT_FOUND -1
32
33
34
35 typedef enum {
36         MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE,   /* uncommitted */
37         MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED,      /* committed   */
38         MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE    /* uncommitted */
39 } mm_resource_manager_res_state_e;
40
41 typedef struct {
42         void *cb;
43         void *user_data;
44         gboolean is_invoked;
45 } mm_resource_manager_cb_s;
46
47 typedef struct {
48         mm_resource_manager_id handle_id;
49         mm_resource_manager_res_type_e type;
50         mm_resource_manager_res_volume volume;
51         mm_resource_manager_res_state_e state;
52         gboolean is_acquire_failed;
53 } mm_resource_manager_res_s;
54 typedef mm_resource_manager_res_s *mm_resource_manager_res_p;
55
56 typedef struct {
57         mm_resource_manager_id id;
58
59         GPtrArray *resources;
60
61         mm_resource_manager_cb_s release_cb;
62         mm_resource_manager_cb_s status_cb;
63         int pid;
64
65         GMutex resources_lock;
66
67         gboolean is_release_marked[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
68
69         mm_resource_manager_res_volume __max_resource_volumes
70                 [MM_RESOURCE_MANAGER_RES_TYPE_MAX];
71         mm_resource_manager_res_volume __condition_volumes
72                 [MM_RESOURCE_MANAGER_RES_TYPE_MAX]
73                 [MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX];
74         int __max_instance[MM_RESOURCE_MANAGER_RES_TYPE_MAX];
75
76         MMResourceManager *dbus_proxy;
77
78         GMainContext *dispatcher_context;
79         GMainLoop *dispatcher_loop;
80         GThread *dispatcher_thread;
81 } mm_resource_manager_s;
82
83 static const char *res_state_str[] = {
84         "FOR ACQUIRE",
85         "ACQUIRED",
86         "FOR RELEASE",
87 };
88
89 static void __init_lib() __attribute__((constructor));
90 static void __deinit_lib() __attribute__((destructor));
91 static int __check_resource(mm_resource_manager_s *rm, mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume);
92 static int __create_resource(mm_resource_manager_s *rm, mm_resource_manager_res_type_e type,
93                 mm_resource_manager_res_volume volume, mm_resource_manager_res_p *res);
94 static void __destroy_resource(void *res);
95 static int __get_resource_index(mm_resource_manager_s *rm,
96                 mm_resource_manager_res_p res);
97  /* FALSE if resource is destroyed */
98 static gboolean __mark_resource_for_release(GPtrArray *resources, int index, mm_resource_manager_res_p resource);
99 static int __send_release_cb_sync(mm_resource_manager_id id);
100 static void __mm_resource_manager_release_callback(mm_resource_manager_s *handle,
101                 mm_resource_manager_id id, mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume);
102 static void __mm_resource_manager_status_callback(mm_resource_manager_s *handle, mm_resource_manager_status_e status);
103 static void __mm_resource_handles_lock(void);
104 static void __mm_resource_handles_unlock(void);
105 static void __mm_resources_lock(mm_resource_manager_s *h);
106 static void __mm_resources_unlock(mm_resource_manager_s *h);
107
108
109 static int __dbus_init(mm_resource_manager_s *handle);
110 static int __dbus_deinit(mm_resource_manager_s *handle);
111 static int __dbus_init_conf(mm_resource_manager_s *handle);
112 static gboolean __check_rm_handle(mm_resource_manager_s *handle);
113 static int __dbus_create(mm_resource_manager_s *handle, mm_resource_manager_app_class_e app_class);
114 static int __dbus_destroy(mm_resource_manager_s *handle);
115 static int __dbus_commit(mm_resource_manager_s *handle);
116 static void __dbus_release_callback(MMResourceManager *object, guint64 arg_id, gint arg_resource_type, gint arg_volume);
117 static void __dbus_status_callback(MMResourceManager *object, gint arg_status);
118 static gpointer __dispatcher_thread(gpointer user_data);
119 static void __destroy_dispatcher(mm_resource_manager_s *handle);
120
121
122 int _mm_resource_manager_create(mm_resource_manager_app_class_e app_class,
123                 mm_resource_manager_release_cb cb, void *cb_data, mm_resource_manager_h *rm)
124 {
125         mm_resource_manager_s *handle = *rm = NULL;
126         int ret;
127         GError *error = NULL;
128
129         handle = (mm_resource_manager_s *) calloc(1, sizeof(mm_resource_manager_s));
130         MM_RM_RETVM_IF(NULL == handle, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Error allocating memory for Handle");
131
132         handle->dispatcher_context = g_main_context_new();
133         if (!handle->dispatcher_context) {
134                 free(handle);
135                 MM_RM_ERROR("g_main_context_new failed");
136                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
137         }
138         MM_RM_INFO("new main context %p", handle->dispatcher_context);
139
140         handle->dispatcher_loop = g_main_loop_new(handle->dispatcher_context, FALSE);
141         if (!handle->dispatcher_loop) {
142                 g_main_context_unref(handle->dispatcher_context);
143                 free(handle);
144                 MM_RM_ERROR("g_main_loop_new failed");
145                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
146         }
147         MM_RM_INFO("new main loop %p", handle->dispatcher_loop);
148
149         ret = __dbus_init(handle);
150         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
151                 __destroy_dispatcher(handle);
152                 free(handle);
153                 MM_RM_ERROR("Error initializing dbus client");
154                 return ret;
155         }
156
157         handle->dispatcher_thread = g_thread_try_new("mmrm:dispatcher", __dispatcher_thread, handle->dispatcher_loop, &error);
158         if (!handle->dispatcher_thread) {
159                 if (error) {
160                         MM_RM_ERROR("dispatcher_thread creation failed : %s", error->message);
161                         g_error_free(error);
162                 }
163                 __destroy_dispatcher(handle);
164                 free(handle);
165                 return MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH;
166         }
167         MM_RM_INFO("new dispatcher thread %p", handle->dispatcher_thread);
168
169         ret = __dbus_init_conf(handle);
170         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
171                 __destroy_dispatcher(handle);
172                 free(handle);
173                 MM_RM_ERROR("Configuration cannot be requested");
174                 return ret;
175         }
176
177         ret = __dbus_create(handle, app_class);
178         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
179                 __destroy_dispatcher(handle);
180                 free(handle);
181                 MM_RM_ERROR("Dbus create request failed");
182                 return ret;
183         }
184
185         handle->release_cb.cb = cb;
186         handle->release_cb.user_data = cb_data;
187
188         handle->resources = g_ptr_array_new_full(MM_RESOURCE_MANAGER_RESERVED_RES_ARRAY_SIZE, __destroy_resource);
189
190         g_mutex_init(&handle->resources_lock);
191
192         *rm = (mm_resource_manager_h *) handle;
193
194         MM_RM_INFO("adding handle %p", handle);
195
196         __mm_resource_handles_lock();
197         g_ptr_array_add(handles, handle);
198
199         MM_RM_INFO("RM #%"PRIu64" is created (%p)", _mm_rm_hash64(handle->id), handle);
200         __mm_resource_handles_unlock();
201
202         return MM_RESOURCE_MANAGER_ERROR_NONE;
203 }
204
205 int _mm_resource_manager_destroy(mm_resource_manager_h rm)
206 {
207         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
208         mm_resource_manager_id id;
209         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
210
211         MM_RM_INFO("Enter %p", rm);
212
213         __mm_resource_handles_lock();
214         MM_RESOURCE_MANAGER_CHECK(handle);
215         g_ptr_array_remove_fast(handles, handle);
216         __mm_resources_lock(handle);
217         __mm_resource_handles_unlock();
218
219         id = handle->id;
220
221         MM_RM_INFO("RM #%"PRIu64" will be destroyed", _mm_rm_hash64(id));
222
223         ret = __dbus_destroy(handle);
224         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
225                 MM_RM_ERROR("Dbus destroy request failed 0x%x", ret);
226
227         __destroy_dispatcher(handle);
228
229         g_ptr_array_free(handle->resources, TRUE);
230         __mm_resources_unlock(handle);
231
232         g_mutex_clear(&handle->resources_lock);
233         free(handle);
234
235         if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
236                 MM_RM_INFO("RM #%"PRIu64" is destroyed", _mm_rm_hash64(id));
237
238         return ret;
239 }
240
241 int _mm_resource_manager_mark_for_acquire(mm_resource_manager_h rm, mm_resource_manager_res_type_e type,
242                 mm_resource_manager_res_volume volume, mm_resource_manager_res_h *resource_h)
243 {
244         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
245         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
246         mm_resource_manager_res_p resource;
247
248         MM_RM_INFO("Enter %p", rm);
249
250         __mm_resource_handles_lock();
251         MM_RESOURCE_MANAGER_CHECK(handle);
252         if (handle->release_cb.is_invoked) {
253                 MM_RM_ERROR("RM #%"PRIu64" is releasing resource, so resource manager can't support your acquire request",
254                         _mm_rm_hash64(handle->id));
255                 __mm_resource_handles_unlock();
256                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
257         }
258         __mm_resources_lock(handle);
259         __mm_resource_handles_unlock();
260
261         ret = __create_resource(handle, type, volume, &resource);
262         MM_RM_UNLOCK_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE, handle->resources_lock, ret, "Resource cannot be created");
263         g_ptr_array_add(handle->resources, resource);
264
265         *resource_h = resource;
266
267         MM_RM_DEBUG("Resource %p of type %d with volume %d is marked for acquire in RM #%"PRIu64,
268                 *resource_h, type, volume, _mm_rm_hash64(handle->id));
269         __mm_resources_unlock(handle);
270
271         return ret;
272 }
273
274 int _mm_resource_manager_resize_marked(mm_resource_manager_h rm,
275                 mm_resource_manager_res_h resource_h, mm_resource_manager_res_volume new_volume)
276 {
277         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
278         mm_resource_manager_res_p resource = (mm_resource_manager_res_p) resource_h;
279         mm_resource_manager_res_p tmp_resource;
280         mm_resource_manager_res_volume add_volume;
281         int idx;
282         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
283
284         MM_RM_INFO("Enter %p", rm);
285
286         __mm_resource_handles_lock();
287         MM_RESOURCE_MANAGER_CHECK(handle);
288         __mm_resources_lock(handle);
289         __mm_resource_handles_unlock();
290
291         idx = __get_resource_index(handle, resource);
292         MM_RM_UNLOCK_RETVM_IF(idx == MM_RESOURCE_MANAGER_RES_NOT_FOUND, handle->resources_lock,
293                 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Invalid resource handle");
294         if (new_volume == resource->volume) {
295                 __mm_resources_unlock(handle);
296                 MM_RM_DEBUG("New volume equals the old. Resize is not needed.");
297                 return ret;
298         }
299
300         add_volume = resource->volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL && new_volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL &&
301                         resource->volume < new_volume ? (new_volume - resource->volume) : 0;
302
303         switch (resource->state) {
304         case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
305                 if (add_volume > 0) {
306                         ret = __check_resource(handle, resource->type, add_volume);
307                         MM_RM_UNLOCK_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE, handle->resources_lock, ret, "Resource check failed");
308                 }
309                 resource->volume = new_volume;
310                 break;
311
312         case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
313         case MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED:
314                 ret = __create_resource(handle, resource->type, add_volume, &tmp_resource);
315                 MM_RM_UNLOCK_RETVM_IF(ret != MM_RESOURCE_MANAGER_ERROR_NONE, handle->resources_lock, ret, "Resource cannot be created");
316
317                 tmp_resource->volume = resource->volume;
318                 tmp_resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
319
320                 g_ptr_array_add(handle->resources, resource);
321                 resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE;
322                 resource->volume = new_volume;
323
324                 handle->resources->pdata[idx] = tmp_resource;
325                 break;
326         }
327
328         MM_RM_INFO("Resource %p is resized for acquire in RM #%"PRIu64, resource_h, _mm_rm_hash64(handle->id));
329         __mm_resources_unlock(handle);
330
331         return ret;
332 }
333
334 int _mm_resource_manager_mark_for_release(mm_resource_manager_h rm, mm_resource_manager_res_h resource_h)
335 {
336         mm_resource_manager_s *handle;
337         mm_resource_manager_res_p resource;
338         mm_resource_manager_id handle_id;
339         int idx = 0;
340         const char *res_name = NULL;
341
342         MM_RM_INFO("Enter %p", rm);
343
344         __mm_resource_handles_lock();
345
346         handle = MM_RESOURCE_MANAGER(rm);
347         MM_RESOURCE_MANAGER_CHECK(handle);
348         handle_id = handle->id;
349         MM_RM_HASH64(handle_id);
350
351         resource = (mm_resource_manager_res_p)resource_h;
352
353         MM_RM_RETVM_IF(resource->type < MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER ||
354                 resource->type >= MM_RESOURCE_MANAGER_RES_TYPE_MAX,
355                 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Type [%d] is out of range", resource->type);
356         MM_RM_RETVM_IF(resource->state < MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE ||
357                 resource->state >= MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE,
358                 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "State [%d] is out of range or already released", resource->state);
359
360         res_name = _mm_resource_manager_get_res_str(resource->type);
361
362         MM_RM_DEBUG("[invoked : %d state : %s] Resource %p is marked for release in resource #%"PRIu64,
363                 handle->release_cb.is_invoked, res_state_str[resource->state], resource_h, handle_id);
364
365         if (handle_id != _mm_rm_hash64(resource->handle_id))
366                 MM_RM_INFO("handle RM #%"PRIu64" is not resource RM #%"PRIu64, handle_id, _mm_rm_hash64(resource->handle_id));
367
368         /* FIXME : We should consider resource lock's vulnerability because of using global variable of 'handles_lock' */
369         if (handle->release_cb.is_invoked) {
370                 MM_RM_DEBUG("Skip resource %p (%s) of RM #%"PRIu64" because release cb will be executed soon", resource, res_name, handle_id);
371                 __mm_resource_handles_unlock();
372                 resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
373                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
374         }
375
376         handle->is_release_marked[resource->type] = TRUE;
377         MM_RM_INFO("(%s) is marked for release in RM #%"PRIu64, res_name, handle_id);
378
379         __mm_resources_lock(handle);
380         __mm_resource_handles_unlock();
381
382         idx = __get_resource_index(handle, resource);
383         MM_RM_UNLOCK_RETVM_IF(idx == MM_RESOURCE_MANAGER_RES_NOT_FOUND,
384                         handle->resources_lock, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Invalid resource handle");
385
386         MM_RM_UNLOCK_RETVM_IF(!__mark_resource_for_release(handle->resources, idx, resource),
387                         handle->resources_lock, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Not in a release state");
388
389         __mm_resources_unlock(handle);
390
391         MM_RM_INFO("RM #%"PRIu64" is completed to mark", handle_id);
392
393         return MM_RESOURCE_MANAGER_ERROR_NONE;
394 }
395
396 int _mm_resource_manager_release_other_resources(mm_resource_manager_s *handle)
397 {
398         int idx;
399         int ret;
400         int len;
401
402         MM_RM_INFO("Enter %p", handle);
403
404         MM_RM_RETVM_IF(NULL == handle, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "NULL handle pointer");
405         handle->release_cb.is_invoked = TRUE;
406         MM_RM_INFO("other resource is released RM #%"PRIu64, _mm_rm_hash64(handle->id));
407
408         len = handle->resources->len;
409
410         for (idx = 0; idx < len; idx++) {
411                 if (!__mark_resource_for_release(handle->resources, idx, (mm_resource_manager_res_p) handle->resources->pdata[idx]))
412                         MM_RM_INFO("[idx %d] resource length %d", idx, len);
413         }
414
415         MM_RM_INFO("[RELEASE] dbus_commit");
416         ret = __dbus_commit(handle);
417         if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
418                 MM_RM_DEBUG("Changes in RM #%"PRIu64" have been committed successfully", _mm_rm_hash64(handle->id));
419         else
420                 MM_RM_ERROR("Dbus commit request failed");
421
422         MM_RM_INFO("All resources are marked for release in RM #%"PRIu64, _mm_rm_hash64(handle->id));
423
424         return ret;
425 }
426
427 int _mm_resource_manager_mark_all_for_release(mm_resource_manager_h rm)
428 {
429         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
430         int idx;
431         int len;
432
433         MM_RM_INFO("Enter %p", rm);
434
435         __mm_resource_handles_lock();
436         MM_RESOURCE_MANAGER_CHECK(handle);
437         if (handle->release_cb.is_invoked) {
438                 MM_RM_ERROR("RM #%"PRIu64" is releasing resource, so resource manager can't support your mark all for release",
439                         _mm_rm_hash64(handle->id));
440                 __mm_resource_handles_unlock();
441                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
442         }
443         __mm_resources_lock(handle);
444         __mm_resource_handles_unlock();
445
446         len = handle->resources->len;
447
448         for (idx = 0; idx < len; idx++) {
449                 if (!__mark_resource_for_release(handle->resources, idx, (mm_resource_manager_res_p) handle->resources->pdata[idx])) {
450                         MM_RM_WARNING("[idx %d] resource is already marked or released", idx);
451                         __mm_resources_unlock(handle);
452                         return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
453                 }
454                 handle->is_release_marked[idx] = TRUE;
455         }
456
457         MM_RM_INFO("All resources are marked for release in RM #%"PRIu64, _mm_rm_hash64(handle->id));
458         __mm_resources_unlock(handle);
459
460         return MM_RESOURCE_MANAGER_ERROR_NONE;
461 }
462
463 int _mm_resource_manager_get_resource_info(mm_resource_manager_h rm,
464                 mm_resource_manager_res_h resource_h, mm_resource_manager_res_info_s *info)
465 {
466         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
467         mm_resource_manager_res_p resource = (mm_resource_manager_res_p) resource_h;
468         int idx;
469
470         MM_RM_INFO("Enter %p", rm);
471
472         __mm_resource_handles_lock();
473         MM_RESOURCE_MANAGER_CHECK(handle);
474         __mm_resources_lock(handle);
475         __mm_resource_handles_unlock();
476
477         idx = __get_resource_index(handle, resource);
478         MM_RM_UNLOCK_RETVM_IF(idx == MM_RESOURCE_MANAGER_RES_NOT_FOUND, handle->resources_lock,
479                 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "Invalid RM #%"PRIu64"", _mm_rm_hash64(handle->id));
480
481         info->type = resource->type;
482         info->volume = resource->volume;
483         info->is_acquire_failed = resource->is_acquire_failed;
484
485         MM_RM_INFO("Info structure of resource %p in RM #%"PRIu64" is filled", resource_h, _mm_rm_hash64(handle->id));
486         __mm_resources_unlock(handle);
487
488         return MM_RESOURCE_MANAGER_ERROR_NONE;
489 }
490
491 int _mm_resource_manager_commit(mm_resource_manager_h rm)
492 {
493         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
494         int ret;
495
496         MM_RM_INFO("Enter %p", rm);
497
498         __mm_resource_handles_lock();
499         MM_RESOURCE_MANAGER_CHECK(handle);
500         if (handle->release_cb.is_invoked) {
501                 MM_RM_ERROR("RM #%"PRIu64" is releasing resource, so resource manager can't support your commit request",
502                         _mm_rm_hash64(handle->id));
503                 __mm_resource_handles_unlock();
504                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
505         }
506         __mm_resources_lock(handle);
507         __mm_resource_handles_unlock();
508
509         handle->pid = (int)getpid();
510
511         MM_RM_INFO("[pid %d] dbus_commit RM #%"PRIu64, handle->pid, _mm_rm_hash64(handle->id));
512         ret = __dbus_commit(handle);
513         if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
514                 MM_RM_DEBUG("Changes in RM #%"PRIu64" have been committed successfully", _mm_rm_hash64(handle->id));
515         else
516                 MM_RM_ERROR("Dbus commit request failed");
517         __mm_resources_unlock(handle);
518
519         return ret;
520 }
521
522 int _mm_resource_manager_set_status_cb(mm_resource_manager_h rm, mm_resource_manager_status_cb cb, void *user_data)
523 {
524         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
525
526         MM_RM_INFO("Enter %p", rm);
527
528         __mm_resource_handles_lock();
529         MM_RESOURCE_MANAGER_CHECK(handle);
530         __mm_resources_lock(handle);
531         __mm_resource_handles_unlock();
532
533         handle->status_cb.cb = cb;
534         handle->status_cb.user_data = user_data;
535         __mm_resources_unlock(handle);
536
537         MM_RM_INFO("Status callback %p in RM #%"PRIu64" is set", cb, _mm_rm_hash64(handle->id));
538
539         return MM_RESOURCE_MANAGER_ERROR_NONE;
540 }
541
542 int _mm_resource_manager_get_res_type_max_volume(mm_resource_manager_h rm,
543                 mm_resource_manager_res_type_e type, mm_resource_manager_res_volume *max_volume)
544 {
545         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
546
547         if (handle->__max_resource_volumes[type] == MM_RESOURCE_MANAGER_NO_RES) {
548                 MM_RM_DEBUG("No resource for the platform");
549                 return MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED;
550         } else {
551                 *max_volume = handle->__max_resource_volumes[type];
552                 return MM_RESOURCE_MANAGER_ERROR_NONE;
553         }
554 }
555
556 int _mm_resource_manager_get_res_type_volume(mm_resource_manager_h rm, mm_resource_manager_res_type_e type,
557         mm_resource_manager_res_type_cond_e condition, mm_resource_manager_res_volume *volume)
558 {
559         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
560
561         if (handle->__condition_volumes[type][condition] == MM_RESOURCE_MANAGER_NO_RES) {
562                 MM_RM_DEBUG("No pair (resource, condition) for the platform");
563                 return MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED;
564         } else {
565                 *volume = handle->__condition_volumes[type][condition];
566                 return MM_RESOURCE_MANAGER_ERROR_NONE;
567         }
568 }
569
570 int _mm_resource_manager_get_type_max_instance(mm_resource_manager_h rm,
571                 mm_resource_manager_res_type_e type, int *max_instance)
572 {
573         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
574
575         if (handle->__max_instance[type] == MM_RESOURCE_MANAGER_NO_RES) {
576                 MM_RM_DEBUG("No resource for the platform");
577                 return MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED;
578         }
579
580         *max_instance = handle->__max_instance[type];
581         return MM_RESOURCE_MANAGER_ERROR_NONE;
582 }
583
584 static void __mm_resource_manager_release_callback(mm_resource_manager_s *handle, mm_resource_manager_id id,
585                 mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume)
586 {
587         mm_resource_manager_res_s *resource;
588         mm_resource_manager_id handle_id;
589         mm_resource_manager_res_type_e t;
590         gboolean release_all = FALSE;
591         int idx;
592         int prev_len;
593         const char *res_name = NULL;
594
595         handle_id = handle->id;
596         MM_RM_HASH64(handle_id);
597
598         res_name = _mm_resource_manager_get_res_str(type);
599
600         MM_RM_DEBUG("Release callback is invoked for %s of volume %d in handle RM #%"PRIu64" input RM #%"PRIu64,
601                 res_name, volume, handle_id, id);
602
603         if (handle_id != id) {
604                 MM_RM_WARNING("handle RM #%"PRIu64" input RM #%"PRIu64" is different", handle_id, id);
605                 __mm_resource_handles_unlock();
606                 return;
607         }
608
609         for (t = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER; t < MM_RESOURCE_MANAGER_RES_TYPE_MAX; t++) {
610                 if (handle->is_release_marked[t] && t == type) {
611                         MM_RM_WARNING("mark_for_release() of %s is executed, which means that we can sync with rm dmn right now RM #%"PRIu64,
612                                 res_name, handle_id);
613                         if (__send_release_cb_sync(handle->id) != MM_RESOURCE_MANAGER_ERROR_NONE)
614                                 MM_RM_ERROR("__send_release_cb_sync is failed");
615                         __mm_resource_handles_unlock();
616                         return;
617                 }
618         }
619
620         __mm_resources_lock(handle);
621         __mm_resource_handles_unlock();
622         prev_len = handle->resources->len;
623
624         MM_RM_DEBUG("resource %p length %d", handle->resources, prev_len);
625
626         for (idx = 0; idx < prev_len; idx++) {
627                 resource = (mm_resource_manager_res_s *)handle->resources->pdata[idx];
628                 if (resource->type == type && resource->volume == volume) {
629                         /* FIXME : Set true in advance release callback invoking to prevent deadlock with resource marking */
630                         handle->release_cb.is_invoked = TRUE;
631
632                         MM_RM_INFO("[res %p type %s volume %d] release_cb", resource, res_name, volume);
633                         release_all = ((mm_resource_manager_release_cb)handle->release_cb.cb)(handle, resource, handle->release_cb.user_data);
634                         MM_RM_INFO("[%d] release_cb is completed", release_all);
635
636                         if (__send_release_cb_sync(handle->id) != MM_RESOURCE_MANAGER_ERROR_NONE) {
637                                 MM_RM_ERROR("__send_release_cb_sync is failed");
638                                 handle->release_cb.is_invoked = FALSE;
639                                 break;
640                         }
641
642                         /* If there is only one resource, the release callback value must be reset considering return value in case the handle is reused. */
643                         if (!release_all)
644                                 handle->release_cb.is_invoked = FALSE;
645
646                         g_ptr_array_remove_index_fast(handle->resources, idx);
647
648                         MM_RM_DEBUG("resource length %d => %d", prev_len, handle->resources->len);
649
650                         break;
651                 }
652         }
653
654         MM_RM_DEBUG("[%d] RELEASE ALL", release_all);
655
656         if (release_all) {
657                 if (_mm_resource_manager_release_other_resources(handle) == MM_RESOURCE_MANAGER_ERROR_NONE) {
658                         MM_RM_DEBUG("All resources are released after release cb");
659                         handle->release_cb.is_invoked = FALSE;
660                         MM_RM_WARNING("Reset release_cb release_cb.is_invoked RM #%"PRIu64, handle_id);
661                 } else {
662                         MM_RM_WARNING("Resources cannot be released after release cb");
663                 }
664         }
665
666         __mm_resources_unlock(handle);
667 }
668
669 static void __mm_resource_manager_status_callback(mm_resource_manager_s *handle, mm_resource_manager_status_e status)
670 {
671         __mm_resources_lock(handle);
672         __mm_resource_handles_unlock();
673         if (handle->status_cb.cb)
674                 ((mm_resource_manager_status_cb)handle->status_cb.cb)(handle, status, handle->status_cb.user_data);
675
676         __mm_resources_unlock(handle);
677 }
678
679 static void __mm_resource_handles_lock(void)
680 {
681         LOGD(">>> handles lock");
682         g_mutex_lock(&handles_lock);
683 }
684
685 static void __mm_resource_handles_unlock(void)
686 {
687         g_mutex_unlock(&handles_lock);
688         LOGD("<<< handles unlock");
689 }
690
691 static void __mm_resources_lock(mm_resource_manager_s *h)
692 {
693         MM_RM_RETM_IF(!h, "handle is NULL");
694         LOGD(">> resource lock");
695         g_mutex_lock(&h->resources_lock);
696 }
697
698 static void __mm_resources_unlock(mm_resource_manager_s *h)
699 {
700         MM_RM_RETM_IF(!h, "handle is NULL");
701         g_mutex_unlock(&h->resources_lock);
702         LOGD("<< resource unlock");
703 }
704
705 static int __check_resource(mm_resource_manager_s *rm, mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume)
706 {
707         mm_resource_manager_res_volume local_volume = rm->__max_resource_volumes[type];
708         mm_resource_manager_res_p i_res;
709         int i;
710
711         MM_RM_DEBUG("[RM #%"PRIu64" type : %d] resource (#%d) for the platform", _mm_rm_hash64(rm->id), type, local_volume);
712
713         if (volume > 0) {
714                 for (i = 0; i < rm->resources->len; i++) {
715                         i_res = (mm_resource_manager_res_p) rm->resources->pdata[i];
716                         if (i_res->type == type && i_res->state != MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE &&
717                                 (i_res->volume == MM_RESOURCE_MANAGER_RES_VOLUME_FULL ||(local_volume -= i_res->volume) < volume)) {
718                                 MM_RM_ERROR("Requested volume %d exceeds remaining local volume %d", volume, i_res->volume ==
719                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL ? 0 : local_volume);
720                                 return MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH;
721                         }
722                 }
723         }
724
725         return MM_RESOURCE_MANAGER_ERROR_NONE;
726 }
727
728 static int __create_resource(mm_resource_manager_s *rm,
729                 mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume, mm_resource_manager_res_p *res)
730 {
731         int ret;
732
733         mm_resource_manager_s *handle = MM_RESOURCE_MANAGER(rm);
734
735         MM_RM_RETVM_IF(handle == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "NULL handle pointer");
736         MM_RM_RETVM_IF(res == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "NULL pointer");
737
738         ret = __check_resource(rm, type, volume);
739         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
740                 return ret;
741
742         *res = g_new0(mm_resource_manager_res_s, 1);
743         (*res)->handle_id = handle->id;
744         (*res)->type = type;
745         if (handle->__max_resource_volumes[type] == MM_RESOURCE_MANAGER_RES_VOLUME_FULL &&
746                 volume != MM_RESOURCE_MANAGER_RES_VOLUME_FULL)
747                 (*res)->volume = MM_RESOURCE_MANAGER_RES_VOLUME_FULL;
748         else
749                 (*res)->volume = volume;
750
751         return MM_RESOURCE_MANAGER_ERROR_NONE;
752 }
753
754 static void __destroy_resource(void *res)
755 {
756         g_free(res);
757 }
758
759 static int __get_resource_index(mm_resource_manager_s *rm, mm_resource_manager_res_p res)
760 {
761         int i;
762
763         MM_RM_RETVM_IF(rm == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "NULL handle pointer");
764
765         for (i = 0; i < rm->resources->len; i++) {
766                 if (rm->resources->pdata[i] == (gpointer) res)
767                         return i;
768         }
769
770         MM_RM_WARNING("[%d] Resource %p is marked for release in RM #%"PRIu64,
771                 rm->resources->len, res, _mm_rm_hash64(rm->id));
772
773         return MM_RESOURCE_MANAGER_RES_NOT_FOUND;
774 }
775
776 static gboolean __mark_resource_for_release(GPtrArray *resources, int index, mm_resource_manager_res_p resource)
777 {
778         switch (resource->state) {
779         case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
780                 g_ptr_array_remove_index_fast(resources, index);
781                 MM_RM_DEBUG("Resource %p is removed implicitly", resource);
782                 return FALSE;
783         case MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED:
784                 resource->state = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
785                 MM_RM_DEBUG("Resource %p is successfully marked", resource);
786                 break;
787         case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
788                 MM_RM_DEBUG("Resource %p is already marked or released", resource);
789                 return FALSE;
790         }
791
792         return TRUE;
793 }
794
795 static gboolean __check_rm_handle(mm_resource_manager_s *handle)
796 {
797         int i;
798
799         for (i = 0; i < handles->len; i++) {
800                 if (g_ptr_array_index(handles, i) == handle)
801                         return TRUE;
802         }
803         return FALSE;
804 }
805
806 static int __send_release_cb_sync(mm_resource_manager_id id)
807 {
808         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
809         int sync_fd;
810
811         MM_RM_DEBUG("Enter");
812         sync_fd = open(RELEASE_CB_SYNC_PATH, O_WRONLY | O_NONBLOCK);
813         MM_RM_DEBUG("[%d] opened %s", sync_fd, RELEASE_CB_SYNC_PATH);
814
815         MM_RM_RETVM_IF(sync_fd == -1, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
816                 "Sync FIFO cannot be opened [errno %d]", errno);
817
818         if (write(sync_fd, &id, sizeof(id)) == sizeof(id)) {
819                 MM_RM_INFO("[SYNC] message is sent successfully RM #%"PRIu64, _mm_rm_hash64(id));
820         } else {
821                 MM_RM_ERROR("[SYNC] message cannot be sent RM #%"PRIu64, _mm_rm_hash64(id));
822                 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
823         }
824
825         MM_RM_RETVM_IF(close(sync_fd) == -1, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
826                 "[%d] close failed [errno %d]", sync_fd, errno);
827         MM_RM_DEBUG("[%d] closed", sync_fd);
828
829         return ret;
830 }
831
832 static void __init_lib()
833 {
834         handles = g_ptr_array_sized_new(MM_RESOURCE_MANAGER_RESERVED_HANDLE_ARRAY_SIZE);
835         MM_RM_RETM_IF(handles == NULL, "API lib cannot be initialized");
836
837         MM_RM_INFO("API lib is loaded");
838 }
839
840 static void __deinit_lib()
841 {
842         if (handles->len > 0) {
843                 MM_RM_DEBUG("Handles array [%d] is not empty. It will be cleaned now.", handles->len);
844                 while (handles->len > 0)
845                         _mm_resource_manager_destroy(handles->pdata[0]);
846         }
847
848         g_ptr_array_free(handles, TRUE);
849
850         MM_RM_INFO("API lib is unloaded");
851 }
852
853 static int __dbus_init(mm_resource_manager_s *handle)
854 {
855         GError *error = NULL;
856
857         MM_RM_RETVM_IF(handle->dbus_proxy != NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Dbus proxy is not NULL");
858
859         g_main_context_push_thread_default(handle->dispatcher_context);
860         handle->dbus_proxy = mmresource_manager_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, 0, RMD_GDBUS_NAME, RMD_GDBUS_PATH, NULL, &error);
861         g_main_context_pop_thread_default(handle->dispatcher_context);
862         MM_RM_RET_IF_GERR(error, "Dbus proxy cannot be created");
863
864         if (g_signal_connect(handle->dbus_proxy, "release_callback", (GCallback)__dbus_release_callback, NULL) < 1 ||
865                 g_signal_connect(handle->dbus_proxy, "status_callback", (GCallback)__dbus_status_callback, NULL) < 1) {
866
867                 g_object_unref(handle->dbus_proxy);
868                 handle->dbus_proxy = NULL;
869                 MM_RM_ERROR("Release or status callback signals cannot be connected");
870
871                 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
872         }
873
874         return MM_RESOURCE_MANAGER_ERROR_NONE;
875 }
876
877 static int __dbus_deinit(mm_resource_manager_s *handle)
878 {
879         MM_RM_RETVM_IF(handle->dbus_proxy == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Dbus proxy is NULL");
880         g_object_unref(handle->dbus_proxy);
881         handle->dbus_proxy = NULL;
882         return MM_RESOURCE_MANAGER_ERROR_NONE;
883 }
884
885 static int __dbus_init_conf(mm_resource_manager_s *handle)
886 {
887         int i, j;
888         GError *error = NULL;
889         int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
890         GVariant *max_volume = NULL;
891         GVariant *cond_volume = NULL;
892         GVariant *max_instance = NULL;
893         GVariant *tmp;
894         GVariantIter volume_iter;
895         GVariantIter cond_volume_iter;
896
897         mmresource_manager_call_conf_sync(handle->dbus_proxy, &rm_error, &max_volume, &cond_volume, &max_instance, NULL, &error);
898         MM_RM_RET_IF_GERR(error, "DBus conf msg cannot be sent");
899
900         MM_RM_RETVM_IF(max_volume == NULL || cond_volume == NULL,
901                         MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Variant data are empty");
902
903         if (g_variant_iter_init(&volume_iter, max_volume) == MM_RESOURCE_MANAGER_RES_TYPE_MAX) {
904                 for (i = 0; g_variant_iter_next(&volume_iter, "i", &handle->__max_resource_volumes[i]); i++);
905                 g_variant_unref(max_volume);
906                 max_volume = NULL;
907         } else {
908                 MM_RM_ERROR("Wrong max volume array size");
909                 goto out;
910         }
911
912         if (g_variant_iter_init(&volume_iter, cond_volume) == MM_RESOURCE_MANAGER_RES_TYPE_MAX) {
913                 for (i = 0; (tmp = g_variant_iter_next_value(&volume_iter)) != NULL; i++) {
914                         if (g_variant_iter_init(&cond_volume_iter, tmp) == MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX) {
915                                 for (j = 0; g_variant_iter_next(&cond_volume_iter, "i", &handle->__condition_volumes[i][j]); j++);
916                                 g_variant_unref(tmp);
917                         } else {
918                                 g_variant_unref(tmp);
919                                 MM_RM_ERROR("Wrong condition volume array size");
920                                 rm_error = MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
921                                 break;
922                         }
923                 }
924                 g_variant_unref(cond_volume);
925                 cond_volume = NULL;
926         } else {
927                 MM_RM_ERROR("Wrong condition volume array size");
928                 goto out;
929         }
930
931         if (g_variant_iter_init(&volume_iter, max_instance) == MM_RESOURCE_MANAGER_RES_TYPE_MAX) {
932                 for (i = 0; g_variant_iter_next(&volume_iter, "i", &handle->__max_instance[i]); i++);
933                 g_variant_unref(max_instance);
934                 max_instance = NULL;
935         } else {
936                 MM_RM_ERROR("Wrong max instance array size");
937                 goto out;
938         }
939
940         return rm_error;
941 out:
942         g_variant_unref(max_volume);
943         g_variant_unref(cond_volume);
944         g_variant_unref(max_instance);
945         return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
946 }
947
948 static int __dbus_create(mm_resource_manager_s *handle, mm_resource_manager_app_class_e app_class)
949 {
950         GError *error = NULL;
951         int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
952
953         mmresource_manager_call_create_sync(handle->dbus_proxy, app_class, &handle->id, &rm_error, NULL, &error);
954         MM_RM_RET_IF_GERR(error, "DBus create msg cannot be sent");
955
956         MM_RM_DEBUG("Create returned id - RM #%"PRIu64", error - %d", _mm_rm_hash64(handle->id), rm_error);
957
958         return rm_error;
959 }
960
961 static int __dbus_destroy(mm_resource_manager_s *handle)
962 {
963         GError *error = NULL;
964         int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
965
966         mmresource_manager_call_destroy_sync(handle->dbus_proxy, handle->id, &rm_error, NULL, &error);
967         MM_RM_RET_IF_GERR(error, "DBus destroy msg cannot be sent");
968
969         MM_RM_DEBUG("Destroy for id - RM #%"PRIu64" returned error - %d", _mm_rm_hash64(handle->id), rm_error);
970
971         return MM_RESOURCE_MANAGER_ERROR_NONE;
972 }
973
974 static int __dbus_commit(mm_resource_manager_s *handle)
975 {
976         GVariant *release;
977         GVariant *acquire;
978         GVariantBuilder *release_builder;
979         GVariantBuilder *acquire_builder;
980         GVariant *flags_variant;
981         GVariantIter flags_iter;
982         mm_resource_manager_res_p resource;
983         int i;
984         int release_num = 0;
985         int acquire_num = 0;
986         GError *error = NULL;
987         int rm_error = MM_RESOURCE_MANAGER_ERROR_NONE;
988
989         release_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
990         acquire_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
991
992         for (i = 0; i < handle->resources->len; i++) {
993                 resource = (mm_resource_manager_res_p) handle->resources->pdata[i];
994
995                 switch (resource->state) {
996                 case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
997                         g_variant_builder_add_value(acquire_builder, g_variant_new("(iii)", resource->type, resource->volume, handle->pid));
998                         acquire_num++;
999                         break;
1000                 case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
1001                         g_variant_builder_add_value(release_builder, g_variant_new("(iii)", resource->type, resource->volume, handle->pid));
1002                         release_num++;
1003                         break;
1004                 default:
1005                         break;
1006                 }
1007         }
1008
1009         if (release_num + acquire_num == 0) {
1010                 g_variant_builder_unref(release_builder);
1011                 g_variant_builder_unref(acquire_builder);
1012                 MM_RM_DEBUG("There is nothing to commit - dbus request is not sent [%d %d]", release_num, acquire_num);
1013                 return rm_error;
1014         }
1015
1016         /* Acquire and release arrays are ended with special element, because g_variant_builder_end crashes without at least one element */
1017         g_variant_builder_add_value(acquire_builder, g_variant_new("(iii)", MM_RESOURCE_MANAGER_NO_RES, 0, handle->pid));
1018         acquire = g_variant_builder_end(acquire_builder);
1019         g_variant_builder_unref(acquire_builder);
1020
1021         g_variant_builder_add_value(release_builder, g_variant_new("(iii)", MM_RESOURCE_MANAGER_NO_RES, 0, handle->pid));
1022         release = g_variant_builder_end(release_builder);
1023         g_variant_builder_unref(release_builder);
1024
1025         mmresource_manager_call_commit_sync(handle->dbus_proxy, handle->id, release, acquire, &rm_error, &flags_variant, NULL, &error);
1026         MM_RM_RET_IF_GERR(error, "DBus commit msg cannot be sent");
1027
1028         MM_RM_DEBUG("Commit for id - RM #%"PRIu64" returned error - %d", _mm_rm_hash64(handle->id), rm_error);
1029
1030         if (rm_error == MM_RESOURCE_MANAGER_ERROR_NONE) {
1031                 for (i = 0; i < handle->resources->len; i++) {
1032                         resource = (mm_resource_manager_res_p) handle->resources->pdata[i];
1033
1034                         switch (resource->state) {
1035                         case MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE:
1036                                 resource->state = MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED;
1037                                 resource->is_acquire_failed = FALSE;
1038                                 break;
1039                         case MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE:
1040                                 handle->is_release_marked[resource->type] = FALSE;
1041                                 g_ptr_array_remove_index_fast(handle->resources, i--);
1042                                 break;
1043                         default:
1044                                 break;
1045                         }
1046                 }
1047         } else if (rm_error == MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY) {
1048                 g_variant_iter_init(&flags_iter, flags_variant);
1049
1050                 for (i = 0; i < handle->resources->len; i++) {
1051                         resource = (mm_resource_manager_res_p) handle->resources->pdata[i];
1052
1053                         if (resource->state == MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE) {
1054                                 if (!g_variant_iter_next(&flags_iter, "b", &resource->is_acquire_failed))
1055                                         MM_RM_ERROR("g_variant_iter_next failed to get the value of is_acquire_failed");
1056                         }
1057                 }
1058         }
1059
1060         g_variant_unref(flags_variant);
1061
1062         return rm_error;
1063 }
1064
1065 static void __dbus_release_callback(MMResourceManager *object, guint64 arg_id, gint arg_resource_type, gint arg_volume)
1066 {
1067         mm_resource_manager_s *handle;
1068         mm_resource_manager_id handle_id;
1069         int i;
1070
1071         __mm_resource_handles_lock();
1072
1073         for (i = 0; i < handles->len; i++) {
1074                 handle = (mm_resource_manager_s *)handles->pdata[i];
1075                 handle_id = handle->id;
1076                 MM_RM_HASH64(handle_id);
1077
1078                 if (handle->dbus_proxy == object && handle_id == arg_id) {
1079                         if (handle->release_cb.is_invoked) {
1080                                 MM_RM_WARNING("other resource release cb is already executed RM #%"PRIu64, handle_id);
1081                                 if (__send_release_cb_sync(handle->id) != MM_RESOURCE_MANAGER_ERROR_NONE)
1082                                         MM_RM_ERROR("__send_release_cb_sync is failed");
1083                                 __mm_resource_handles_unlock();
1084                                 return;
1085                         }
1086                         MM_RM_INFO("[release_callback] RM #%"PRIu64, handle_id);
1087                         __mm_resource_manager_release_callback(handle, arg_id, arg_resource_type, arg_volume);
1088                         return;
1089                 }
1090         }
1091
1092         __mm_resource_handles_unlock();
1093 }
1094
1095 static void __dbus_status_callback(MMResourceManager *object, gint arg_status)
1096 {
1097         mm_resource_manager_s *handle;
1098         int i;
1099
1100         MM_RM_INFO("status callback status %d", arg_status);
1101         __mm_resource_handles_lock();
1102
1103         for (i = 0; i < handles->len; i++) {
1104                 handle = (mm_resource_manager_s *)handles->pdata[i];
1105                 if (handle->dbus_proxy == object) {
1106                         __mm_resource_manager_status_callback(handle, arg_status);
1107                         return;
1108                 }
1109         }
1110
1111         __mm_resource_handles_unlock();
1112 }
1113
1114 static gpointer __dispatcher_thread(gpointer user_data)
1115 {
1116         GMainLoop *ml = (GMainLoop *) user_data;
1117
1118         MM_RM_INFO("main loop %p", ml);
1119
1120         if (ml) {
1121                 g_main_loop_run(ml);
1122                 MM_RM_INFO("main loop %p quit", ml);
1123         }
1124
1125         return NULL;
1126 }
1127
1128 static void __destroy_dispatcher(mm_resource_manager_s *handle)
1129 {
1130         MM_RM_WARNING("handle %p", handle);
1131
1132         __mm_resource_handles_lock();
1133
1134         if (__dbus_deinit(handle) != MM_RESOURCE_MANAGER_ERROR_NONE)
1135                 MM_RM_ERROR("Error while dbus deinitializing");
1136
1137         MM_RM_INFO("dispatcher main loop %p", handle->dispatcher_loop);
1138         if (handle->dispatcher_loop) {
1139                 if (g_main_loop_is_running(handle->dispatcher_loop)) {
1140                         MM_RM_INFO("mainloop %p is running", handle->dispatcher_loop);
1141                         g_main_loop_quit(handle->dispatcher_loop);
1142                 }
1143
1144                 g_main_loop_unref(handle->dispatcher_loop);
1145                 handle->dispatcher_loop = NULL;
1146         }
1147
1148         MM_RM_INFO("dispatcher thread %p", handle->dispatcher_thread);
1149         if (handle->dispatcher_thread) {
1150                 g_thread_join(handle->dispatcher_thread);
1151                 MM_RM_INFO("dispatcher thread join %p", handle->dispatcher_thread);
1152                 handle->dispatcher_thread = NULL;
1153         }
1154
1155         MM_RM_INFO("dispatcher context %p", handle->dispatcher_context);
1156         if (handle->dispatcher_context) {
1157                 g_main_context_unref(handle->dispatcher_context);
1158                 handle->dispatcher_context = NULL;
1159         }
1160
1161         __mm_resource_handles_unlock();
1162 }