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 package android.car.storagemonitoring;
17 
18 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE;
19 
20 import static java.util.Objects.requireNonNull;
21 
22 import android.annotation.NonNull;
23 import android.annotation.SystemApi;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 
27 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
28 
29 import java.time.Instant;
30 import java.util.Objects;
31 
32 /**
33  * Change in wear-out information.
34  *
35  * Contains information about the first cycle during which the system detected a change
36  * in wear-out information of the flash storage.
37  *
38  * @hide
39  */
40 @SystemApi
41 public final class WearEstimateChange implements Parcelable {
42     public static final Parcelable.Creator<WearEstimateChange> CREATOR =
43             new Parcelable.Creator<WearEstimateChange>() {
44         public WearEstimateChange createFromParcel(Parcel in) {
45             return new WearEstimateChange(in);
46         }
47 
48         public WearEstimateChange[] newArray(int size) {
49                 return new WearEstimateChange[size];
50             }
51     };
52 
53     /**
54      * The previous wear estimate.
55      */
56     public final @NonNull WearEstimate oldEstimate;
57 
58     /**
59      * The new wear estimate.
60      */
61     public final @NonNull WearEstimate newEstimate;
62 
63     /**
64      * Total CarService uptime when this change was detected.
65      */
66     public final long uptimeAtChange;
67 
68     /**
69      * Wall-clock time when this change was detected.
70      */
71     public final @NonNull Instant dateAtChange;
72 
73     /**
74      * Whether this change was within the vendor range for acceptable flash degradation.
75      */
76     public final boolean isAcceptableDegradation;
77 
WearEstimateChange(WearEstimate oldEstimate, WearEstimate newEstimate, long uptimeAtChange, Instant dateAtChange, boolean isAcceptableDegradation)78     public WearEstimateChange(WearEstimate oldEstimate,
79                               WearEstimate newEstimate,
80                               long uptimeAtChange,
81                               Instant dateAtChange,
82                               boolean isAcceptableDegradation) {
83         if (uptimeAtChange < 0) {
84             throw new IllegalArgumentException("uptimeAtChange must be >= 0");
85         }
86         this.oldEstimate = requireNonNull(oldEstimate);
87         this.newEstimate = requireNonNull(newEstimate);
88         this.uptimeAtChange = uptimeAtChange;
89         this.dateAtChange = Instant.ofEpochSecond(requireNonNull(dateAtChange).getEpochSecond());
90         this.isAcceptableDegradation = isAcceptableDegradation;
91     }
92 
WearEstimateChange(Parcel in)93     public WearEstimateChange(Parcel in) {
94         oldEstimate = in.readParcelable(WearEstimate.class.getClassLoader());
95         newEstimate = in.readParcelable(WearEstimate.class.getClassLoader());
96         uptimeAtChange = in.readLong();
97         long secs = in.readLong();
98         int nanos = in.readInt();
99         dateAtChange = Instant.ofEpochSecond(secs, nanos);
100         isAcceptableDegradation = in.readInt() == 1;
101     }
102 
103     @Override
104     @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE)
describeContents()105     public int describeContents() {
106         return 0;
107     }
108 
109     @Override
writeToParcel(Parcel dest, int flags)110     public void writeToParcel(Parcel dest, int flags) {
111         dest.writeParcelable(oldEstimate, flags);
112         dest.writeParcelable(newEstimate, flags);
113         dest.writeLong(uptimeAtChange);
114         dest.writeLong(dateAtChange.getEpochSecond());
115         dest.writeInt(dateAtChange.getNano());
116         dest.writeInt(isAcceptableDegradation ? 1 : 0);
117     }
118 
119     @Override
equals(Object other)120     public boolean equals(Object other) {
121         if (other instanceof WearEstimateChange) {
122             WearEstimateChange wo = (WearEstimateChange) other;
123             return wo.isAcceptableDegradation == isAcceptableDegradation
124                     && wo.uptimeAtChange == uptimeAtChange
125                     && wo.dateAtChange.equals(dateAtChange)
126                     && wo.oldEstimate.equals(oldEstimate)
127                     && wo.newEstimate.equals(newEstimate);
128         }
129         return false;
130     }
131 
132     @Override
hashCode()133     public int hashCode() {
134         return Objects.hash(oldEstimate,
135                             newEstimate,
136                             uptimeAtChange,
137                             dateAtChange,
138                             isAcceptableDegradation);
139     }
140 
141     @Override
toString()142     public String toString() {
143         return String.format(
144                 "wear change{old level=%s, new level=%s, uptime=%d, date=%s, acceptable=%s}",
145                 oldEstimate,
146                 newEstimate,
147                 uptimeAtChange,
148                 dateAtChange,
149                 isAcceptableDegradation ? "yes" : "no");
150     }
151 
152 }
153