/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.car.storagemonitoring; import android.annotation.IntRange; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.util.JsonReader; import android.util.JsonWriter; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.Objects; /** * Wear-out information for flash storage. * * Contains a lower-bound estimate of the wear of "type A" (SLC) and "type B" (MLC) storage. * * Current technology offers wear data in increments of 10% (i.e. from 0 == new device up to * 100 == worn-out device). It is possible for a storage device to only support one type of memory * cell, in which case it is expected that the storage type not supported will have UNKNOWN wear. * * @hide */ @SystemApi public final class WearEstimate implements Parcelable { public static final int UNKNOWN = -1; /** @hide */ public static final WearEstimate UNKNOWN_ESTIMATE = new WearEstimate(UNKNOWN, UNKNOWN); public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public WearEstimate createFromParcel(Parcel in) { return new WearEstimate(in); } public WearEstimate[] newArray(int size) { return new WearEstimate[size]; } }; /** * Wear estimate data for "type A" storage. */ @IntRange(from = -1, to = 100) public final int typeA; /** * Wear estimate data for "type B" storage. */ @IntRange(from = -1, to = 100) public final int typeB; private static int validateWearValue(int value) { if (value == UNKNOWN) return value; if ((value >= 0) && (value <= 100)) return value; throw new IllegalArgumentException(value + " is not a valid wear estimate"); } public WearEstimate(int typeA, int typeB) { this.typeA = validateWearValue(typeA); this.typeB = validateWearValue(typeB); } public WearEstimate(Parcel in) { typeA = validateWearValue(in.readInt()); typeB = validateWearValue(in.readInt()); } /** * @hide */ public WearEstimate(JsonReader in) throws IOException { int typeA = UNKNOWN; int typeB = UNKNOWN; in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "wearEstimateTypeA": typeA = validateWearValue(in.nextInt()); break; case "wearEstimateTypeB": typeB = validateWearValue(in.nextInt()); break; } } in.endObject(); this.typeA = typeA; this.typeB = typeB; } /** @hide */ public WearEstimate(JSONObject in) throws JSONException { typeA = in.getInt("wearEstimateTypeA"); typeB = in.getInt("wearEstimateTypeB"); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(typeA); dest.writeInt(typeB); } /** * @hide */ public void writeToJson(JsonWriter jsonWriter) throws IOException { jsonWriter.beginObject(); jsonWriter.name("wearEstimateTypeA").value(typeA); jsonWriter.name("wearEstimateTypeB").value(typeB); jsonWriter.endObject(); } @Override public boolean equals(Object other) { if (other instanceof WearEstimate) { WearEstimate wo = (WearEstimate) other; return wo.typeA == typeA && wo.typeB == typeB; } return false; } @Override public int hashCode() { return Objects.hash(typeA, typeB); } private static String wearValueToString(int value) { if (value == UNKNOWN) return "unknown"; return value + "%"; } @Override public String toString() { return "type A: " + wearValueToString(typeA) + ", type B: " + wearValueToString(typeB); } }