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 #include <android/os/StatsLogEventWrapper.h>
17 
18 #include <binder/Parcel.h>
19 #include <binder/Parcelable.h>
20 #include <binder/Status.h>
21 #include <utils/RefBase.h>
22 #include <vector>
23 
24 using android::Parcel;
25 using android::Parcelable;
26 using android::status_t;
27 using std::vector;
28 
29 namespace android {
30 namespace os {
31 
StatsLogEventWrapper()32 StatsLogEventWrapper::StatsLogEventWrapper(){};
33 
writeToParcel(Parcel * out) const34 status_t StatsLogEventWrapper::writeToParcel(Parcel* out) const {
35   // Implement me if desired. We don't currently use this.
36   ALOGE(
37       "Cannot do c++ StatsLogEventWrapper.writeToParcel(); it is not "
38       "implemented.");
39   (void)out;  // To prevent compile error of unused parameter 'in'
40   return UNKNOWN_ERROR;
41 };
42 
readFromParcel(const Parcel * in)43 status_t StatsLogEventWrapper::readFromParcel(const Parcel* in) {
44   status_t res = OK;
45   if (in == NULL) {
46     ALOGE("statsd received parcel argument was NULL.");
47     return BAD_VALUE;
48   }
49   if ((res = in->readInt32(&mTagId)) != OK) {
50     ALOGE("statsd could not read tagId from parcel");
51     return res;
52   }
53   if ((res = in->readInt64(&mElapsedRealTimeNs)) != OK) {
54     ALOGE("statsd could not read elapsed real time from parcel");
55     return res;
56   }
57   if ((res = in->readInt64(&mWallClockTimeNs)) != OK) {
58     ALOGE("statsd could not read wall clock time from parcel");
59     return res;
60   }
61   int numWorkChain = 0;
62   if ((res = in->readInt32(&numWorkChain)) != OK) {
63     ALOGE("statsd could not read number of work chains from parcel");
64     return res;
65   }
66   if (numWorkChain > 0) {
67     for (int i = 0; i < numWorkChain; i++) {
68       int numNodes = 0;
69       if ((res = in->readInt32(&numNodes)) != OK) {
70         ALOGE(
71             "statsd could not read number of nodes in work chain from parcel");
72         return res;
73       }
74       if (numNodes == 0) {
75         ALOGE("empty work chain");
76         return BAD_VALUE;
77       }
78       WorkChain wc;
79       for (int j = 0; j < numNodes; j++) {
80         wc.uids.push_back(in->readInt32());
81         wc.tags.push_back(std::string(String8(in->readString16()).string()));
82       }
83       mWorkChains.push_back(wc);
84     }
85   }
86   int dataSize = 0;
87   if ((res = in->readInt32(&dataSize)) != OK) {
88     ALOGE("statsd could not read data size from parcel");
89     return res;
90   }
91   if (mTagId <= 0 || mElapsedRealTimeNs <= 0 || mWallClockTimeNs <= 0 ||
92       dataSize <= 0) {
93     ALOGE("statsd received invalid parcel");
94     return BAD_VALUE;
95   }
96 
97   for (int i = 0; i < dataSize; i++) {
98     int type = in->readInt32();
99     switch (type) {
100       case StatsLogValue::INT:
101         mElements.push_back(StatsLogValue(in->readInt32()));
102         break;
103       case StatsLogValue::LONG:
104         mElements.push_back(StatsLogValue(in->readInt64()));
105         break;
106       case StatsLogValue::STRING:
107         mElements.push_back(
108             StatsLogValue(std::string(String8(in->readString16()).string())));
109         break;
110       case StatsLogValue::FLOAT:
111         mElements.push_back(StatsLogValue(in->readFloat()));
112         break;
113       case StatsLogValue::STORAGE:
114         mElements.push_back(StatsLogValue());
115         mElements.back().setType(StatsLogValue::STORAGE);
116         in->readByteVector(&(mElements.back().storage_value));
117         break;
118       default:
119         ALOGE("unrecognized data type: %d", type);
120         return BAD_TYPE;
121     }
122   }
123   return NO_ERROR;
124 };
125 
126 } // Namespace os
127 } // Namespace android
128