1 /*
2  * Copyright (C) 2020 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/pal/wwan.h"
18 
19 #include "chre/platform/linux/task_util/task_manager.h"
20 
21 #include "chre/util/memory.h"
22 #include "chre/util/unique_ptr.h"
23 
24 #include <chrono>
25 #include <cinttypes>
26 
27 /**
28  * A simulated implementation of the WWAN PAL for the linux platform.
29  */
30 namespace {
31 
32 using ::chre::TaskManagerSingleton;
33 
34 const struct chrePalSystemApi *gSystemApi = nullptr;
35 const struct chrePalWwanCallbacks *gCallbacks = nullptr;
36 
37 //! Task to deliver asynchronous WWAN cell info results after a CHRE request.
38 std::optional<uint32_t> gCellInfosTaskId;
39 
sendCellInfoResult()40 void sendCellInfoResult() {
41   auto result = chre::MakeUniqueZeroFill<struct chreWwanCellInfoResult>();
42   auto cell = chre::MakeUniqueZeroFill<struct chreWwanCellInfo>();
43   cell->timeStamp = gSystemApi->getCurrentTime();
44   cell->cellInfoType = CHRE_WWAN_CELL_INFO_TYPE_GSM;
45   // INT*_MAX == unknown
46   cell->CellInfo.gsm.cellIdentityGsm.mcc = INT32_MAX;
47   cell->CellInfo.gsm.cellIdentityGsm.mnc = INT32_MAX;
48   cell->CellInfo.gsm.cellIdentityGsm.lac = INT32_MAX;
49   cell->CellInfo.gsm.cellIdentityGsm.cid = INT32_MAX;
50   cell->CellInfo.gsm.cellIdentityGsm.arfcn = INT32_MAX;
51   cell->CellInfo.gsm.cellIdentityGsm.bsic = INT8_MAX;
52   cell->CellInfo.gsm.signalStrengthGsm.signalStrength = INT32_MAX;
53   cell->CellInfo.gsm.signalStrengthGsm.signalStrength = INT32_MAX;
54   cell->CellInfo.gsm.signalStrengthGsm.signalStrength = INT32_MAX;
55 
56   result->cellInfoCount = 1;
57   result->errorCode = CHRE_ERROR_NONE;
58   result->cells = cell.release();
59 
60   gCallbacks->cellInfoResultCallback(result.release());
61 }
62 
stopCellInfoTask()63 void stopCellInfoTask() {
64   if (gCellInfosTaskId.has_value()) {
65     TaskManagerSingleton::get()->cancelTask(*gCellInfosTaskId);
66     gCellInfosTaskId.reset();
67   }
68 }
69 
chrePalWwanGetCapabilities()70 uint32_t chrePalWwanGetCapabilities() {
71   return CHRE_WWAN_GET_CELL_INFO;
72 }
73 
chrePalWwanRequestCellInfo()74 bool chrePalWwanRequestCellInfo() {
75   stopCellInfoTask();
76   gCellInfosTaskId = TaskManagerSingleton::get()->addTask(sendCellInfoResult);
77   return gCellInfosTaskId.has_value();
78 }
79 
chrePalWwanReleaseCellInfoResult(struct chreWwanCellInfoResult * result)80 void chrePalWwanReleaseCellInfoResult(struct chreWwanCellInfoResult *result) {
81   for (uint8_t i = 0; i < result->cellInfoCount; i++) {
82     chre::memoryFree(const_cast<struct chreWwanCellInfo *>(&result->cells[i]));
83   }
84   chre::memoryFree(result);
85 }
86 
chrePalWwanApiClose()87 void chrePalWwanApiClose() {
88   stopCellInfoTask();
89 }
90 
chrePalWwanApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalWwanCallbacks * callbacks)91 bool chrePalWwanApiOpen(const struct chrePalSystemApi *systemApi,
92                         const struct chrePalWwanCallbacks *callbacks) {
93   chrePalWwanApiClose();
94 
95   bool success = false;
96   if (systemApi != nullptr && callbacks != nullptr) {
97     gSystemApi = systemApi;
98     gCallbacks = callbacks;
99     success = true;
100   }
101 
102   return success;
103 }
104 
105 }  // anonymous namespace
106 
chrePalWwanGetApi(uint32_t requestedApiVersion)107 const struct chrePalWwanApi *chrePalWwanGetApi(uint32_t requestedApiVersion) {
108   static const struct chrePalWwanApi kApi = {
109       .moduleVersion = CHRE_PAL_WWAN_API_CURRENT_VERSION,
110       .open = chrePalWwanApiOpen,
111       .close = chrePalWwanApiClose,
112       .getCapabilities = chrePalWwanGetCapabilities,
113       .requestCellInfo = chrePalWwanRequestCellInfo,
114       .releaseCellInfoResult = chrePalWwanReleaseCellInfoResult,
115   };
116 
117   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
118                                         requestedApiVersion)) {
119     return nullptr;
120   } else {
121     return &kApi;
122   }
123 }
124