• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 package com.android.settings.fuelgauge.batteryusage.db;
18 
19 import android.content.ContentValues;
20 
21 import androidx.room.Entity;
22 import androidx.room.PrimaryKey;
23 
24 import com.android.settings.fuelgauge.BatteryUtils;
25 import com.android.settings.fuelgauge.batteryusage.BatteryInformation;
26 import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
27 
28 import com.google.errorprone.annotations.CanIgnoreReturnValue;
29 
30 import java.util.Locale;
31 
32 /** A {@link Entity} class to save battery states snapshot into database. */
33 @Entity
34 public class BatteryState {
35     @PrimaryKey(autoGenerate = true)
36     private long mId;
37 
38     // Records the app relative information.
39     public final long uid;
40     public final long userId;
41     public final String packageName;
42     public final long timestamp;
43     public final int consumerType;
44     public final boolean isFullChargeCycleStart;
45     public final String batteryInformation;
46     /**
47      * This field is filled only when build type is "userdebug".
48      * For now, Java Proto Lite is recommended by the Android team as the more lightweight solution
49      * designed specifically for mobile apps to process protobuf.
50      * However, converting protobuf to string through Java Proto Lite needs to parse it into a bytes
51      * field first, which leads to the strings saved in our database are encoded and hard to
52      * understand.
53      * To make it easier to debug in our daily development, this field is added.
54      * It will not be filled for the real users.
55      */
56     public final String batteryInformationDebug;
57 
BatteryState( long uid, long userId, String packageName, long timestamp, int consumerType, boolean isFullChargeCycleStart, String batteryInformation, String batteryInformationDebug)58     public BatteryState(
59             long uid,
60             long userId,
61             String packageName,
62             long timestamp,
63             int consumerType,
64             boolean isFullChargeCycleStart,
65             String batteryInformation,
66             String batteryInformationDebug) {
67         // Records the app relative information.
68         this.uid = uid;
69         this.userId = userId;
70         this.packageName = packageName;
71         this.timestamp = timestamp;
72         this.consumerType = consumerType;
73         this.isFullChargeCycleStart = isFullChargeCycleStart;
74         this.batteryInformation = batteryInformation;
75         this.batteryInformationDebug = batteryInformationDebug;
76     }
77 
78     /** Sets the auto-generated content ID. */
setId(long id)79     public void setId(long id) {
80         this.mId = id;
81     }
82 
83     /** Gets the auto-generated content ID. */
getId()84     public long getId() {
85         return mId;
86     }
87 
88     @Override
toString()89     public String toString() {
90         final String recordAtDateTime = ConvertUtils.utcToLocalTimeForLogging(timestamp);
91         final BatteryInformation batteryInformationInstance =
92                 BatteryUtils.parseProtoFromString(
93                         batteryInformation, BatteryInformation.getDefaultInstance());
94         final StringBuilder builder = new StringBuilder()
95                 .append("\nBatteryState{")
96                 .append(String.format(Locale.US,
97                         "\n\tpackage=%s|uid=%d|userId=%d", packageName, uid, userId))
98                 .append(String.format(Locale.US, "\n\ttimestamp=%s|consumer=%d|isStart=%b",
99                         recordAtDateTime, consumerType, isFullChargeCycleStart))
100                 .append(String.format(Locale.US, "\n\tbatteryInfo="))
101                 .append(batteryInformationInstance.toString());
102         return builder.toString();
103     }
104 
105 
106     /** Creates new {@link BatteryState} from {@link ContentValues}. */
create(ContentValues contentValues)107     public static BatteryState create(ContentValues contentValues) {
108         Builder builder = BatteryState.newBuilder();
109         if (contentValues.containsKey("uid")) {
110             builder.setUid(contentValues.getAsLong("uid"));
111         }
112         if (contentValues.containsKey("userId")) {
113             builder.setUserId(contentValues.getAsLong("userId"));
114         }
115         if (contentValues.containsKey("packageName")) {
116             builder.setPackageName(contentValues.getAsString("packageName"));
117         }
118         if (contentValues.containsKey("timestamp")) {
119             builder.setTimestamp(contentValues.getAsLong("timestamp"));
120         }
121         if (contentValues.containsKey("consumerType")) {
122             builder.setConsumerType(contentValues.getAsInteger("consumerType"));
123         }
124         if (contentValues.containsKey("isFullChargeCycleStart")) {
125             builder.setIsFullChargeCycleStart(
126                     contentValues.getAsBoolean("isFullChargeCycleStart"));
127         }
128         if (contentValues.containsKey("batteryInformation")) {
129             builder.setBatteryInformation(contentValues.getAsString("batteryInformation"));
130         }
131         if (contentValues.containsKey("batteryInformationDebug")) {
132             builder.setBatteryInformationDebug(
133                     contentValues.getAsString("batteryInformationDebug"));
134         }
135         return builder.build();
136     }
137 
138     /** Creates a new {@link Builder} instance. */
newBuilder()139     public static Builder newBuilder() {
140         return new Builder();
141     }
142 
143     /** A convenience builder class to improve readability. */
144     public static class Builder {
145         private long mUid;
146         private long mUserId;
147         private String mPackageName;
148         private long mTimestamp;
149         private int mConsumerType;
150         private boolean mIsFullChargeCycleStart;
151         private String mBatteryInformation;
152         private String mBatteryInformationDebug;
153 
154         /** Sets the uid. */
155         @CanIgnoreReturnValue
setUid(long uid)156         public Builder setUid(long uid) {
157             this.mUid = uid;
158             return this;
159         }
160 
161         /** Sets the user ID. */
162         @CanIgnoreReturnValue
setUserId(long userId)163         public Builder setUserId(long userId) {
164             this.mUserId = userId;
165             return this;
166         }
167 
168         /** Sets the package name. */
169         @CanIgnoreReturnValue
setPackageName(String packageName)170         public Builder setPackageName(String packageName) {
171             this.mPackageName = packageName;
172             return this;
173         }
174 
175         /** Sets the timestamp. */
176         @CanIgnoreReturnValue
setTimestamp(long timestamp)177         public Builder setTimestamp(long timestamp) {
178             this.mTimestamp = timestamp;
179             return this;
180         }
181 
182         /** Sets the consumer type. */
183         @CanIgnoreReturnValue
setConsumerType(int consumerType)184         public Builder setConsumerType(int consumerType) {
185             this.mConsumerType = consumerType;
186             return this;
187         }
188 
189         /** Sets whether is the full charge cycle start. */
190         @CanIgnoreReturnValue
setIsFullChargeCycleStart(boolean isFullChargeCycleStart)191         public Builder setIsFullChargeCycleStart(boolean isFullChargeCycleStart) {
192             this.mIsFullChargeCycleStart = isFullChargeCycleStart;
193             return this;
194         }
195 
196         /** Sets the battery information. */
197         @CanIgnoreReturnValue
setBatteryInformation(String batteryInformation)198         public Builder setBatteryInformation(String batteryInformation) {
199             this.mBatteryInformation = batteryInformation;
200             return this;
201         }
202 
203         /** Sets the battery information debug string. */
204         @CanIgnoreReturnValue
setBatteryInformationDebug(String batteryInformationDebug)205         public Builder setBatteryInformationDebug(String batteryInformationDebug) {
206             this.mBatteryInformationDebug = batteryInformationDebug;
207             return this;
208         }
209 
210         /** Builds the BatteryState. */
build()211         public BatteryState build() {
212             return new BatteryState(
213                     mUid,
214                     mUserId,
215                     mPackageName,
216                     mTimestamp,
217                     mConsumerType,
218                     mIsFullChargeCycleStart,
219                     mBatteryInformation,
220                     mBatteryInformationDebug);
221         }
222 
Builder()223         private Builder() {}
224     }
225 }
226