| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015, 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 | |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 17 | #include <memory> |
| Christopher Wiley | 12e894a | 2016-01-29 11:55:07 -0800 | [diff] [blame] | 18 | #include <set> |
| 19 | #include <string> |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 20 | #include <vector> |
| 21 | |
| Christopher Wiley | ec31a05 | 2016-01-25 07:28:51 -0800 | [diff] [blame] | 22 | #include <android-base/stringprintf.h> |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 23 | #include <gtest/gtest.h> |
| 24 | |
| 25 | #include "aidl.h" |
| 26 | #include "aidl_language.h" |
| 27 | #include "tests/fake_io_delegate.h" |
| 28 | #include "type_cpp.h" |
| 29 | #include "type_java.h" |
| 30 | #include "type_namespace.h" |
| 31 | |
| 32 | using android::aidl::test::FakeIoDelegate; |
| Christopher Wiley | ec31a05 | 2016-01-25 07:28:51 -0800 | [diff] [blame] | 33 | using android::base::StringPrintf; |
| Christopher Wiley | 12e894a | 2016-01-29 11:55:07 -0800 | [diff] [blame] | 34 | using std::set; |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 35 | using std::string; |
| 36 | using std::unique_ptr; |
| Christopher Wiley | 12e894a | 2016-01-29 11:55:07 -0800 | [diff] [blame] | 37 | using std::vector; |
| Christopher Wiley | ef14093 | 2015-11-03 09:29:19 -0800 | [diff] [blame] | 38 | using android::aidl::internals::parse_preprocessed_file; |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 39 | |
| 40 | namespace android { |
| 41 | namespace aidl { |
| 42 | |
| 43 | class AidlTest : public ::testing::Test { |
| 44 | protected: |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 45 | void SetUp() override { |
| 46 | java_types_.Init(); |
| 47 | cpp_types_.Init(); |
| 48 | } |
| 49 | |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 50 | unique_ptr<AidlInterface> Parse(const string& path, |
| 51 | const string& contents, |
| 52 | TypeNamespace* types) { |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 53 | io_delegate_.SetFileContents(path, contents); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 54 | unique_ptr<AidlInterface> ret; |
| 55 | std::vector<std::unique_ptr<AidlImport>> imports; |
| 56 | ::android::aidl::internals::load_and_validate_aidl( |
| Christopher Wiley | 4154437 | 2015-11-03 14:52:29 -0800 | [diff] [blame] | 57 | preprocessed_files_, |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 58 | import_paths_, |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 59 | path, |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 60 | io_delegate_, |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 61 | types, |
| 62 | &ret, |
| 63 | &imports); |
| 64 | return ret; |
| 65 | } |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 66 | |
| 67 | FakeIoDelegate io_delegate_; |
| Christopher Wiley | 4154437 | 2015-11-03 14:52:29 -0800 | [diff] [blame] | 68 | vector<string> preprocessed_files_; |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 69 | vector<string> import_paths_; |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 70 | java::JavaTypeNamespace java_types_; |
| 71 | cpp::TypeNamespace cpp_types_; |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 72 | }; |
| 73 | |
| 74 | TEST_F(AidlTest, JavaAcceptsMissingPackage) { |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 75 | EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", &java_types_)); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 76 | } |
| 77 | |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 78 | TEST_F(AidlTest, RejectsArraysOfBinders) { |
| 79 | import_paths_.push_back(""); |
| 80 | io_delegate_.SetFileContents("bar/IBar.aidl", |
| 81 | "package bar; interface IBar {}"); |
| 82 | string path = "foo/IFoo.aidl"; |
| 83 | string contents = "package foo;\n" |
| 84 | "import bar.IBar;\n" |
| 85 | "interface IFoo { void f(in IBar[] input); }"; |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 86 | EXPECT_EQ(nullptr, Parse(path, contents, &java_types_)); |
| 87 | EXPECT_EQ(nullptr, Parse(path, contents, &cpp_types_)); |
| Christopher Wiley | 0522cd5 | 2015-10-28 15:39:44 -0700 | [diff] [blame] | 88 | } |
| 89 | |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 90 | TEST_F(AidlTest, CppRejectsMissingPackage) { |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 91 | EXPECT_EQ(nullptr, Parse("IFoo.aidl", "interface IFoo { }", &cpp_types_)); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 92 | EXPECT_NE(nullptr, |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 93 | Parse("a/IFoo.aidl", "package a; interface IFoo { }", &cpp_types_)); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | TEST_F(AidlTest, RejectsOnewayOutParameters) { |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 97 | string oneway_interface = |
| 98 | "package a; oneway interface IFoo { void f(out int bar); }"; |
| 99 | string oneway_method = |
| 100 | "package a; interface IBar { oneway void f(out int bar); }"; |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 101 | EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_interface, &cpp_types_)); |
| 102 | EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_interface, &java_types_)); |
| 103 | EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, &cpp_types_)); |
| 104 | EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, &java_types_)); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | TEST_F(AidlTest, RejectsOnewayNonVoidReturn) { |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 108 | string oneway_method = "package a; interface IFoo { oneway int f(); }"; |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 109 | EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_)); |
| 110 | EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_)); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 111 | } |
| 112 | |
| Casey Dahlin | 57dbe24 | 2015-12-04 11:44:02 -0800 | [diff] [blame] | 113 | TEST_F(AidlTest, RejectsNullablePrimitive) { |
| 114 | string oneway_method = "package a; interface IFoo { @nullable int f(); }"; |
| 115 | EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_)); |
| 116 | EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_)); |
| 117 | } |
| 118 | |
| Christopher Wiley | ec31a05 | 2016-01-25 07:28:51 -0800 | [diff] [blame] | 119 | TEST_F(AidlTest, ParsesNullableAnnotation) { |
| 120 | for (auto is_nullable: {true, false}) { |
| 121 | auto parse_result = Parse( |
| 122 | "a/IFoo.aidl", |
| 123 | StringPrintf( "package a; interface IFoo {%s String f(); }", |
| 124 | (is_nullable) ? "@nullable" : ""), |
| 125 | &cpp_types_); |
| 126 | ASSERT_NE(nullptr, parse_result); |
| 127 | ASSERT_FALSE(parse_result->GetMethods().empty()); |
| 128 | EXPECT_EQ(parse_result->GetMethods()[0]->GetType().IsNullable(), |
| 129 | is_nullable); |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | TEST_F(AidlTest, ParsesUtf8Annotations) { |
| 134 | for (auto is_utf8: {true, false}) { |
| 135 | auto parse_result = Parse( |
| 136 | "a/IFoo.aidl", |
| 137 | StringPrintf( "package a; interface IFoo {%s String f(); }", |
| Christopher Wiley | 9f40372 | 2016-01-27 16:04:11 -0800 | [diff] [blame] | 138 | (is_utf8) ? "@utf8InCpp" : ""), |
| Christopher Wiley | b7e0117 | 2016-01-28 16:32:34 -0800 | [diff] [blame] | 139 | &cpp_types_); |
| Christopher Wiley | ec31a05 | 2016-01-25 07:28:51 -0800 | [diff] [blame] | 140 | ASSERT_NE(nullptr, parse_result); |
| 141 | ASSERT_FALSE(parse_result->GetMethods().empty()); |
| Christopher Wiley | 9f40372 | 2016-01-27 16:04:11 -0800 | [diff] [blame] | 142 | EXPECT_EQ(parse_result->GetMethods()[0]->GetType().IsUtf8InCpp(), |
| Christopher Wiley | ec31a05 | 2016-01-25 07:28:51 -0800 | [diff] [blame] | 143 | is_utf8); |
| 144 | } |
| 145 | } |
| 146 | |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 147 | TEST_F(AidlTest, AcceptsOneway) { |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 148 | string oneway_method = "package a; interface IFoo { oneway void f(int a); }"; |
| 149 | string oneway_interface = |
| 150 | "package a; oneway interface IBar { void f(int a); }"; |
| Christopher Wiley | 5679952 | 2015-10-31 10:17:04 -0700 | [diff] [blame] | 151 | EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_)); |
| 152 | EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_)); |
| 153 | EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, &cpp_types_)); |
| 154 | EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, &java_types_)); |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 155 | } |
| Christopher Wiley | ef14093 | 2015-11-03 09:29:19 -0800 | [diff] [blame] | 156 | |
| 157 | TEST_F(AidlTest, ParsesPreprocessedFile) { |
| 158 | string simple_content = "parcelable a.Foo;\ninterface b.IBar;"; |
| 159 | io_delegate_.SetFileContents("path", simple_content); |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 160 | EXPECT_FALSE(java_types_.HasTypeByCanonicalName("a.Foo")); |
| Christopher Wiley | ef14093 | 2015-11-03 09:29:19 -0800 | [diff] [blame] | 161 | EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &java_types_)); |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 162 | EXPECT_TRUE(java_types_.HasTypeByCanonicalName("a.Foo")); |
| 163 | EXPECT_TRUE(java_types_.HasTypeByCanonicalName("b.IBar")); |
| Christopher Wiley | ef14093 | 2015-11-03 09:29:19 -0800 | [diff] [blame] | 164 | } |
| 165 | |
| 166 | TEST_F(AidlTest, ParsesPreprocessedFileWithWhitespace) { |
| 167 | string simple_content = "parcelable a.Foo;\n interface b.IBar ;\t"; |
| 168 | io_delegate_.SetFileContents("path", simple_content); |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 169 | EXPECT_FALSE(java_types_.HasTypeByCanonicalName("a.Foo")); |
| Christopher Wiley | ef14093 | 2015-11-03 09:29:19 -0800 | [diff] [blame] | 170 | EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &java_types_)); |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 171 | EXPECT_TRUE(java_types_.HasTypeByCanonicalName("a.Foo")); |
| 172 | EXPECT_TRUE(java_types_.HasTypeByCanonicalName("b.IBar")); |
| Christopher Wiley | ef14093 | 2015-11-03 09:29:19 -0800 | [diff] [blame] | 173 | } |
| 174 | |
| Christopher Wiley | 4154437 | 2015-11-03 14:52:29 -0800 | [diff] [blame] | 175 | TEST_F(AidlTest, PreferImportToPreprocessed) { |
| 176 | io_delegate_.SetFileContents("preprocessed", "interface another.IBar;"); |
| 177 | io_delegate_.SetFileContents("one/IBar.aidl", "package one; " |
| 178 | "interface IBar {}"); |
| 179 | preprocessed_files_.push_back("preprocessed"); |
| 180 | import_paths_.push_back(""); |
| 181 | auto parse_result = Parse( |
| 182 | "p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}", |
| 183 | &java_types_); |
| 184 | EXPECT_NE(nullptr, parse_result); |
| 185 | // We expect to know about both kinds of IBar |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 186 | EXPECT_TRUE(java_types_.HasTypeByCanonicalName("one.IBar")); |
| 187 | EXPECT_TRUE(java_types_.HasTypeByCanonicalName("another.IBar")); |
| Christopher Wiley | 4154437 | 2015-11-03 14:52:29 -0800 | [diff] [blame] | 188 | // But if we request just "IBar" we should get our imported one. |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 189 | AidlType ambiguous_type("IBar", 0, "", false /* not an array */); |
| 190 | const java::Type* type = java_types_.Find(ambiguous_type); |
| Christopher Wiley | 4154437 | 2015-11-03 14:52:29 -0800 | [diff] [blame] | 191 | ASSERT_TRUE(type); |
| Christopher Wiley | d21bfee | 2016-01-29 15:11:38 -0800 | [diff] [blame] | 192 | EXPECT_EQ("one.IBar", type->CanonicalName()); |
| Christopher Wiley | 4154437 | 2015-11-03 14:52:29 -0800 | [diff] [blame] | 193 | } |
| 194 | |
| Casey Dahlin | c1f39b4 | 2015-11-24 10:34:34 -0800 | [diff] [blame] | 195 | TEST_F(AidlTest, WritePreprocessedFile) { |
| 196 | io_delegate_.SetFileContents("p/Outer.aidl", |
| 197 | "package p; parcelable Outer.Inner;"); |
| 198 | io_delegate_.SetFileContents("one/IBar.aidl", "package one; import p.Outer;" |
| 199 | "interface IBar {}"); |
| 200 | |
| 201 | JavaOptions options; |
| 202 | options.output_file_name_ = "preprocessed"; |
| 203 | options.files_to_preprocess_.resize(2); |
| 204 | options.files_to_preprocess_[0] = "p/Outer.aidl"; |
| 205 | options.files_to_preprocess_[1] = "one/IBar.aidl"; |
| 206 | EXPECT_TRUE(::android::aidl::preprocess_aidl(options, io_delegate_)); |
| 207 | |
| 208 | string output; |
| 209 | EXPECT_TRUE(io_delegate_.GetWrittenContents("preprocessed", &output)); |
| 210 | EXPECT_EQ("parcelable p.Outer.Inner;\ninterface one.IBar;\n", output); |
| 211 | } |
| 212 | |
| Christopher Wiley | 63bce2a | 2015-11-03 14:55:03 -0800 | [diff] [blame] | 213 | TEST_F(AidlTest, RequireOuterClass) { |
| 214 | io_delegate_.SetFileContents("p/Outer.aidl", |
| 215 | "package p; parcelable Outer.Inner;"); |
| 216 | import_paths_.push_back(""); |
| 217 | auto parse_result = Parse( |
| 218 | "p/IFoo.aidl", |
| 219 | "package p; import p.Outer; interface IFoo { void f(in Inner c); }", |
| 220 | &java_types_); |
| 221 | EXPECT_EQ(nullptr, parse_result); |
| 222 | } |
| 223 | |
| 224 | TEST_F(AidlTest, ParseCompoundParcelableFromPreprocess) { |
| 225 | io_delegate_.SetFileContents("preprocessed", |
| 226 | "parcelable p.Outer.Inner;"); |
| 227 | preprocessed_files_.push_back("preprocessed"); |
| 228 | auto parse_result = Parse( |
| 229 | "p/IFoo.aidl", |
| 230 | "package p; interface IFoo { void f(in Inner c); }", |
| 231 | &java_types_); |
| 232 | // TODO(wiley): This should actually return nullptr because we require |
| 233 | // the outer class name. However, for legacy reasons, |
| 234 | // this behavior must be maintained. b/17415692 |
| 235 | EXPECT_NE(nullptr, parse_result); |
| 236 | } |
| 237 | |
| Christopher Wiley | 632801d | 2015-11-05 14:15:49 -0800 | [diff] [blame] | 238 | TEST_F(AidlTest, FailOnParcelable) { |
| 239 | JavaOptions options; |
| 240 | options.input_file_name_ = "p/IFoo.aidl"; |
| 241 | io_delegate_.SetFileContents(options.input_file_name_, |
| 242 | "package p; parcelable IFoo;"); |
| 243 | // By default, we shouldn't fail on parcelable. |
| 244 | EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_)); |
| 245 | options.fail_on_parcelable_ = true; |
| 246 | EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_)); |
| 247 | } |
| 248 | |
| Christopher Wiley | 9078d72 | 2015-11-17 10:23:49 -0800 | [diff] [blame] | 249 | TEST_F(AidlTest, UnderstandsNativeParcelables) { |
| 250 | io_delegate_.SetFileContents( |
| 251 | "p/Bar.aidl", |
| Casey Dahlin | cd63921 | 2015-12-15 12:51:04 -0800 | [diff] [blame] | 252 | "package p; parcelable Bar cpp_header \"baz/header\";"); |
| Christopher Wiley | 9078d72 | 2015-11-17 10:23:49 -0800 | [diff] [blame] | 253 | import_paths_.push_back(""); |
| 254 | const string input_path = "p/IFoo.aidl"; |
| 255 | const string input = "package p; import p.Bar; interface IFoo { }"; |
| 256 | |
| 257 | // C++ understands C++ specific stuff |
| 258 | auto cpp_parse_result = Parse(input_path, input, &cpp_types_); |
| 259 | EXPECT_NE(nullptr, cpp_parse_result); |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 260 | auto cpp_type = cpp_types_.FindTypeByCanonicalName("p.Bar"); |
| Christopher Wiley | 9078d72 | 2015-11-17 10:23:49 -0800 | [diff] [blame] | 261 | ASSERT_NE(nullptr, cpp_type); |
| Casey Dahlin | a2f77c4 | 2015-12-01 18:26:02 -0800 | [diff] [blame] | 262 | EXPECT_EQ("::p::Bar", cpp_type->CppType()); |
| Christopher Wiley | 9078d72 | 2015-11-17 10:23:49 -0800 | [diff] [blame] | 263 | set<string> headers; |
| Casey Dahlin | a2f77c4 | 2015-12-01 18:26:02 -0800 | [diff] [blame] | 264 | cpp_type->GetHeaders(&headers); |
| Christopher Wiley | 9078d72 | 2015-11-17 10:23:49 -0800 | [diff] [blame] | 265 | EXPECT_EQ(1u, headers.size()); |
| 266 | EXPECT_EQ(1u, headers.count("baz/header")); |
| 267 | |
| 268 | // Java ignores C++ specific stuff |
| 269 | auto java_parse_result = Parse(input_path, input, &java_types_); |
| 270 | EXPECT_NE(nullptr, java_parse_result); |
| Christopher Wiley | 9ab0623 | 2016-01-27 14:55:18 -0800 | [diff] [blame] | 271 | auto java_type = java_types_.FindTypeByCanonicalName("p.Bar"); |
| Christopher Wiley | 9078d72 | 2015-11-17 10:23:49 -0800 | [diff] [blame] | 272 | ASSERT_NE(nullptr, java_type); |
| 273 | EXPECT_EQ("p.Bar", java_type->InstantiableName()); |
| 274 | } |
| 275 | |
| Christopher Wiley | 90be4e3 | 2015-10-20 14:55:25 -0700 | [diff] [blame] | 276 | } // namespace aidl |
| 277 | } // namespace android |