| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2016 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 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 17 | #define LOG_TAG "mediametrics::Item" | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 18 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 19 | #include <inttypes.h> | 
| Ray Essick | b5fac8e | 2016-12-12 11:33:56 -0800 | [diff] [blame] | 20 | #include <stdlib.h> | 
 | 21 | #include <string.h> | 
 | 22 | #include <sys/types.h> | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 23 |  | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 24 | #include <mutex> | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 25 | #include <set> | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 26 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 27 | #include <binder/Parcel.h> | 
 | 28 | #include <utils/Errors.h> | 
 | 29 | #include <utils/Log.h> | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 30 | #include <utils/SortedVector.h> | 
 | 31 | #include <utils/threads.h> | 
 | 32 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 33 | #include <binder/IServiceManager.h> | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 34 | #include <media/IMediaMetricsService.h> | 
 | 35 | #include <media/MediaMetricsItem.h> | 
| Ray Essick | 79a89ef | 2017-04-24 15:52:54 -0700 | [diff] [blame] | 36 | #include <private/android_filesystem_config.h> | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 37 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 38 | // Max per-property string size before truncation in toString(). | 
 | 39 | // Do not make too large, as this is used for dumpsys purposes. | 
 | 40 | static constexpr size_t kMaxPropertyStringSize = 4096; | 
 | 41 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 42 | namespace android::mediametrics { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 43 |  | 
 | 44 | #define DEBUG_SERVICEACCESS     0 | 
| Ray Essick | b5fac8e | 2016-12-12 11:33:56 -0800 | [diff] [blame] | 45 | #define DEBUG_API               0 | 
 | 46 | #define DEBUG_ALLOCATIONS       0 | 
 | 47 |  | 
 | 48 | // after this many failed attempts, we stop trying [from this process] and just say that | 
 | 49 | // the service is off. | 
 | 50 | #define SVC_TRIES               2 | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 51 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 52 | mediametrics::Item* mediametrics::Item::convert(mediametrics_handle_t handle) { | 
 | 53 |     mediametrics::Item *item = (android::mediametrics::Item *) handle; | 
| Ray Essick | bf536ac | 2019-08-26 11:04:28 -0700 | [diff] [blame] | 54 |     return item; | 
 | 55 | } | 
 | 56 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 57 | mediametrics_handle_t mediametrics::Item::convert(mediametrics::Item *item ) { | 
| Ray Essick | bf536ac | 2019-08-26 11:04:28 -0700 | [diff] [blame] | 58 |     mediametrics_handle_t handle = (mediametrics_handle_t) item; | 
 | 59 |     return handle; | 
 | 60 | } | 
 | 61 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 62 | mediametrics::Item::~Item() { | 
| Ray Essick | b5fac8e | 2016-12-12 11:33:56 -0800 | [diff] [blame] | 63 |     if (DEBUG_ALLOCATIONS) { | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 64 |         ALOGD("Destroy  mediametrics::Item @ %p", this); | 
| Ray Essick | b5fac8e | 2016-12-12 11:33:56 -0800 | [diff] [blame] | 65 |     } | 
| Ray Essick | b5fac8e | 2016-12-12 11:33:56 -0800 | [diff] [blame] | 66 | } | 
 | 67 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 68 | mediametrics::Item &mediametrics::Item::setTimestamp(nsecs_t ts) { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 69 |     mTimestamp = ts; | 
 | 70 |     return *this; | 
 | 71 | } | 
 | 72 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 73 | nsecs_t mediametrics::Item::getTimestamp() const { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 74 |     return mTimestamp; | 
 | 75 | } | 
 | 76 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 77 | mediametrics::Item &mediametrics::Item::setPid(pid_t pid) { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 78 |     mPid = pid; | 
 | 79 |     return *this; | 
 | 80 | } | 
 | 81 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 82 | pid_t mediametrics::Item::getPid() const { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 83 |     return mPid; | 
 | 84 | } | 
 | 85 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 86 | mediametrics::Item &mediametrics::Item::setUid(uid_t uid) { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 87 |     mUid = uid; | 
 | 88 |     return *this; | 
 | 89 | } | 
 | 90 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 91 | uid_t mediametrics::Item::getUid() const { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 92 |     return mUid; | 
 | 93 | } | 
 | 94 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 95 | mediametrics::Item &mediametrics::Item::setPkgName(const std::string &pkgName) { | 
| Ray Essick | f65f421 | 2017-08-31 11:41:19 -0700 | [diff] [blame] | 96 |     mPkgName = pkgName; | 
 | 97 |     return *this; | 
 | 98 | } | 
 | 99 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 100 | mediametrics::Item &mediametrics::Item::setPkgVersionCode(int64_t pkgVersionCode) { | 
| Ray Essick | f65f421 | 2017-08-31 11:41:19 -0700 | [diff] [blame] | 101 |     mPkgVersionCode = pkgVersionCode; | 
 | 102 |     return *this; | 
 | 103 | } | 
 | 104 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 105 | int64_t mediametrics::Item::getPkgVersionCode() const { | 
| Ray Essick | f65f421 | 2017-08-31 11:41:19 -0700 | [diff] [blame] | 106 |     return mPkgVersionCode; | 
 | 107 | } | 
 | 108 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 109 | // remove indicated keys and their values | 
 | 110 | // return value is # keys removed | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 111 | size_t mediametrics::Item::filter(size_t n, const char *attrs[]) { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 112 |     size_t zapped = 0; | 
 | 113 |     for (size_t i = 0; i < n; ++i) { | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 114 |         zapped += mProps.erase(attrs[i]); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 115 |     } | 
 | 116 |     return zapped; | 
 | 117 | } | 
 | 118 |  | 
 | 119 | // remove any keys NOT in the provided list | 
 | 120 | // return value is # keys removed | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 121 | size_t mediametrics::Item::filterNot(size_t n, const char *attrs[]) { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 122 |     std::set<std::string> check(attrs, attrs + n); | 
 | 123 |     size_t zapped = 0; | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 124 |     for (auto it = mProps.begin(); it != mProps.end();) { | 
 | 125 |         if (check.find(it->first) != check.end()) { | 
 | 126 |             ++it; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 127 |         } else { | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 128 |            it = mProps.erase(it); | 
 | 129 |            ++zapped; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 130 |         } | 
 | 131 |     } | 
 | 132 |     return zapped; | 
 | 133 | } | 
 | 134 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 135 | // Parcel / serialize things for binder calls | 
 | 136 | // | 
 | 137 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 138 | status_t mediametrics::Item::readFromParcel(const Parcel& data) { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 139 |     int32_t version; | 
 | 140 |     status_t status = data.readInt32(&version); | 
 | 141 |     if (status != NO_ERROR) return status; | 
| Ray Essick | ba8c484 | 2019-01-18 11:35:33 -0800 | [diff] [blame] | 142 |  | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 143 |     switch (version) { | 
 | 144 |     case 0: | 
 | 145 |       return readFromParcel0(data); | 
 | 146 |     default: | 
 | 147 |       ALOGE("%s: unsupported parcel version: %d", __func__, version); | 
 | 148 |       return INVALID_OPERATION; | 
| Ray Essick | ba8c484 | 2019-01-18 11:35:33 -0800 | [diff] [blame] | 149 |     } | 
 | 150 | } | 
 | 151 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 152 | status_t mediametrics::Item::readFromParcel0(const Parcel& data) { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 153 |     const char *s = data.readCString(); | 
 | 154 |     mKey = s == nullptr ? "" : s; | 
 | 155 |     int32_t pid, uid; | 
 | 156 |     status_t status = data.readInt32(&pid) ?: data.readInt32(&uid); | 
 | 157 |     if (status != NO_ERROR) return status; | 
 | 158 |     mPid = (pid_t)pid; | 
 | 159 |     mUid = (uid_t)uid; | 
 | 160 |     s = data.readCString(); | 
 | 161 |     mPkgName = s == nullptr ? "" : s; | 
 | 162 |     int32_t count; | 
 | 163 |     int64_t version, timestamp; | 
 | 164 |     status = data.readInt64(&version) ?: data.readInt64(×tamp) ?: data.readInt32(&count); | 
 | 165 |     if (status != NO_ERROR) return status; | 
 | 166 |     if (count < 0) return BAD_VALUE; | 
 | 167 |     mPkgVersionCode = version; | 
 | 168 |     mTimestamp = timestamp; | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 169 |     for (int i = 0; i < count; i++) { | 
 | 170 |         Prop prop; | 
 | 171 |         status_t status = prop.readFromParcel(data); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 172 |         if (status != NO_ERROR) return status; | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 173 |         mProps[prop.getName()] = std::move(prop); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 174 |     } | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 175 |     return NO_ERROR; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 176 | } | 
 | 177 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 178 | status_t mediametrics::Item::writeToParcel(Parcel *data) const { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 179 |     if (data == nullptr) return BAD_VALUE; | 
| Ray Essick | ba8c484 | 2019-01-18 11:35:33 -0800 | [diff] [blame] | 180 |  | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 181 |     const int32_t version = 0; | 
 | 182 |     status_t status = data->writeInt32(version); | 
 | 183 |     if (status != NO_ERROR) return status; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 184 |  | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 185 |     switch (version) { | 
 | 186 |     case 0: | 
 | 187 |       return writeToParcel0(data); | 
 | 188 |     default: | 
 | 189 |       ALOGE("%s: unsupported parcel version: %d", __func__, version); | 
 | 190 |       return INVALID_OPERATION; | 
| Ray Essick | ba8c484 | 2019-01-18 11:35:33 -0800 | [diff] [blame] | 191 |     } | 
 | 192 | } | 
 | 193 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 194 | status_t mediametrics::Item::writeToParcel0(Parcel *data) const { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 195 |     status_t status = | 
 | 196 |         data->writeCString(mKey.c_str()) | 
 | 197 |         ?: data->writeInt32(mPid) | 
 | 198 |         ?: data->writeInt32(mUid) | 
 | 199 |         ?: data->writeCString(mPkgName.c_str()) | 
 | 200 |         ?: data->writeInt64(mPkgVersionCode) | 
 | 201 |         ?: data->writeInt64(mTimestamp); | 
 | 202 |     if (status != NO_ERROR) return status; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 203 |  | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 204 |     data->writeInt32((int32_t)mProps.size()); | 
 | 205 |     for (auto &prop : *this) { | 
 | 206 |         status = prop.writeToParcel(data); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 207 |         if (status != NO_ERROR) return status; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 208 |     } | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 209 |     return NO_ERROR; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 210 | } | 
 | 211 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 212 | const char *mediametrics::Item::toCString() { | 
| Ray Essick | 2014732 | 2018-11-17 09:08:39 -0800 | [diff] [blame] | 213 |    return toCString(PROTO_LAST); | 
 | 214 | } | 
 | 215 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 216 | const char * mediametrics::Item::toCString(int version) { | 
| Ray Essick | 2014732 | 2018-11-17 09:08:39 -0800 | [diff] [blame] | 217 |     std::string val = toString(version); | 
 | 218 |     return strdup(val.c_str()); | 
 | 219 | } | 
 | 220 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 221 | std::string mediametrics::Item::toString() const { | 
| Ray Essick | 5b77bd2 | 2018-01-23 16:11:06 -0800 | [diff] [blame] | 222 |    return toString(PROTO_LAST); | 
| Ray Essick | f65f421 | 2017-08-31 11:41:19 -0700 | [diff] [blame] | 223 | } | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 224 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 225 | std::string mediametrics::Item::toString(int version) const { | 
| Ray Essick | 783bd0d | 2018-01-11 11:10:35 -0800 | [diff] [blame] | 226 |     std::string result; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 227 |     char buffer[kMaxPropertyStringSize]; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 228 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 229 |     snprintf(buffer, sizeof(buffer), "[%d:%s:%d:%d:%lld:%s:%zu:", | 
 | 230 |             version, mKey.c_str(), mPid, mUid, (long long)mTimestamp, | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 231 |             mPkgName.c_str(), mProps.size()); | 
| Ray Essick | f65f421 | 2017-08-31 11:41:19 -0700 | [diff] [blame] | 232 |     result.append(buffer); | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 233 |     for (auto &prop : *this) { | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 234 |         prop.toStringBuffer(buffer, sizeof(buffer)); | 
| Andy Hung | aeef788 | 2019-10-18 15:18:14 -0700 | [diff] [blame] | 235 |         result.append(buffer); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 236 |     } | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 237 |     result.append("]"); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 238 |     return result; | 
 | 239 | } | 
 | 240 |  | 
 | 241 | // for the lazy, we offer methods that finds the service and | 
 | 242 | // calls the appropriate daemon | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 243 | bool mediametrics::Item::selfrecord() { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 244 |     ALOGD_IF(DEBUG_API, "%s: delivering %s", __func__, this->toString().c_str()); | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 245 |     sp<IMediaMetricsService> svc = getService(); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 246 |     if (svc != NULL) { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 247 |         status_t status = svc->submit(this); | 
 | 248 |         if (status != NO_ERROR) { | 
 | 249 |             ALOGW("%s: failed to record: %s", __func__, this->toString().c_str()); | 
| Ray Essick | 2ab3c43 | 2017-10-02 09:29:49 -0700 | [diff] [blame] | 250 |             return false; | 
 | 251 |         } | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 252 |         return true; | 
 | 253 |     } else { | 
 | 254 |         return false; | 
 | 255 |     } | 
 | 256 | } | 
 | 257 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 258 | //static | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 259 | bool BaseItem::isEnabled() { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 260 |     // completely skip logging from certain UIDs. We do this here | 
 | 261 |     // to avoid the multi-second timeouts while we learn that | 
 | 262 |     // sepolicy will not let us find the service. | 
 | 263 |     // We do this only for a select set of UIDs | 
 | 264 |     // The sepolicy protection is still in place, we just want a faster | 
 | 265 |     // response from this specific, small set of uids. | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 266 |  | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 267 |     // This is checked only once in the lifetime of the process. | 
 | 268 |     const uid_t uid = getuid(); | 
 | 269 |     switch (uid) { | 
 | 270 |     case AID_RADIO:     // telephony subsystem, RIL | 
 | 271 |         return false; | 
 | 272 |     } | 
 | 273 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 274 |     int enabled = property_get_int32(Item::EnabledProperty, -1); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 275 |     if (enabled == -1) { | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 276 |         enabled = property_get_int32(Item::EnabledPropertyPersist, -1); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 277 |     } | 
 | 278 |     if (enabled == -1) { | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 279 |         enabled = Item::EnabledProperty_default; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 280 |     } | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 281 |     return enabled > 0; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 282 | } | 
 | 283 |  | 
