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 android.annotation.IntRange; 21 import android.annotation.SystemApi; 22 import android.car.annotation.AddedInOrBefore; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.util.JsonReader; 26 import android.util.JsonWriter; 27 28 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 29 30 import org.json.JSONException; 31 import org.json.JSONObject; 32 33 import java.io.IOException; 34 import java.util.Objects; 35 36 /** 37 * Wear-out information for flash storage. 38 * 39 * Contains a lower-bound estimate of the wear of "type A" (SLC) and "type B" (MLC) storage. 40 * 41 * Current technology offers wear data in increments of 10% (i.e. from 0 == new device up to 42 * 100 == worn-out device). It is possible for a storage device to only support one type of memory 43 * cell, in which case it is expected that the storage type not supported will have UNKNOWN wear. 44 * 45 * @hide 46 */ 47 @SystemApi 48 public final class WearEstimate implements Parcelable { 49 @AddedInOrBefore(majorVersion = 33) 50 public static final int UNKNOWN = -1; 51 52 /** @hide */ 53 @AddedInOrBefore(majorVersion = 33) 54 public static final WearEstimate UNKNOWN_ESTIMATE = new WearEstimate(UNKNOWN, UNKNOWN); 55 56 @AddedInOrBefore(majorVersion = 33) 57 public static final Parcelable.Creator<WearEstimate> CREATOR = 58 new Parcelable.Creator<WearEstimate>() { 59 public WearEstimate createFromParcel(Parcel in) { 60 return new WearEstimate(in); 61 } 62 public WearEstimate[] newArray(int size) { 63 return new WearEstimate[size]; 64 } 65 }; 66 67 /** 68 * Wear estimate data for "type A" storage. 69 */ 70 @IntRange(from = -1, to = 100) 71 @AddedInOrBefore(majorVersion = 33) 72 public final int typeA; 73 74 /** 75 * Wear estimate data for "type B" storage. 76 */ 77 @IntRange(from = -1, to = 100) 78 @AddedInOrBefore(majorVersion = 33) 79 public final int typeB; 80 validateWearValue(int value)81 private static int validateWearValue(int value) { 82 if (value == UNKNOWN) return value; 83 if ((value >= 0) && (value <= 100)) return value; 84 throw new IllegalArgumentException(value + " is not a valid wear estimate"); 85 } 86 WearEstimate(int typeA, int typeB)87 public WearEstimate(int typeA, int typeB) { 88 this.typeA = validateWearValue(typeA); 89 this.typeB = validateWearValue(typeB); 90 } 91 WearEstimate(Parcel in)92 public WearEstimate(Parcel in) { 93 typeA = validateWearValue(in.readInt()); 94 typeB = validateWearValue(in.readInt()); 95 } 96 97 /** 98 * @hide 99 */ WearEstimate(JsonReader in)100 public WearEstimate(JsonReader in) throws IOException { 101 int typeA = UNKNOWN; 102 int typeB = UNKNOWN; 103 in.beginObject(); 104 while (in.hasNext()) { 105 switch (in.nextName()) { 106 case "wearEstimateTypeA": 107 typeA = validateWearValue(in.nextInt()); 108 break; 109 case "wearEstimateTypeB": 110 typeB = validateWearValue(in.nextInt()); 111 break; 112 } 113 } 114 in.endObject(); 115 this.typeA = typeA; 116 this.typeB = typeB; 117 } 118 119 /** @hide */ WearEstimate(JSONObject in)120 public WearEstimate(JSONObject in) throws JSONException { 121 typeA = in.getInt("wearEstimateTypeA"); 122 typeB = in.getInt("wearEstimateTypeB"); 123 } 124 125 @Override 126 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 127 @AddedInOrBefore(majorVersion = 33) describeContents()128 public int describeContents() { 129 return 0; 130 } 131 132 @Override 133 @AddedInOrBefore(majorVersion = 33) writeToParcel(Parcel dest, int flags)134 public void writeToParcel(Parcel dest, int flags) { 135 dest.writeInt(typeA); 136 dest.writeInt(typeB); 137 } 138 139 /** 140 * @hide 141 */ 142 @AddedInOrBefore(majorVersion = 33) writeToJson(JsonWriter jsonWriter)143 public void writeToJson(JsonWriter jsonWriter) throws IOException { 144 jsonWriter.beginObject(); 145 jsonWriter.name("wearEstimateTypeA").value(typeA); 146 jsonWriter.name("wearEstimateTypeB").value(typeB); 147 jsonWriter.endObject(); 148 } 149 150 @Override 151 @AddedInOrBefore(majorVersion = 33) equals(Object other)152 public boolean equals(Object other) { 153 if (other instanceof WearEstimate) { 154 WearEstimate wo = (WearEstimate) other; 155 return wo.typeA == typeA && wo.typeB == typeB; 156 } 157 return false; 158 } 159 160 @Override 161 @AddedInOrBefore(majorVersion = 33) hashCode()162 public int hashCode() { 163 return Objects.hash(typeA, typeB); 164 } 165 wearValueToString(int value)166 private static String wearValueToString(int value) { 167 if (value == UNKNOWN) return "unknown"; 168 return value + "%"; 169 } 170 171 @Override 172 @AddedInOrBefore(majorVersion = 33) toString()173 public String toString() { 174 return "type A: " + wearValueToString(typeA) + ", type B: " + wearValueToString(typeB); 175 } 176 } 177