• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include "chre/util/nanoapp/app_id.h"
18 #include "chre_host/host_protocol_host.h"
19 #include "chre_host/log.h"
20 #include "chre_host/socket_client.h"
21 
22 #include <inttypes.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 
26 #include <fstream>
27 #include <thread>
28 
29 #include <cutils/sockets.h>
30 #include <utils/StrongPointer.h>
31 
32 /**
33  * @file
34  * A test utility that connects to the CHRE daemon that runs on the apps
35  * processor of MSM chipsets, which is used to help test basic functionality.
36  */
37 
38 using android::sp;
39 using android::chre::getStringFromByteVector;
40 using android::chre::FragmentedLoadTransaction;
41 using android::chre::HostProtocolHost;
42 using android::chre::IChreMessageHandlers;
43 using android::chre::SocketClient;
44 using flatbuffers::FlatBufferBuilder;
45 
46 // Aliased for consistency with the way these symbols are referenced in
47 // CHRE-side code
48 namespace fbs = ::chre::fbs;
49 
50 namespace {
51 
52 //! The host endpoint we use when sending; set to CHRE_HOST_ENDPOINT_UNSPECIFIED
53 //! Other clients below the HAL may use a value above 0x8000 to enable unicast
54 //! messaging (currently requires internal coordination to avoid conflict;
55 //! in the future these should be assigned by the daemon).
56 constexpr uint16_t kHostEndpoint = 0xfffe;
57 
58 class SocketCallbacks : public SocketClient::ICallbacks,
59                         public IChreMessageHandlers {
60  public:
onMessageReceived(const void * data,size_t length)61   void onMessageReceived(const void *data, size_t length) override {
62     if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) {
63       LOGE("Failed to decode message");
64     }
65   }
66 
onConnected()67   void onConnected() override {
68     LOGI("Socket (re)connected");
69   }
70 
onConnectionAborted()71   void onConnectionAborted() override {
72     LOGI("Socket (re)connection aborted");
73   }
74 
onDisconnected()75   void onDisconnected() override {
76     LOGI("Socket disconnected");
77   }
78 
handleNanoappMessage(const fbs::NanoappMessageT & message)79   void handleNanoappMessage(const fbs::NanoappMessageT& message)
80       override {
81     LOGI("Got message from nanoapp 0x%" PRIx64 " to endpoint 0x%" PRIx16
82          " with type 0x%" PRIx32 " and length %zu", message.app_id,
83          message.host_endpoint, message.message_type, message.message.size());
84   }
85 
handleHubInfoResponse(const fbs::HubInfoResponseT & rsp)86   void handleHubInfoResponse(const fbs::HubInfoResponseT& rsp)
87       override {
88     LOGI("Got hub info response:");
89     LOGI("  Name: '%s'", getStringFromByteVector(rsp.name));
90     LOGI("  Vendor: '%s'", getStringFromByteVector(rsp.vendor));
91     LOGI("  Toolchain: '%s'", getStringFromByteVector(rsp.toolchain));
92     LOGI("  Legacy versions: platform 0x%08" PRIx32 " toolchain 0x%08" PRIx32,
93          rsp.platform_version, rsp.toolchain_version);
94     LOGI("  MIPS %.2f Power (mW): stopped %.2f sleep %.2f peak %.2f",
95          rsp.peak_mips, rsp.stopped_power, rsp.sleep_power, rsp.peak_power);
96     LOGI("  Max message len: %" PRIu32, rsp.max_msg_len);
97     LOGI("  Platform ID: 0x%016" PRIx64 " Version: 0x%08" PRIx32,
98          rsp.platform_id, rsp.chre_platform_version);
99   }
100 
handleNanoappListResponse(const fbs::NanoappListResponseT & response)101   void handleNanoappListResponse(const fbs::NanoappListResponseT& response)
102       override {
103     LOGI("Got nanoapp list response with %zu apps:", response.nanoapps.size());
104     for (const std::unique_ptr<fbs::NanoappListEntryT>& nanoapp
105            : response.nanoapps) {
106       LOGI("  App ID 0x%016" PRIx64 " version 0x%" PRIx32 " enabled %d system "
107            "%d", nanoapp->app_id, nanoapp->version, nanoapp->enabled,
108            nanoapp->is_system);
109     }
110   }
111 
handleLoadNanoappResponse(const fbs::LoadNanoappResponseT & response)112   void handleLoadNanoappResponse(const fbs::LoadNanoappResponseT& response)
113       override {
114     LOGI("Got load nanoapp response, transaction ID 0x%" PRIx32 " result %d",
115          response.transaction_id, response.success);
116   }
117 
handleUnloadNanoappResponse(const fbs::UnloadNanoappResponseT & response)118   void handleUnloadNanoappResponse(const fbs::UnloadNanoappResponseT& response)
119       override {
120     LOGI("Got unload nanoapp response, transaction ID 0x%" PRIx32 " result %d",
121          response.transaction_id, response.success);
122   }
123 };
124 
requestHubInfo(SocketClient & client)125 void requestHubInfo(SocketClient& client) {
126   FlatBufferBuilder builder(64);
127   HostProtocolHost::encodeHubInfoRequest(builder);
128 
129   LOGI("Sending hub info request (%" PRIu32 " bytes)", builder.GetSize());
130   if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
131     LOGE("Failed to send message");
132   }
133 }
134 
requestNanoappList(SocketClient & client)135 void requestNanoappList(SocketClient& client) {
136   FlatBufferBuilder builder(64);
137   HostProtocolHost::encodeNanoappListRequest(builder);
138 
139   LOGI("Sending app list request (%" PRIu32 " bytes)", builder.GetSize());
140   if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
141     LOGE("Failed to send message");
142   }
143 }
144 
sendMessageToNanoapp(SocketClient & client)145 void sendMessageToNanoapp(SocketClient& client) {
146   FlatBufferBuilder builder(64);
147   uint8_t messageData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
148   HostProtocolHost::encodeNanoappMessage(
149       builder, chre::kMessageWorldAppId, 1234 /* messageType */,
150       kHostEndpoint, messageData, sizeof(messageData));
151 
152   LOGI("Sending message to nanoapp (%" PRIu32 " bytes w/%zu bytes of payload)",
153        builder.GetSize(), sizeof(messageData));
154   if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
155     LOGE("Failed to send message");
156   }
157 }
158 
sendLoadNanoappRequest(SocketClient & client,const char * filename)159 void sendLoadNanoappRequest(SocketClient& client, const char *filename) {
160   std::ifstream file(filename, std::ios::binary | std::ios::ate);
161   if (!file) {
162     LOGE("Couldn't open file '%s': %s", filename, strerror(errno));
163     return;
164   }
165   ssize_t size = file.tellg();
166   file.seekg(0, std::ios::beg);
167 
168   std::vector<uint8_t> buffer(size);
169   if (!file.read(reinterpret_cast<char *>(buffer.data()), size)) {
170     LOGE("Couldn't read from file: %s", strerror(errno));
171     return;
172   }
173 
174   // Perform loading with 1 fragment for simplicity
175   FlatBufferBuilder builder(size + 128);
176   FragmentedLoadTransaction transaction = FragmentedLoadTransaction(
177       1 /* transactionId */, 0x476f6f676c00100b /* appId */, 0 /* appVersion */,
178       0x01000000 /* targetApiVersion */, buffer,
179       buffer.size() /* fragmentSize */);
180   HostProtocolHost::encodeFragmentedLoadNanoappRequest(
181       builder, transaction.getNextRequest());
182 
183   LOGI("Sending load nanoapp request (%" PRIu32 " bytes total w/%zu bytes of "
184        "payload)", builder.GetSize(), buffer.size());
185   if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
186     LOGE("Failed to send message");
187   }
188 }
189 
sendUnloadNanoappRequest(SocketClient & client,uint64_t appId)190 void sendUnloadNanoappRequest(SocketClient& client, uint64_t appId) {
191   FlatBufferBuilder builder(48);
192   constexpr uint32_t kTransactionId = 4321;
193   HostProtocolHost::encodeUnloadNanoappRequest(
194       builder, kTransactionId, appId, true /* allowSystemNanoappUnload */);
195 
196   LOGI("Sending unload request for nanoapp 0x%016" PRIx64 " (size %" PRIu32 ")",
197        appId, builder.GetSize());
198   if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
199     LOGE("Failed to send message");
200   }
201 }
202 
203 }  // anonymous namespace
204 
main()205 int main() {
206   SocketClient client;
207   sp<SocketCallbacks> callbacks = new SocketCallbacks();
208 
209   if (!client.connect("chre", callbacks)) {
210     LOGE("Couldn't connect to socket");
211   } else {
212     requestHubInfo(client);
213     requestNanoappList(client);
214     sendMessageToNanoapp(client);
215     sendLoadNanoappRequest(client, "/data/activity.so");
216     sendUnloadNanoappRequest(client, chre::kSpammerAppId);
217 
218     LOGI("Sleeping, waiting on responses");
219     std::this_thread::sleep_for(std::chrono::seconds(5));
220   }
221 
222  return 0;
223 }
224