| Ray Essick | 2ab3c43 | 2017-10-02 09:29:49 -0700 | [diff] [blame] | 284 | // monitor health of our connection to the metrics service | 
 | 285 | class MediaMetricsDeathNotifier : public IBinder::DeathRecipient { | 
 | 286 |         virtual void binderDied(const wp<IBinder> &) { | 
 | 287 |             ALOGW("Reacquire service connection on next request"); | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 288 |             BaseItem::dropInstance(); | 
| Ray Essick | 2ab3c43 | 2017-10-02 09:29:49 -0700 | [diff] [blame] | 289 |         } | 
 | 290 | }; | 
 | 291 |  | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 292 | static sp<MediaMetricsDeathNotifier> sNotifier; | 
 | 293 | // static | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 294 | sp<IMediaMetricsService> BaseItem::sMediaMetricsService; | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 295 | static std::mutex sServiceMutex; | 
 | 296 | static int sRemainingBindAttempts = SVC_TRIES; | 
| Ray Essick | 2ab3c43 | 2017-10-02 09:29:49 -0700 | [diff] [blame] | 297 |  | 
 | 298 | // static | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 299 | void BaseItem::dropInstance() { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 300 |     std::lock_guard  _l(sServiceMutex); | 
 | 301 |     sRemainingBindAttempts = SVC_TRIES; | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 302 |     sMediaMetricsService = nullptr; | 
