• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #define LOG_TAG "mediametrics::Item-Serialization"
18 
19 #include <inttypes.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/endian.h>
23 #include <sys/types.h>
24 
25 #include <binder/Parcel.h>
26 #include <cutils/multiuser.h>
27 #include <cutils/properties.h>
28 #include <utils/Errors.h>
29 #include <utils/Log.h>
30 #include <utils/SortedVector.h>
31 #include <utils/threads.h>
32 
33 #include <android/media/BnMediaMetricsService.h> // for direct Binder access
34 #include <android/media/IMediaMetricsService.h>
35 #include <binder/IServiceManager.h>
36 #include <media/MediaMetricsItem.h>
37 #include <private/android_filesystem_config.h>
38 
39 // Max per-property string size before truncation in toString().
40 // Do not make too large, as this is used for dumpsys purposes.
41 static constexpr size_t kMaxPropertyStringSize = 4096;
42 
43 namespace android::mediametrics {
44 
45 // Parcel / serialize things for binder calls
46 //
47 
readFromParcel(const Parcel & data)48 status_t mediametrics::Item::readFromParcel(const Parcel& data) {
49     int32_t version;
50     status_t status = data.readInt32(&version);
51     if (status != NO_ERROR) return status;
52 
53     switch (version) {
54     case 0:
55       return readFromParcel0(data);
56     default:
57       ALOGE("%s: unsupported parcel version: %d", __func__, version);
58       return INVALID_OPERATION;
59     }
60 }
61 
readFromParcel0(const Parcel & data)62 status_t mediametrics::Item::readFromParcel0(const Parcel& data) {
63     mKey = std::string{data.readString8()};
64     int32_t pid, uid;
65     status_t status = data.readInt32(&pid) ?: data.readInt32(&uid);
66     if (status != NO_ERROR) return status;
67     mPid = (pid_t)pid;
68     mUid = (uid_t)uid;
69     mPkgName = std::string(data.readString8());
70     int32_t count;
71     int64_t version, timestamp;
72     status = data.readInt64(&version) ?: data.readInt64(&timestamp) ?: data.readInt32(&count);
73     if (status != NO_ERROR) return status;
74     if (count < 0) return BAD_VALUE;
75     mPkgVersionCode = version;
76     mTimestamp = timestamp;
77     for (int i = 0; i < count; i++) {
78         Prop prop;
79         status_t status = prop.readFromParcel(data);
80         if (status != NO_ERROR) return status;
81         mProps[prop.getName()] = std::move(prop);
82     }
83     return NO_ERROR;
84 }
85 
writeToParcel(Parcel * data) const86 status_t mediametrics::Item::writeToParcel(Parcel *data) const {
87     if (data == nullptr) return BAD_VALUE;
88 
89     const int32_t version = 0;
90     status_t status = data->writeInt32(version);
91     if (status != NO_ERROR) return status;
92 
93     switch (version) {
94     case 0:
95       return writeToParcel0(data);
96     default:
97       ALOGE("%s: unsupported parcel version: %d", __func__, version);
98       return INVALID_OPERATION;
99     }
100 }
101 
writeToParcel0(Parcel * data) const102 status_t mediametrics::Item::writeToParcel0(Parcel *data) const {
103     status_t status =
104         data->writeString8(String8{mKey})
105         ?: data->writeInt32(mPid)
106         ?: data->writeInt32(mUid)
107         ?: data->writeString8(String8{mPkgName})
108         ?: data->writeInt64(mPkgVersionCode)
109         ?: data->writeInt64(mTimestamp);
110     if (status != NO_ERROR) return status;
111 
112     data->writeInt32((int32_t)mProps.size());
113     for (auto &prop : *this) {
114         status = prop.writeToParcel(data);
115         if (status != NO_ERROR) return status;
116     }
117     return NO_ERROR;
118 }
119 
readFromParcel(const Parcel & data)120 status_t mediametrics::Item::Prop::readFromParcel(const Parcel& data)
121 {
122     const std::string key {data.readString8()};
123     int32_t type;
124     status_t status = data.readInt32(&type);
125     if (status != NO_ERROR) return status;
126     switch (type) {
127     case mediametrics::kTypeInt32: {
128         int32_t value;
129         status = data.readInt32(&value);
130         if (status != NO_ERROR) return status;
131         mElem = value;
132     } break;
133     case mediametrics::kTypeInt64: {
134         int64_t value;
135         status = data.readInt64(&value);
136         if (status != NO_ERROR) return status;
137         mElem = value;
138     } break;
139     case mediametrics::kTypeDouble: {
140         double value;
141         status = data.readDouble(&value);
142         if (status != NO_ERROR) return status;
143         mElem = value;
144     } break;
145     case mediametrics::kTypeCString: {
146         mElem = std::string{data.readString8()};
147     } break;
148     case mediametrics::kTypeRate: {
149         std::pair<int64_t, int64_t> rate;
150         status = data.readInt64(&rate.first)
151                 ?: data.readInt64(&rate.second);
152         if (status != NO_ERROR) return status;
153         mElem = rate;
154     } break;
155     case mediametrics::kTypeNone: {
156         mElem = std::monostate{};
157     } break;
158     default:
159         ALOGE("%s: reading bad item type: %d", __func__, type);
160         return BAD_VALUE;
161     }
162     setName(key);
163     return NO_ERROR;
164 }
165 
166 } // namespace android::mediametrics
167