1 /*
2 * Copyright (C) 2017 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 #pragma once
17
18 #include <stdlib.h>
19
20 #include <cutils/sockets.h>
21 #include <log/log.h>
22
23 #include "common/libs/fs/shared_fd.h"
24
25 // #define DEBUG_CONNECTIONS
26
27 /*
28 * Packet structures for commands sent to the remoter from the GCE HAL.
29 * This is a private protocol between the HAL and the remoter.
30 */
31
32 static const size_t kSensorNameMaxLen = 64;
33 // Don't use PATH_MAX here because it would increate the size of every
34 // packet that we send to the remoter.
35 static const size_t kScreenRecordFilePathMaxLen = 128;
36 static const size_t kUnixSocketPathMaxLen = 128;
37
38 struct remoter_request_packet {
39 /* Length of the packet in bytes. */
40 uint32_t length;
41
42 /* Operation to perform. */
43 uint8_t operation;
44
45 /* Set to '1' if a response packet is desired */
46 uint8_t send_response;
47
48 /* Operation arguments. */
49 union {
50 /* Arguments for the frame buffer 'post' operation. */
51 struct {
52 /* Y offset in the double-buffer where this frame starts. */
53 uint32_t y_offset;
54 } fb_post_params;
55 /* Arguments for the frame buffer 'update rect' operation. */
56 struct {
57 uint32_t left;
58 uint32_t top;
59 uint32_t width;
60 uint32_t height;
61 } fb_update_rect_params;
62 struct {
63 uint32_t type;
64 bool enabled;
65 int64_t delay_ns;
66 int handle;
67 } sensor_state_params;
68 struct {
69 char filepath[kScreenRecordFilePathMaxLen];
70 } screenrecord_params;
71 struct {
72 char unix_socket[kUnixSocketPathMaxLen];
73 } hal_ready_params;
74 } params;
75 } __attribute__((packed));
76
77 enum {
78 kRemoterHALReady = 1,
79 kRemoterSensorState
80 };
81
82 /*
83 * If 'send_response' is set in a request then the remoter will respond
84 * with the following structure.
85 */
86 struct remoter_response_packet {
87 uint32_t length;
88 uint8_t status;
89 union {
90 struct {
91 /* Number of 'struct sensor_list_element_packet's to follow */
92 uint8_t num_sensors;
93 } sensor_list_data;
94 } data;
95 } __attribute__((packed));
96
97 struct sensor_list_element_packet {
98 int handle;
99 int type;
100 char name[kSensorNameMaxLen];
101 char vendor[kSensorNameMaxLen];
102 int version;
103 float max_range;
104 float resolution;
105 float power;
106 } __attribute__((packed));
107
108 enum {
109 kResponseStatusOk = 1,
110 kResponseStatusFailed
111 };
112
remoter_request_packet_init(struct remoter_request_packet * pkt,uint8_t operation,uint8_t send_response)113 static inline void remoter_request_packet_init(
114 struct remoter_request_packet* pkt, uint8_t operation,
115 uint8_t send_response) {
116 memset(pkt, 0, sizeof(*pkt));
117 pkt->length = sizeof(*pkt);
118 pkt->operation = operation;
119 pkt->send_response = send_response;
120 }
121
remoter_response_packet_init(struct remoter_response_packet * pkt,uint8_t status)122 static inline void remoter_response_packet_init(
123 struct remoter_response_packet* pkt, uint8_t status) {
124 memset(pkt, 0, sizeof(*pkt));
125 pkt->length = sizeof(*pkt);
126 pkt->status = status;
127 }
128
129 void remoter_connect(cvd::SharedFD* dest);
130 int remoter_connect();
131
remoter_read_request(const cvd::SharedFD & socket,struct remoter_request_packet * request)132 static inline int remoter_read_request(
133 const cvd::SharedFD& socket,
134 struct remoter_request_packet* request) {
135 int len;
136 int remaining_data;
137 /* Packets start with a 4 byte length (which includes the length). */
138
139 if ((len = socket->Read(request, sizeof(request->length))) < 0) {
140 ALOGE("%s: Failed to read remoter request (%s)",
141 __FUNCTION__, socket->StrError());
142 return -1;
143 } else if (len == 0) {
144 return 0;
145 } else if (len != sizeof(request->length)) {
146 ALOGE("%s: Failed to read remoter request (Short read)", __FUNCTION__);
147 return -1;
148 }
149
150 /* Extra paranoia. */
151 if (request->length != sizeof(*request)) {
152 ALOGE("%s: Malformed remoter request", __FUNCTION__);
153 return -1;
154 }
155 remaining_data = request->length - sizeof(request->length);
156 uint8_t* cursor = ((uint8_t*)request) + sizeof(request->length);
157 if ((len = socket->Read(cursor, remaining_data)) < 0) {
158 ALOGE("%s: Failed to read remoter request (%s)",
159 __FUNCTION__, socket->StrError());
160 return -1;
161 } else if (len == 0) {
162 return 0;
163 } else if (len != (int) remaining_data) {
164 ALOGE("%s: Failed to read remoter request (Short read)", __FUNCTION__);
165 return -1;
166 }
167 return 1;
168 }
169
remoter_read_response(int socket,struct remoter_response_packet * response)170 static inline int remoter_read_response(
171 int socket, struct remoter_response_packet* response) {
172 int len;
173 int remaining_data;
174 /* Packets start with a 4 byte length (which includes the length). */
175
176 #ifdef DEBUG_CONNECTIONS
177 ALOGI("remoter_read_response(): socket %d, length length = %d", socket,
178 sizeof(response->length));
179 #endif
180 if ((len = TEMP_FAILURE_RETRY(
181 read(socket, response, sizeof(response->length)))) < 0) {
182 ALOGE("%s: Failed to read remoter response (%s)",
183 __FUNCTION__, strerror(errno));
184 return -1;
185 } else if (len == 0) {
186 return 0;
187 } else if (len != sizeof(response->length)) {
188 ALOGE("%s: Failed to read remoter response (Short read)", __FUNCTION__);
189 return -1;
190 }
191
192 /* Extra paranoia. */
193 if (response->length != sizeof(*response)) {
194 ALOGE("%s: Malformed remoter response", __FUNCTION__);
195 return -1;
196 }
197 remaining_data = response->length - sizeof(response->length);
198 uint8_t* cursor = ((uint8_t*)response) + sizeof(response->length);
199 #ifdef DEBUG_CONNECTIONS
200 ALOGI("remoter_read_request(): socket %d, data length = %d",
201 socket, remaining_data);
202 #endif
203 if ((len = TEMP_FAILURE_RETRY(read(socket, cursor, remaining_data))) < 0) {
204 ALOGE("%s: Failed to read remoter response (%s)",
205 __FUNCTION__, strerror(errno));
206 return -1;
207 } else if (len == 0) {
208 return 0;
209 } else if (len != (int) remaining_data) {
210 ALOGE("%s: Failed to read remoter response (Short read)", __FUNCTION__);
211 return -1;
212 }
213 return 1;
214 }
215
remoter_send_request(int socket,struct remoter_request_packet * request)216 static inline int remoter_send_request(
217 int socket, struct remoter_request_packet* request) {
218 #ifdef DEBUG_CONNECTIONS
219 ALOGI(
220 "remoter_send_request(): socket %d, length %u", socket, sizeof(*request));
221 #endif
222 int len = TEMP_FAILURE_RETRY(write(socket, request, sizeof(*request)));
223 if (len <= 0) {
224 ALOGE("Failed to write request to remoter (%s)", strerror(errno));
225 return -1;
226 } else if (len != sizeof(*request)) {
227 ALOGE("Failed to write request to remoter (short write)");
228 return -1;
229 }
230 return 0;
231 }
232
remoter_send_response(const cvd::SharedFD & socket,struct remoter_response_packet * response)233 static inline int remoter_send_response(
234 const cvd::SharedFD& socket,
235 struct remoter_response_packet* response) {
236 int len = socket->Write(response, sizeof(*response));
237 if (len <=0) {
238 ALOGE("%s: Failed to send response to remoter (%s)",
239 __FUNCTION__, strerror(errno));
240 return -1;
241 }
242 return 0;
243 }
244
remoter_do_single_request_with_socket(int socket,struct remoter_request_packet * request,struct remoter_response_packet * response)245 static inline int remoter_do_single_request_with_socket(
246 int socket, struct remoter_request_packet* request,
247 struct remoter_response_packet* response) {
248
249 if (request->send_response && !response) {
250 ALOGE("%s: Request specifies a response but no response ptr set",
251 __FUNCTION__);
252 return -1;
253 } else if (!request->send_response && response) {
254 ALOGE("%s: Request specifies no response but has response ptr set",
255 __FUNCTION__);
256 return -1;
257 }
258
259 if (remoter_send_request(socket, request) < 0) {
260 return -1;
261 }
262
263 if (response && (remoter_read_response(socket, response) <= 0)) {
264 return -1;
265 }
266 return 0;
267 }
268
remoter_do_single_request(struct remoter_request_packet * request,struct remoter_response_packet * response)269 static inline int remoter_do_single_request(
270 struct remoter_request_packet* request,
271 struct remoter_response_packet* response) {
272 int socket;
273 if ((socket = remoter_connect()) < 0) {
274 return -1;
275 }
276
277 if (remoter_do_single_request_with_socket(socket, request, response) < 0) {
278 close(socket);
279 return -1;
280 }
281 close(socket);
282 return 0;
283 }
284
285