| Ray Essick | 2ab3c43 | 2017-10-02 09:29:49 -0700 | [diff] [blame] | 303 | } | 
 | 304 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 305 | // static | 
 | 306 | bool BaseItem::submitBuffer(const char *buffer, size_t size) { | 
 | 307 | /* | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 308 |     mediametrics::Item item; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 309 |     status_t status = item.readFromByteString(buffer, size); | 
 | 310 |     ALOGD("%s: status:%d, size:%zu, item:%s", __func__, status, size, item.toString().c_str()); | 
 | 311 |     return item.selfrecord(); | 
 | 312 |     */ | 
 | 313 |  | 
 | 314 |     ALOGD_IF(DEBUG_API, "%s: delivering %zu bytes", __func__, size); | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 315 |     sp<IMediaMetricsService> svc = getService(); | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 316 |     if (svc != nullptr) { | 
 | 317 |         const status_t status = svc->submitBuffer(buffer, size); | 
 | 318 |         if (status != NO_ERROR) { | 
 | 319 |             ALOGW("%s: failed(%d) to record: %zu bytes", __func__, status, size); | 
 | 320 |             return false; | 
 | 321 |         } | 
 | 322 |         return true; | 
 | 323 |     } | 
 | 324 |     return false; | 
 | 325 | } | 
 | 326 |  | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 327 | //static | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 328 | sp<IMediaMetricsService> BaseItem::getService() { | 
