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