• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 <cstddef>
18 #include <cstdint>
19 #include <cstdlib>
20 #include <cstring>
21 
22 #include "chre/util/system/service_helpers.h"
23 
24 namespace chre::message {
25 
26 namespace {
27 
28 //! Legacy format is: chre.nanoapp_0x<nanoappId>.service_0x<serviceId>
29 //! All IDs are in hexadecimal
30 constexpr char kPrefix[] = "chre.nanoapp_0x";
31 constexpr size_t kPrefixLength = sizeof(kPrefix) - 1;
32 constexpr char kSeparator[] = ".service_0x";
33 constexpr size_t kSeparatorLength = sizeof(kSeparator) - 1;
34 constexpr size_t kEncodingLength = 16;
35 constexpr size_t kBase = 16;
36 constexpr size_t kServiceDescriptorLength =
37     kPrefixLength + kEncodingLength + kSeparatorLength + kEncodingLength;
38 
39 //! Converts a string containing a 16-character hexadecimal encoding to a
40 //! uint64_t. We are using this instead of directly using strtoull because
41 //! some of our platforms do not support this function.
42 //! @return the converted uint64_t
convertEncodedIdToUint64(const char * str)43 uint64_t convertEncodedIdToUint64(const char *str) {
44   constexpr size_t kHalfEncodingLength = kEncodingLength / 2;
45   char buffer[kHalfEncodingLength + 1];
46   buffer[kHalfEncodingLength] = '\0';
47 
48   // Convert the first half (upper 32 bits) of the encoding to a uint64_t
49   memcpy(buffer, str, kHalfEncodingLength);
50   uint64_t resultFirst = strtoul(buffer, nullptr, kBase);
51 
52   // Convert the second half (lower 32 bits) of the encoding to a uint64_t
53   memcpy(buffer, str + kHalfEncodingLength, kHalfEncodingLength);
54   uint64_t resultSecond = strtoul(buffer, nullptr, kBase);
55 
56   // Combine the two halves into a single uint64_t
57   return (resultFirst << 32) | resultSecond;
58 }
59 
60 }  // anonymous namespace
61 
extractNanoappIdAndServiceId(const char * serviceDescriptor,uint64_t & nanoappId,uint64_t & serviceId)62 bool extractNanoappIdAndServiceId(const char *serviceDescriptor,
63                                   uint64_t &nanoappId, uint64_t &serviceId) {
64   // Reject null service descriptors
65   if (serviceDescriptor == nullptr) {
66     return false;
67   }
68 
69   // Check the service descriptor length
70   if (strlen(serviceDescriptor) != kServiceDescriptorLength) {
71     return false;
72   }
73 
74   // Check if the service descriptor starts with the legacy prefix
75   if (strstr(serviceDescriptor, kPrefix) != serviceDescriptor) {
76     return false;
77   }
78 
79   // Check if the service descriptor contains the separator in the correct
80   // location
81   const char *separatorIndex =
82       strstr(serviceDescriptor + kPrefixLength, kSeparator);
83   if (separatorIndex == nullptr ||
84       (reinterpret_cast<uintptr_t>(separatorIndex) -
85        reinterpret_cast<uintptr_t>(serviceDescriptor)) *
86               sizeof(char) !=
87           kPrefixLength + kEncodingLength) {
88     return false;
89   }
90 
91   // Convert the encoded strings for the IDs to uint64_t
92   nanoappId = convertEncodedIdToUint64(serviceDescriptor + kPrefixLength);
93   serviceId = convertEncodedIdToUint64(separatorIndex + kSeparatorLength);
94   return true;
95 }
96 
97 }  // namespace chre::message
98