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