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