1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "dbus/values_util.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <memory>
8*635a8641SAndroid Build Coastguard Worker #include <utility>
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include "base/json/json_writer.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/values.h"
13*635a8641SAndroid Build Coastguard Worker #include "dbus/message.h"
14*635a8641SAndroid Build Coastguard Worker
15*635a8641SAndroid Build Coastguard Worker namespace dbus {
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker namespace {
18*635a8641SAndroid Build Coastguard Worker
19*635a8641SAndroid Build Coastguard Worker // Returns whether |value| is exactly representable by double or not.
20*635a8641SAndroid Build Coastguard Worker template<typename T>
IsExactlyRepresentableByDouble(T value)21*635a8641SAndroid Build Coastguard Worker bool IsExactlyRepresentableByDouble(T value) {
22*635a8641SAndroid Build Coastguard Worker return value == static_cast<T>(static_cast<double>(value));
23*635a8641SAndroid Build Coastguard Worker }
24*635a8641SAndroid Build Coastguard Worker
25*635a8641SAndroid Build Coastguard Worker // Pops values from |reader| and appends them to |list_value|.
PopListElements(MessageReader * reader,base::ListValue * list_value)26*635a8641SAndroid Build Coastguard Worker bool PopListElements(MessageReader* reader, base::ListValue* list_value) {
27*635a8641SAndroid Build Coastguard Worker while (reader->HasMoreData()) {
28*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> element_value = PopDataAsValue(reader);
29*635a8641SAndroid Build Coastguard Worker if (!element_value)
30*635a8641SAndroid Build Coastguard Worker return false;
31*635a8641SAndroid Build Coastguard Worker list_value->Append(std::move(element_value));
32*635a8641SAndroid Build Coastguard Worker }
33*635a8641SAndroid Build Coastguard Worker return true;
34*635a8641SAndroid Build Coastguard Worker }
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard Worker // Pops dict-entries from |reader| and sets them to |dictionary_value|
PopDictionaryEntries(MessageReader * reader,base::DictionaryValue * dictionary_value)37*635a8641SAndroid Build Coastguard Worker bool PopDictionaryEntries(MessageReader* reader,
38*635a8641SAndroid Build Coastguard Worker base::DictionaryValue* dictionary_value) {
39*635a8641SAndroid Build Coastguard Worker while (reader->HasMoreData()) {
40*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(Message::DICT_ENTRY, reader->GetDataType());
41*635a8641SAndroid Build Coastguard Worker MessageReader entry_reader(nullptr);
42*635a8641SAndroid Build Coastguard Worker if (!reader->PopDictEntry(&entry_reader))
43*635a8641SAndroid Build Coastguard Worker return false;
44*635a8641SAndroid Build Coastguard Worker // Get key as a string.
45*635a8641SAndroid Build Coastguard Worker std::string key_string;
46*635a8641SAndroid Build Coastguard Worker if (entry_reader.GetDataType() == Message::STRING) {
47*635a8641SAndroid Build Coastguard Worker // If the type of keys is STRING, pop it directly.
48*635a8641SAndroid Build Coastguard Worker if (!entry_reader.PopString(&key_string))
49*635a8641SAndroid Build Coastguard Worker return false;
50*635a8641SAndroid Build Coastguard Worker } else {
51*635a8641SAndroid Build Coastguard Worker // If the type of keys is not STRING, convert it to string.
52*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> key(PopDataAsValue(&entry_reader));
53*635a8641SAndroid Build Coastguard Worker if (!key)
54*635a8641SAndroid Build Coastguard Worker return false;
55*635a8641SAndroid Build Coastguard Worker // Use JSONWriter to convert an arbitrary value to a string.
56*635a8641SAndroid Build Coastguard Worker base::JSONWriter::Write(*key, &key_string);
57*635a8641SAndroid Build Coastguard Worker }
58*635a8641SAndroid Build Coastguard Worker // Get the value and set the key-value pair.
59*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> value = PopDataAsValue(&entry_reader);
60*635a8641SAndroid Build Coastguard Worker if (!value)
61*635a8641SAndroid Build Coastguard Worker return false;
62*635a8641SAndroid Build Coastguard Worker dictionary_value->SetWithoutPathExpansion(key_string, std::move(value));
63*635a8641SAndroid Build Coastguard Worker }
64*635a8641SAndroid Build Coastguard Worker return true;
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker
67*635a8641SAndroid Build Coastguard Worker // Gets the D-Bus type signature for the value.
GetTypeSignature(const base::Value & value)68*635a8641SAndroid Build Coastguard Worker std::string GetTypeSignature(const base::Value& value) {
69*635a8641SAndroid Build Coastguard Worker switch (value.type()) {
70*635a8641SAndroid Build Coastguard Worker case base::Value::Type::BOOLEAN:
71*635a8641SAndroid Build Coastguard Worker return "b";
72*635a8641SAndroid Build Coastguard Worker case base::Value::Type::INTEGER:
73*635a8641SAndroid Build Coastguard Worker return "i";
74*635a8641SAndroid Build Coastguard Worker case base::Value::Type::DOUBLE:
75*635a8641SAndroid Build Coastguard Worker return "d";
76*635a8641SAndroid Build Coastguard Worker case base::Value::Type::STRING:
77*635a8641SAndroid Build Coastguard Worker return "s";
78*635a8641SAndroid Build Coastguard Worker case base::Value::Type::BINARY:
79*635a8641SAndroid Build Coastguard Worker return "ay";
80*635a8641SAndroid Build Coastguard Worker case base::Value::Type::DICTIONARY:
81*635a8641SAndroid Build Coastguard Worker return "a{sv}";
82*635a8641SAndroid Build Coastguard Worker case base::Value::Type::LIST:
83*635a8641SAndroid Build Coastguard Worker return "av";
84*635a8641SAndroid Build Coastguard Worker default:
85*635a8641SAndroid Build Coastguard Worker DLOG(ERROR) << "Unexpected type " << value.type();
86*635a8641SAndroid Build Coastguard Worker return std::string();
87*635a8641SAndroid Build Coastguard Worker }
88*635a8641SAndroid Build Coastguard Worker }
89*635a8641SAndroid Build Coastguard Worker
90*635a8641SAndroid Build Coastguard Worker } // namespace
91*635a8641SAndroid Build Coastguard Worker
PopDataAsValue(MessageReader * reader)92*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> PopDataAsValue(MessageReader* reader) {
93*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::Value> result;
94*635a8641SAndroid Build Coastguard Worker switch (reader->GetDataType()) {
95*635a8641SAndroid Build Coastguard Worker case Message::INVALID_DATA:
96*635a8641SAndroid Build Coastguard Worker // Do nothing.
97*635a8641SAndroid Build Coastguard Worker break;
98*635a8641SAndroid Build Coastguard Worker case Message::BYTE: {
99*635a8641SAndroid Build Coastguard Worker uint8_t value = 0;
100*635a8641SAndroid Build Coastguard Worker if (reader->PopByte(&value))
101*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
102*635a8641SAndroid Build Coastguard Worker break;
103*635a8641SAndroid Build Coastguard Worker }
104*635a8641SAndroid Build Coastguard Worker case Message::BOOL: {
105*635a8641SAndroid Build Coastguard Worker bool value = false;
106*635a8641SAndroid Build Coastguard Worker if (reader->PopBool(&value))
107*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
108*635a8641SAndroid Build Coastguard Worker break;
109*635a8641SAndroid Build Coastguard Worker }
110*635a8641SAndroid Build Coastguard Worker case Message::INT16: {
111*635a8641SAndroid Build Coastguard Worker int16_t value = 0;
112*635a8641SAndroid Build Coastguard Worker if (reader->PopInt16(&value))
113*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
114*635a8641SAndroid Build Coastguard Worker break;
115*635a8641SAndroid Build Coastguard Worker }
116*635a8641SAndroid Build Coastguard Worker case Message::UINT16: {
117*635a8641SAndroid Build Coastguard Worker uint16_t value = 0;
118*635a8641SAndroid Build Coastguard Worker if (reader->PopUint16(&value))
119*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
120*635a8641SAndroid Build Coastguard Worker break;
121*635a8641SAndroid Build Coastguard Worker }
122*635a8641SAndroid Build Coastguard Worker case Message::INT32: {
123*635a8641SAndroid Build Coastguard Worker int32_t value = 0;
124*635a8641SAndroid Build Coastguard Worker if (reader->PopInt32(&value))
125*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
126*635a8641SAndroid Build Coastguard Worker break;
127*635a8641SAndroid Build Coastguard Worker }
128*635a8641SAndroid Build Coastguard Worker case Message::UINT32: {
129*635a8641SAndroid Build Coastguard Worker uint32_t value = 0;
130*635a8641SAndroid Build Coastguard Worker if (reader->PopUint32(&value)) {
131*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(static_cast<double>(value));
132*635a8641SAndroid Build Coastguard Worker }
133*635a8641SAndroid Build Coastguard Worker break;
134*635a8641SAndroid Build Coastguard Worker }
135*635a8641SAndroid Build Coastguard Worker case Message::INT64: {
136*635a8641SAndroid Build Coastguard Worker int64_t value = 0;
137*635a8641SAndroid Build Coastguard Worker if (reader->PopInt64(&value)) {
138*635a8641SAndroid Build Coastguard Worker DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value)) <<
139*635a8641SAndroid Build Coastguard Worker value << " is not exactly representable by double";
140*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(static_cast<double>(value));
141*635a8641SAndroid Build Coastguard Worker }
142*635a8641SAndroid Build Coastguard Worker break;
143*635a8641SAndroid Build Coastguard Worker }
144*635a8641SAndroid Build Coastguard Worker case Message::UINT64: {
145*635a8641SAndroid Build Coastguard Worker uint64_t value = 0;
146*635a8641SAndroid Build Coastguard Worker if (reader->PopUint64(&value)) {
147*635a8641SAndroid Build Coastguard Worker DLOG_IF(WARNING, !IsExactlyRepresentableByDouble(value)) <<
148*635a8641SAndroid Build Coastguard Worker value << " is not exactly representable by double";
149*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(static_cast<double>(value));
150*635a8641SAndroid Build Coastguard Worker }
151*635a8641SAndroid Build Coastguard Worker break;
152*635a8641SAndroid Build Coastguard Worker }
153*635a8641SAndroid Build Coastguard Worker case Message::DOUBLE: {
154*635a8641SAndroid Build Coastguard Worker double value = 0;
155*635a8641SAndroid Build Coastguard Worker if (reader->PopDouble(&value))
156*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
157*635a8641SAndroid Build Coastguard Worker break;
158*635a8641SAndroid Build Coastguard Worker }
159*635a8641SAndroid Build Coastguard Worker case Message::STRING: {
160*635a8641SAndroid Build Coastguard Worker std::string value;
161*635a8641SAndroid Build Coastguard Worker if (reader->PopString(&value))
162*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value);
163*635a8641SAndroid Build Coastguard Worker break;
164*635a8641SAndroid Build Coastguard Worker }
165*635a8641SAndroid Build Coastguard Worker case Message::OBJECT_PATH: {
166*635a8641SAndroid Build Coastguard Worker ObjectPath value;
167*635a8641SAndroid Build Coastguard Worker if (reader->PopObjectPath(&value))
168*635a8641SAndroid Build Coastguard Worker result = std::make_unique<base::Value>(value.value());
169*635a8641SAndroid Build Coastguard Worker break;
170*635a8641SAndroid Build Coastguard Worker }
171*635a8641SAndroid Build Coastguard Worker case Message::UNIX_FD: {
172*635a8641SAndroid Build Coastguard Worker // Cannot distinguish a file descriptor from an int
173*635a8641SAndroid Build Coastguard Worker NOTREACHED();
174*635a8641SAndroid Build Coastguard Worker break;
175*635a8641SAndroid Build Coastguard Worker }
176*635a8641SAndroid Build Coastguard Worker case Message::ARRAY: {
177*635a8641SAndroid Build Coastguard Worker MessageReader sub_reader(nullptr);
178*635a8641SAndroid Build Coastguard Worker if (reader->PopArray(&sub_reader)) {
179*635a8641SAndroid Build Coastguard Worker // If the type of the array's element is DICT_ENTRY, create a
180*635a8641SAndroid Build Coastguard Worker // DictionaryValue, otherwise create a ListValue.
181*635a8641SAndroid Build Coastguard Worker if (sub_reader.GetDataType() == Message::DICT_ENTRY) {
182*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::DictionaryValue> dictionary_value(
183*635a8641SAndroid Build Coastguard Worker new base::DictionaryValue);
184*635a8641SAndroid Build Coastguard Worker if (PopDictionaryEntries(&sub_reader, dictionary_value.get()))
185*635a8641SAndroid Build Coastguard Worker result = std::move(dictionary_value);
186*635a8641SAndroid Build Coastguard Worker } else {
187*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::ListValue> list_value(new base::ListValue);
188*635a8641SAndroid Build Coastguard Worker if (PopListElements(&sub_reader, list_value.get()))
189*635a8641SAndroid Build Coastguard Worker result = std::move(list_value);
190*635a8641SAndroid Build Coastguard Worker }
191*635a8641SAndroid Build Coastguard Worker }
192*635a8641SAndroid Build Coastguard Worker break;
193*635a8641SAndroid Build Coastguard Worker }
194*635a8641SAndroid Build Coastguard Worker case Message::STRUCT: {
195*635a8641SAndroid Build Coastguard Worker MessageReader sub_reader(nullptr);
196*635a8641SAndroid Build Coastguard Worker if (reader->PopStruct(&sub_reader)) {
197*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::ListValue> list_value(new base::ListValue);
198*635a8641SAndroid Build Coastguard Worker if (PopListElements(&sub_reader, list_value.get()))
199*635a8641SAndroid Build Coastguard Worker result = std::move(list_value);
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker break;
202*635a8641SAndroid Build Coastguard Worker }
203*635a8641SAndroid Build Coastguard Worker case Message::DICT_ENTRY:
204*635a8641SAndroid Build Coastguard Worker // DICT_ENTRY must be popped as an element of an array.
205*635a8641SAndroid Build Coastguard Worker NOTREACHED();
206*635a8641SAndroid Build Coastguard Worker break;
207*635a8641SAndroid Build Coastguard Worker case Message::VARIANT: {
208*635a8641SAndroid Build Coastguard Worker MessageReader sub_reader(nullptr);
209*635a8641SAndroid Build Coastguard Worker if (reader->PopVariant(&sub_reader))
210*635a8641SAndroid Build Coastguard Worker result = PopDataAsValue(&sub_reader);
211*635a8641SAndroid Build Coastguard Worker break;
212*635a8641SAndroid Build Coastguard Worker }
213*635a8641SAndroid Build Coastguard Worker }
214*635a8641SAndroid Build Coastguard Worker return result;
215*635a8641SAndroid Build Coastguard Worker }
216*635a8641SAndroid Build Coastguard Worker
AppendBasicTypeValueData(MessageWriter * writer,const base::Value & value)217*635a8641SAndroid Build Coastguard Worker void AppendBasicTypeValueData(MessageWriter* writer, const base::Value& value) {
218*635a8641SAndroid Build Coastguard Worker switch (value.type()) {
219*635a8641SAndroid Build Coastguard Worker case base::Value::Type::BOOLEAN: {
220*635a8641SAndroid Build Coastguard Worker bool bool_value = false;
221*635a8641SAndroid Build Coastguard Worker bool success = value.GetAsBoolean(&bool_value);
222*635a8641SAndroid Build Coastguard Worker DCHECK(success);
223*635a8641SAndroid Build Coastguard Worker writer->AppendBool(bool_value);
224*635a8641SAndroid Build Coastguard Worker break;
225*635a8641SAndroid Build Coastguard Worker }
226*635a8641SAndroid Build Coastguard Worker case base::Value::Type::INTEGER: {
227*635a8641SAndroid Build Coastguard Worker int int_value = 0;
228*635a8641SAndroid Build Coastguard Worker bool success = value.GetAsInteger(&int_value);
229*635a8641SAndroid Build Coastguard Worker DCHECK(success);
230*635a8641SAndroid Build Coastguard Worker writer->AppendInt32(int_value);
231*635a8641SAndroid Build Coastguard Worker break;
232*635a8641SAndroid Build Coastguard Worker }
233*635a8641SAndroid Build Coastguard Worker case base::Value::Type::DOUBLE: {
234*635a8641SAndroid Build Coastguard Worker double double_value = 0;
235*635a8641SAndroid Build Coastguard Worker bool success = value.GetAsDouble(&double_value);
236*635a8641SAndroid Build Coastguard Worker DCHECK(success);
237*635a8641SAndroid Build Coastguard Worker writer->AppendDouble(double_value);
238*635a8641SAndroid Build Coastguard Worker break;
239*635a8641SAndroid Build Coastguard Worker }
240*635a8641SAndroid Build Coastguard Worker case base::Value::Type::STRING: {
241*635a8641SAndroid Build Coastguard Worker std::string string_value;
242*635a8641SAndroid Build Coastguard Worker bool success = value.GetAsString(&string_value);
243*635a8641SAndroid Build Coastguard Worker DCHECK(success);
244*635a8641SAndroid Build Coastguard Worker writer->AppendString(string_value);
245*635a8641SAndroid Build Coastguard Worker break;
246*635a8641SAndroid Build Coastguard Worker }
247*635a8641SAndroid Build Coastguard Worker default:
248*635a8641SAndroid Build Coastguard Worker DLOG(ERROR) << "Unexpected type " << value.type();
249*635a8641SAndroid Build Coastguard Worker break;
250*635a8641SAndroid Build Coastguard Worker }
251*635a8641SAndroid Build Coastguard Worker }
252*635a8641SAndroid Build Coastguard Worker
AppendBasicTypeValueDataAsVariant(MessageWriter * writer,const base::Value & value)253*635a8641SAndroid Build Coastguard Worker void AppendBasicTypeValueDataAsVariant(MessageWriter* writer,
254*635a8641SAndroid Build Coastguard Worker const base::Value& value) {
255*635a8641SAndroid Build Coastguard Worker MessageWriter sub_writer(nullptr);
256*635a8641SAndroid Build Coastguard Worker writer->OpenVariant(GetTypeSignature(value), &sub_writer);
257*635a8641SAndroid Build Coastguard Worker AppendBasicTypeValueData(&sub_writer, value);
258*635a8641SAndroid Build Coastguard Worker writer->CloseContainer(&sub_writer);
259*635a8641SAndroid Build Coastguard Worker }
260*635a8641SAndroid Build Coastguard Worker
AppendValueData(MessageWriter * writer,const base::Value & value)261*635a8641SAndroid Build Coastguard Worker void AppendValueData(MessageWriter* writer, const base::Value& value) {
262*635a8641SAndroid Build Coastguard Worker switch (value.type()) {
263*635a8641SAndroid Build Coastguard Worker case base::Value::Type::DICTIONARY: {
264*635a8641SAndroid Build Coastguard Worker const base::DictionaryValue* dictionary = nullptr;
265*635a8641SAndroid Build Coastguard Worker value.GetAsDictionary(&dictionary);
266*635a8641SAndroid Build Coastguard Worker dbus::MessageWriter array_writer(nullptr);
267*635a8641SAndroid Build Coastguard Worker writer->OpenArray("{sv}", &array_writer);
268*635a8641SAndroid Build Coastguard Worker for (base::DictionaryValue::Iterator iter(*dictionary);
269*635a8641SAndroid Build Coastguard Worker !iter.IsAtEnd(); iter.Advance()) {
270*635a8641SAndroid Build Coastguard Worker dbus::MessageWriter dict_entry_writer(nullptr);
271*635a8641SAndroid Build Coastguard Worker array_writer.OpenDictEntry(&dict_entry_writer);
272*635a8641SAndroid Build Coastguard Worker dict_entry_writer.AppendString(iter.key());
273*635a8641SAndroid Build Coastguard Worker AppendValueDataAsVariant(&dict_entry_writer, iter.value());
274*635a8641SAndroid Build Coastguard Worker array_writer.CloseContainer(&dict_entry_writer);
275*635a8641SAndroid Build Coastguard Worker }
276*635a8641SAndroid Build Coastguard Worker writer->CloseContainer(&array_writer);
277*635a8641SAndroid Build Coastguard Worker break;
278*635a8641SAndroid Build Coastguard Worker }
279*635a8641SAndroid Build Coastguard Worker case base::Value::Type::LIST: {
280*635a8641SAndroid Build Coastguard Worker const base::ListValue* list = nullptr;
281*635a8641SAndroid Build Coastguard Worker value.GetAsList(&list);
282*635a8641SAndroid Build Coastguard Worker dbus::MessageWriter array_writer(nullptr);
283*635a8641SAndroid Build Coastguard Worker writer->OpenArray("v", &array_writer);
284*635a8641SAndroid Build Coastguard Worker for (const auto& value : *list) {
285*635a8641SAndroid Build Coastguard Worker AppendValueDataAsVariant(&array_writer, value);
286*635a8641SAndroid Build Coastguard Worker }
287*635a8641SAndroid Build Coastguard Worker writer->CloseContainer(&array_writer);
288*635a8641SAndroid Build Coastguard Worker break;
289*635a8641SAndroid Build Coastguard Worker }
290*635a8641SAndroid Build Coastguard Worker case base::Value::Type::BOOLEAN:
291*635a8641SAndroid Build Coastguard Worker case base::Value::Type::INTEGER:
292*635a8641SAndroid Build Coastguard Worker case base::Value::Type::DOUBLE:
293*635a8641SAndroid Build Coastguard Worker case base::Value::Type::STRING:
294*635a8641SAndroid Build Coastguard Worker AppendBasicTypeValueData(writer, value);
295*635a8641SAndroid Build Coastguard Worker break;
296*635a8641SAndroid Build Coastguard Worker default:
297*635a8641SAndroid Build Coastguard Worker DLOG(ERROR) << "Unexpected type: " << value.type();
298*635a8641SAndroid Build Coastguard Worker }
299*635a8641SAndroid Build Coastguard Worker }
300*635a8641SAndroid Build Coastguard Worker
AppendValueDataAsVariant(MessageWriter * writer,const base::Value & value)301*635a8641SAndroid Build Coastguard Worker void AppendValueDataAsVariant(MessageWriter* writer, const base::Value& value) {
302*635a8641SAndroid Build Coastguard Worker MessageWriter variant_writer(nullptr);
303*635a8641SAndroid Build Coastguard Worker writer->OpenVariant(GetTypeSignature(value), &variant_writer);
304*635a8641SAndroid Build Coastguard Worker AppendValueData(&variant_writer, value);
305*635a8641SAndroid Build Coastguard Worker writer->CloseContainer(&variant_writer);
306*635a8641SAndroid Build Coastguard Worker }
307*635a8641SAndroid Build Coastguard Worker
308*635a8641SAndroid Build Coastguard Worker } // namespace dbus
309