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.h>
18 #include <cinttypes>
19
20 #include "chre/util/nanoapp/log.h"
21 #include "chre/util/time.h"
22
23 #define LOG_TAG "[WwanWorld]"
24
25 #ifdef CHRE_NANOAPP_INTERNAL
26 namespace chre {
27 namespace {
28 #endif // CHRE_NANOAPP_INTERNAL
29
30 //! A dummy cookie to pass into the cell info request.
31 const uint32_t kCellInfoCookie = 0x1337;
32
33 //! The interval for cell info requests.
34 const Nanoseconds kCellInfoInterval = Nanoseconds(Seconds(10));
35
36 //! A handle for the cyclic timer to request periodic cell info.
37 uint32_t gCellInfoTimerHandle;
38
39 namespace {
40
41 /**
42 * Handles a timer event.
43 *
44 * @param eventData The cookie passed to the timer request.
45 */
handleTimerEvent(const void * eventData)46 void handleTimerEvent(const void *eventData) {
47 const uint32_t *timerHandle = static_cast<const uint32_t *>(eventData);
48 if (*timerHandle == gCellInfoTimerHandle) {
49 if (chreWwanGetCellInfoAsync(&kCellInfoCookie)) {
50 LOGI("Requested cell info successfully");
51 } else {
52 LOGE("Failed to request cell info");
53 }
54 } else {
55 LOGE("Received invalid timer handle");
56 }
57 }
58
59 /**
60 * Logs a CHRE WWAN cell info result.
61 *
62 * @param cell the cell info to log.
63 */
logChreWwanInfo(const chreWwanCellInfo * cell)64 void logChreWwanInfo(const chreWwanCellInfo *cell) {
65 LOGI("Found cell at time %" PRIu64, cell->timeStamp);
66 LOGI(" timestamp type %" PRIu8, cell->timeStampType);
67 LOGI(" registered %" PRIu8, cell->registered);
68
69 switch (cell->cellInfoType) {
70 case CHRE_WWAN_CELL_INFO_TYPE_LTE:
71 LOGI(" LTE cell detected");
72 LOGI(" mcc %" PRId32, cell->CellInfo.lte.cellIdentityLte.mcc);
73 LOGI(" mnc %" PRId32, cell->CellInfo.lte.cellIdentityLte.mnc);
74 LOGI(" ci %" PRId32, cell->CellInfo.lte.cellIdentityLte.ci);
75 LOGI(" pci %" PRId32, cell->CellInfo.lte.cellIdentityLte.pci);
76 LOGI(" tac %" PRId32, cell->CellInfo.lte.cellIdentityLte.tac);
77 LOGI(" earfcn %" PRId32, cell->CellInfo.lte.cellIdentityLte.earfcn);
78 break;
79 case CHRE_WWAN_CELL_INFO_TYPE_GSM:
80 LOGI(" GSM cell detected");
81 LOGI(" mcc %" PRId32, cell->CellInfo.gsm.cellIdentityGsm.mcc);
82 LOGI(" mnc %" PRId32, cell->CellInfo.gsm.cellIdentityGsm.mnc);
83 LOGI(" lac %" PRId32, cell->CellInfo.gsm.cellIdentityGsm.lac);
84 LOGI(" cid %" PRId32, cell->CellInfo.gsm.cellIdentityGsm.cid);
85 LOGI(" arfcn %" PRId32, cell->CellInfo.gsm.cellIdentityGsm.arfcn);
86 LOGI(" bsic %" PRIu8, cell->CellInfo.gsm.cellIdentityGsm.bsic);
87 break;
88 case CHRE_WWAN_CELL_INFO_TYPE_WCDMA:
89 LOGI(" WCDMA cell detected");
90 LOGI(" mcc %" PRId32, cell->CellInfo.wcdma.cellIdentityWcdma.mcc);
91 LOGI(" mnc %" PRId32, cell->CellInfo.wcdma.cellIdentityWcdma.mnc);
92 LOGI(" lac %" PRId32, cell->CellInfo.wcdma.cellIdentityWcdma.lac);
93 LOGI(" cid %" PRId32, cell->CellInfo.wcdma.cellIdentityWcdma.cid);
94 LOGI(" psc %" PRId32, cell->CellInfo.wcdma.cellIdentityWcdma.psc);
95 LOGI(" uarfcn %" PRId32, cell->CellInfo.wcdma.cellIdentityWcdma.uarfcn);
96 break;
97 default:
98 // TODO: Support logging all cell types.
99 LOGI(" unsupported cell info %" PRIu8, cell->cellInfoType);
100 break;
101 };
102 }
103
104 /**
105 * Handles a WWAN cell info result.
106 *
107 * @param result a WWAN cell info result.
108 */
handleCellInfoResult(const chreWwanCellInfoResult * result)109 void handleCellInfoResult(const chreWwanCellInfoResult *result) {
110 if (result->errorCode != CHRE_ERROR_NONE) {
111 LOGE("Failed to request WWAN cell info with %" PRIu8, result->errorCode);
112 } else {
113 LOGD("Received cell info result with version %" PRIu8, result->version);
114
115 for (uint8_t i = 0; i < result->cellInfoCount; i++) {
116 logChreWwanInfo(&result->cells[i]);
117 }
118 }
119 }
120
121 } // namespace
122
123
nanoappStart()124 bool nanoappStart() {
125 LOGI("App started as instance %" PRIu32, chreGetInstanceId());
126
127 const char *wwanCapabilitiesStr;
128 uint32_t wwanCapabilities = chreWwanGetCapabilities();
129 switch (wwanCapabilities) {
130 case CHRE_WWAN_GET_CELL_INFO:
131 wwanCapabilitiesStr = "GET_CELL_INFO";
132 break;
133 case CHRE_WWAN_CAPABILITIES_NONE:
134 wwanCapabilitiesStr = "NONE";
135 break;
136 default:
137 wwanCapabilitiesStr = "INVALID";
138 }
139
140 LOGI("Detected WWAN support as: %s (%" PRIu32 ")",
141 wwanCapabilitiesStr, wwanCapabilities);
142
143 if (wwanCapabilities & CHRE_WWAN_GET_CELL_INFO) {
144 gCellInfoTimerHandle = chreTimerSet(kCellInfoInterval.toRawNanoseconds(),
145 &gCellInfoTimerHandle /* data */,
146 false /* oneShot */);
147 if (gCellInfoTimerHandle == CHRE_TIMER_INVALID) {
148 LOGE("Failed to set a periodic cell info timer");
149 } else {
150 LOGI("Set a timer to request periodic cell info");
151 }
152 }
153
154 return true;
155 }
156
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)157 void nanoappHandleEvent(uint32_t senderInstanceId,
158 uint16_t eventType,
159 const void *eventData) {
160 switch (eventType) {
161 case CHRE_EVENT_TIMER:
162 handleTimerEvent(eventData);
163 break;
164 case CHRE_EVENT_WWAN_CELL_INFO_RESULT:
165 handleCellInfoResult(
166 static_cast<const chreWwanCellInfoResult *>(eventData));
167 break;
168 default:
169 LOGW("Unhandled event type %" PRIu16, eventType);
170 }
171 }
172
nanoappEnd()173 void nanoappEnd() {
174 LOGI("Stopped");
175 }
176
177 #ifdef CHRE_NANOAPP_INTERNAL
178 } // anonymous namespace
179 } // namespace chre
180
181 #include "chre/util/nanoapp/app_id.h"
182 #include "chre/platform/static_nanoapp_init.h"
183
184 CHRE_STATIC_NANOAPP_INIT(WwanWorld, chre::kWwanWorldAppId, 0);
185 #endif // CHRE_NANOAPP_INTERNAL
186