| Ray Essick | d38e174 | 2017-01-23 15:17:06 -0800 | [diff] [blame] | 329 |     static const char *servicename = "media.metrics"; | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 330 |     static const bool enabled = isEnabled(); // singleton initialized | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 331 |  | 
 | 332 |     if (enabled == false) { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 333 |         ALOGD_IF(DEBUG_SERVICEACCESS, "disabled"); | 
 | 334 |         return nullptr; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 335 |     } | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 336 |     std::lock_guard _l(sServiceMutex); | 
 | 337 |     // think of remainingBindAttempts as telling us whether service == nullptr because | 
 | 338 |     // (1) we haven't tried to initialize it yet | 
 | 339 |     // (2) we've tried to initialize it, but failed. | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 340 |     if (sMediaMetricsService == nullptr && sRemainingBindAttempts > 0) { | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 341 |         const char *badness = ""; | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 342 |         sp<IServiceManager> sm = defaultServiceManager(); | 
 | 343 |         if (sm != nullptr) { | 
 | 344 |             sp<IBinder> binder = sm->getService(String16(servicename)); | 
 | 345 |             if (binder != nullptr) { | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 346 |                 sMediaMetricsService = interface_cast<IMediaMetricsService>(binder); | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 347 |                 sNotifier = new MediaMetricsDeathNotifier(); | 
 | 348 |                 binder->linkToDeath(sNotifier); | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 349 |             } else { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 350 |                 badness = "did not find service"; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 351 |             } | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 352 |         } else { | 
 | 353 |             badness = "No Service Manager access"; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 354 |         } | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 355 |         if (sMediaMetricsService == nullptr) { | 
| Andy Hung | a87e69c | 2019-10-18 10:07:40 -0700 | [diff] [blame] | 356 |             if (sRemainingBindAttempts > 0) { | 
 | 357 |                 sRemainingBindAttempts--; | 
 | 358 |             } | 
 | 359 |             ALOGD_IF(DEBUG_SERVICEACCESS, "%s: unable to bind to service %s: %s", | 
 | 360 |                     __func__, servicename, badness); | 
 | 361 |         } | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 362 |     } | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 363 |     return sMediaMetricsService; | 
