1 /*
2  * Copyright (C) 2016, 2018-2019 ARM Limited. All rights reserved.
3  *
4  * Copyright (C) 2008 The Android Open Source Project
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * You may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #if GRALLOC_VERSION_MAJOR == 1
20 #include <hardware/gralloc1.h>
21 #elif GRALLOC_VERSION_MAJOR == 0
22 #include <hardware/gralloc.h>
23 #endif
24 
25 #include "mali_gralloc_module.h"
26 #include "mali_gralloc_private_interface_types.h"
27 #include "mali_gralloc_buffer.h"
28 #include "mali_gralloc_ion.h"
29 #include "gralloc_buffer_priv.h"
30 #include "mali_gralloc_bufferallocation.h"
31 #include "mali_gralloc_debug.h"
32 
33 static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER;
34 
mali_gralloc_reference_retain(mali_gralloc_module const * module,buffer_handle_t handle)35 int mali_gralloc_reference_retain(mali_gralloc_module const *module, buffer_handle_t handle)
36 {
37 	GRALLOC_UNUSED(module);
38 
39 	if (private_handle_t::validate(handle) < 0)
40 	{
41 		AERR("Registering/Retaining invalid buffer %p, returning error", handle);
42 		return -EINVAL;
43 	}
44 
45 	private_handle_t *hnd = (private_handle_t *)handle;
46 	pthread_mutex_lock(&s_map_lock);
47 
48 	if (hnd->allocating_pid == getpid() || hnd->remote_pid == getpid())
49 	{
50 		hnd->ref_count++;
51 		pthread_mutex_unlock(&s_map_lock);
52 		return 0;
53 	}
54 	else
55 	{
56 		hnd->remote_pid = getpid();
57 		hnd->ref_count = 1;
58 	}
59 
60 	int retval = -EINVAL;
61 
62 	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
63 	{
64 		retval = 0;
65 	}
66 	else if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_ION))
67 	{
68 		retval = mali_gralloc_ion_map(hnd);
69 #if GRALLOC_ION_HANDLE_IMPORT == 1
70 		if (retval >= 0)
71 		{
72 			/* failing to import ion handle is not fatal */
73 			import_exynos_ion_handles(hnd);
74 			retval = 0;
75 		}
76 #endif
77 	}
78 	else
79 	{
80 		AERR("Unknown buffer flags not supported. flags = %d", hnd->flags);
81 	}
82 
83 	pthread_mutex_unlock(&s_map_lock);
84 	return retval;
85 }
86 
mali_gralloc_reference_release(mali_gralloc_module const * module,buffer_handle_t handle,bool canFree)87 int mali_gralloc_reference_release(mali_gralloc_module const *module, buffer_handle_t handle, bool canFree)
88 {
89 	GRALLOC_UNUSED(module);
90 
91 	if (private_handle_t::validate(handle) < 0)
92 	{
93 		AERR("unregistering/releasing invalid buffer %p, returning error", handle);
94 		return -EINVAL;
95 	}
96 
97 	private_handle_t *hnd = (private_handle_t *)handle;
98 	pthread_mutex_lock(&s_map_lock);
99 
100 	if (hnd->ref_count == 0)
101 	{
102 		AERR("Buffer %p should have already been released", handle);
103 		pthread_mutex_unlock(&s_map_lock);
104 		return -EINVAL;
105 	}
106 
107 	if (hnd->allocating_pid == getpid())
108 	{
109 		hnd->ref_count--;
110 
111 		if (hnd->ref_count == 0 && canFree)
112 		{
113 			if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
114 			{
115 				close(hnd->fb_fd);
116 			}
117 			else
118 			{
119 				mali_gralloc_dump_buffer_erase(hnd);
120 			}
121 
122 #if GRALLOC_ION_HANDLE_IMPORT == 1
123 			free_exynos_ion_handles(hnd);
124 #endif
125 			mali_gralloc_buffer_free(handle);
126 			delete handle;
127 		}
128 	}
129 	else if (hnd->remote_pid == getpid()) // never unmap buffers that were not imported into this process
130 	{
131 		hnd->ref_count--;
132 
133 		if (hnd->ref_count == 0)
134 		{
135 
136 			if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_ION))
137 			{
138 				mali_gralloc_ion_unmap(hnd);
139 #if GRALLOC_ION_HANDLE_IMPORT == 1
140 				free_exynos_ion_handles(hnd);
141 #endif
142 			}
143 			else
144 			{
145 				AERR("Unregistering/Releasing unknown buffer is not supported. Flags = %d", hnd->flags);
146 			}
147 
148 #if GRALLOC_USE_ASHMEM_METADATA != 1
149 			/*
150 			 * Close shared attribute region file descriptor. It might seem strange to "free"
151 			 * this here since this can happen in a client process, but free here is nothing
152 			 * but unmapping and closing the duplicated file descriptor. The original ashmem
153 			 * fd instance is still open until alloc_device_free() is called. Even sharing
154 			 * of gralloc buffers within the same process should have fds dup:ed.
155 			 */
156 			gralloc_buffer_attr_free(hnd);
157 #endif
158 
159 			hnd->base = 0;
160 		}
161 	}
162 	else
163 	{
164 		AERR("Trying to unregister buffer %p from process %d that was not imported into current process: %d", hnd,
165 		     hnd->remote_pid, getpid());
166 	}
167 
168 	pthread_mutex_unlock(&s_map_lock);
169 	return 0;
170 }
171