| Ray Essick | 3938dc6 | 2016-11-01 08:56:56 -0700 | [diff] [blame] | 364 | } | 
 | 365 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 366 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 367 | status_t mediametrics::Item::writeToByteString(char **pbuffer, size_t *plength) const | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 368 | { | 
 | 369 |     if (pbuffer == nullptr || plength == nullptr) | 
 | 370 |         return BAD_VALUE; | 
 | 371 |  | 
 | 372 |     // get size | 
 | 373 |     const size_t keySizeZeroTerminated = strlen(mKey.c_str()) + 1; | 
 | 374 |     if (keySizeZeroTerminated > UINT16_MAX) { | 
 | 375 |         ALOGW("%s: key size %zu too large", __func__, keySizeZeroTerminated); | 
 | 376 |         return INVALID_OPERATION; | 
 | 377 |     } | 
 | 378 |     const uint16_t version = 0; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 379 |     const uint32_t header_size = | 
 | 380 |         sizeof(uint32_t)      // total size | 
 | 381 |         + sizeof(header_size) // header size | 
 | 382 |         + sizeof(version)     // encoding version | 
 | 383 |         + sizeof(uint16_t)    // key size | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 384 |         + keySizeZeroTerminated // key, zero terminated | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 385 |         + sizeof(int32_t)     // pid | 
 | 386 |         + sizeof(int32_t)     // uid | 
 | 387 |         + sizeof(int64_t)     // timestamp | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 388 |         ; | 
 | 389 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 390 |     uint32_t size = header_size | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 391 |         + sizeof(uint32_t) // # properties | 
 | 392 |         ; | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 393 |     for (auto &prop : *this) { | 
 | 394 |         const size_t propSize = prop.getByteStringSize(); | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 395 |         if (propSize > UINT16_MAX) { | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 396 |             ALOGW("%s: prop %s size %zu too large", __func__, prop.getName(), propSize); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 397 |             return INVALID_OPERATION; | 
 | 398 |         } | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 399 |         if (__builtin_add_overflow(size, propSize, &size)) { | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 400 |             ALOGW("%s: item size overflow at property %s", __func__, prop.getName()); | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 401 |             return INVALID_OPERATION; | 
 | 402 |         } | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 403 |     } | 
 | 404 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 405 |     // since we fill every byte in the buffer (there is no padding), | 
 | 406 |     // malloc is used here instead of calloc. | 
 | 407 |     char * const build = (char *)malloc(size); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 408 |     if (build == nullptr) return NO_MEMORY; | 
 | 409 |  | 
 | 410 |     char *filling = build; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 411 |     char *buildmax = build + size; | 
 | 412 |     if (insert((uint32_t)size, &filling, buildmax) != NO_ERROR | 
 | 413 |             || insert(header_size, &filling, buildmax) != NO_ERROR | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 414 |             || insert(version, &filling, buildmax) != NO_ERROR | 
 | 415 |             || insert((uint16_t)keySizeZeroTerminated, &filling, buildmax) != NO_ERROR | 
 | 416 |             || insert(mKey.c_str(), &filling, buildmax) != NO_ERROR | 
 | 417 |             || insert((int32_t)mPid, &filling, buildmax) != NO_ERROR | 
 | 418 |             || insert((int32_t)mUid, &filling, buildmax) != NO_ERROR | 
 | 419 |             || insert((int64_t)mTimestamp, &filling, buildmax) != NO_ERROR | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 420 |             || insert((uint32_t)mProps.size(), &filling, buildmax) != NO_ERROR) { | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 421 |         ALOGE("%s:could not write header", __func__);  // shouldn't happen | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 422 |         free(build); | 
 | 423 |         return INVALID_OPERATION; | 
 | 424 |     } | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 425 |     for (auto &prop : *this) { | 
 | 426 |         if (prop.writeToByteString(&filling, buildmax) != NO_ERROR) { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 427 |             free(build); | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 428 |             // shouldn't happen | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 429 |             ALOGE("%s:could not write prop %s", __func__, prop.getName()); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 430 |             return INVALID_OPERATION; | 
 | 431 |         } | 
 | 432 |     } | 
 | 433 |  | 
 | 434 |     if (filling != buildmax) { | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 435 |         ALOGE("%s: problems populating; wrote=%d planned=%d", | 
 | 436 |                 __func__, (int)(filling - build), (int)size); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 437 |         free(build); | 
 | 438 |         return INVALID_OPERATION; | 
 | 439 |     } | 
 | 440 |     *pbuffer = build; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 441 |     *plength = size; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 442 |     return NO_ERROR; | 
 | 443 | } | 
 | 444 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 445 | status_t mediametrics::Item::readFromByteString(const char *bufferptr, size_t length) | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 446 | { | 
 | 447 |     if (bufferptr == nullptr) return BAD_VALUE; | 
 | 448 |  | 
 | 449 |     const char *read = bufferptr; | 
 | 450 |     const char *readend = bufferptr + length; | 
 | 451 |  | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 452 |     uint32_t size; | 
 | 453 |     uint32_t header_size; | 
 | 454 |     uint16_t version; | 
 | 455 |     uint16_t key_size; | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 456 |     std::string key; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 457 |     int32_t pid; | 
 | 458 |     int32_t uid; | 
 | 459 |     int64_t timestamp; | 
 | 460 |     uint32_t propCount; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 461 |     if (extract(&size, &read, readend) != NO_ERROR | 
 | 462 |             || extract(&header_size, &read, readend) != NO_ERROR | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 463 |             || extract(&version, &read, readend) != NO_ERROR | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 464 |             || extract(&key_size, &read, readend) != NO_ERROR | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 465 |             || extract(&key, &read, readend) != NO_ERROR | 
 | 466 |             || extract(&pid, &read, readend) != NO_ERROR | 
 | 467 |             || extract(&uid, &read, readend) != NO_ERROR | 
 | 468 |             || extract(×tamp, &read, readend) != NO_ERROR | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 469 |             || size > length | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 470 |             || key.size() + 1 != key_size | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 471 |             || header_size > size) { | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 472 |         ALOGW("%s: invalid header", __func__); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 473 |         return INVALID_OPERATION; | 
 | 474 |     } | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 475 |     mKey = std::move(key); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 476 |     const size_t pos = read - bufferptr; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 477 |     if (pos > header_size) { | 
 | 478 |         ALOGW("%s: invalid header pos:%zu > header_size:%u", | 
 | 479 |                 __func__, pos, header_size); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 480 |         return INVALID_OPERATION; | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 481 |     } else if (pos < header_size) { | 
 | 482 |         ALOGW("%s: mismatched header pos:%zu < header_size:%u, advancing", | 
 | 483 |                 __func__, pos, header_size); | 
 | 484 |         read += (header_size - pos); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 485 |     } | 
 | 486 |     if (extract(&propCount, &read, readend) != NO_ERROR) { | 
 | 487 |         ALOGD("%s: cannot read prop count", __func__); | 
 | 488 |         return INVALID_OPERATION; | 
 | 489 |     } | 
 | 490 |     mPid = pid; | 
 | 491 |     mUid = uid; | 
 | 492 |     mTimestamp = timestamp; | 
 | 493 |     for (size_t i = 0; i < propCount; ++i) { | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 494 |         Prop prop; | 
 | 495 |         if (prop.readFromByteString(&read, readend) != NO_ERROR) { | 
| Andy Hung | 1efc9c6 | 2019-12-03 13:43:33 -0800 | [diff] [blame] | 496 |             ALOGW("%s: cannot read prop %zu", __func__, i); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 497 |             return INVALID_OPERATION; | 
 | 498 |         } | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 499 |         mProps[prop.getName()] = std::move(prop); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 500 |     } | 
 | 501 |     return NO_ERROR; | 
 | 502 | } | 
 | 503 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 504 | status_t mediametrics::Item::Prop::readFromParcel(const Parcel& data) | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 505 | { | 
 | 506 |     const char *key = data.readCString(); | 
 | 507 |     if (key == nullptr) return BAD_VALUE; | 
 | 508 |     int32_t type; | 
 | 509 |     status_t status = data.readInt32(&type); | 
 | 510 |     if (status != NO_ERROR) return status; | 
 | 511 |     switch (type) { | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 512 |     case mediametrics::kTypeInt32: { | 
 | 513 |         int32_t value; | 
 | 514 |         status = data.readInt32(&value); | 
 | 515 |         if (status != NO_ERROR) return status; | 
 | 516 |         mElem = value; | 
 | 517 |     } break; | 
 | 518 |     case mediametrics::kTypeInt64: { | 
 | 519 |         int64_t value; | 
 | 520 |         status = data.readInt64(&value); | 
 | 521 |         if (status != NO_ERROR) return status; | 
 | 522 |         mElem = value; | 
 | 523 |     } break; | 
 | 524 |     case mediametrics::kTypeDouble: { | 
 | 525 |         double value; | 
 | 526 |         status = data.readDouble(&value); | 
 | 527 |         if (status != NO_ERROR) return status; | 
 | 528 |         mElem = value; | 
 | 529 |     } break; | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 530 |     case mediametrics::kTypeCString: { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 531 |         const char *s = data.readCString(); | 
 | 532 |         if (s == nullptr) return BAD_VALUE; | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 533 |         mElem = s; | 
 | 534 |     } break; | 
| Andy Hung | 47e58d6 | 2019-12-06 18:40:19 -0800 | [diff] [blame] | 535 |     case mediametrics::kTypeRate: { | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 536 |         std::pair<int64_t, int64_t> rate; | 
 | 537 |         status = data.readInt64(&rate.first) | 
 | 538 |                 ?: data.readInt64(&rate.second); | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 539 |         if (status != NO_ERROR) return status; | 
 | 540 |         mElem = rate; | 
 | 541 |     } break; | 
 | 542 |     case mediametrics::kTypeNone: { | 
 | 543 |         mElem = std::monostate{}; | 
 | 544 |     } break; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 545 |     default: | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 546 |         ALOGE("%s: reading bad item type: %d", __func__, type); | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 547 |         return BAD_VALUE; | 
 | 548 |     } | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 549 |     setName(key); | 
 | 550 |     return NO_ERROR; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 551 | } | 
 | 552 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 553 | status_t mediametrics::Item::Prop::readFromByteString( | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 554 |         const char **bufferpptr, const char *bufferptrmax) | 
 | 555 | { | 
 | 556 |     uint16_t len; | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 557 |     std::string name; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 558 |     uint8_t type; | 
 | 559 |     status_t status = extract(&len, bufferpptr, bufferptrmax) | 
 | 560 |             ?: extract(&type, bufferpptr, bufferptrmax) | 
 | 561 |             ?: extract(&name, bufferpptr, bufferptrmax); | 
 | 562 |     if (status != NO_ERROR) return status; | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 563 |     switch (type) { | 
 | 564 |     case mediametrics::kTypeInt32: { | 
 | 565 |         int32_t value; | 
 | 566 |         status = extract(&value, bufferpptr, bufferptrmax); | 
 | 567 |         if (status != NO_ERROR) return status; | 
 | 568 |         mElem = value; | 
 | 569 |     } break; | 
 | 570 |     case mediametrics::kTypeInt64: { | 
 | 571 |         int64_t value; | 
 | 572 |         status = extract(&value, bufferpptr, bufferptrmax); | 
 | 573 |         if (status != NO_ERROR) return status; | 
 | 574 |         mElem = value; | 
 | 575 |     } break; | 
 | 576 |     case mediametrics::kTypeDouble: { | 
 | 577 |         double value; | 
 | 578 |         status = extract(&value, bufferpptr, bufferptrmax); | 
 | 579 |         if (status != NO_ERROR) return status; | 
 | 580 |         mElem = value; | 
 | 581 |     } break; | 
 | 582 |     case mediametrics::kTypeRate: { | 
 | 583 |         std::pair<int64_t, int64_t> value; | 
 | 584 |         status = extract(&value.first, bufferpptr, bufferptrmax) | 
 | 585 |                 ?: extract(&value.second, bufferpptr, bufferptrmax); | 
 | 586 |         if (status != NO_ERROR) return status; | 
 | 587 |         mElem = value; | 
 | 588 |     } break; | 
 | 589 |     case mediametrics::kTypeCString: { | 
 | 590 |         std::string value; | 
 | 591 |         status = extract(&value, bufferpptr, bufferptrmax); | 
 | 592 |         if (status != NO_ERROR) return status; | 
 | 593 |         mElem = std::move(value); | 
 | 594 |     } break; | 
 | 595 |     case mediametrics::kTypeNone: { | 
 | 596 |         mElem = std::monostate{}; | 
 | 597 |     } break; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 598 |     default: | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 599 |         ALOGE("%s: found bad prop type: %d, name %s", | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 600 |                 __func__, (int)type, mName.c_str());  // no payload sent | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 601 |         return BAD_VALUE; | 
 | 602 |     } | 
| Andy Hung | b7aadb3 | 2019-12-09 19:40:42 -0800 | [diff] [blame^] | 603 |     mName = name; | 
 | 604 |     return NO_ERROR; | 
| Andy Hung | 3253f2d | 2019-10-21 14:50:07 -0700 | [diff] [blame] | 605 | } | 
 | 606 |  | 
| Ray Essick | f27e987 | 2019-12-07 06:28:46 -0800 | [diff] [blame] | 607 | } // namespace android::mediametrics |