Loading apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl +5 −5 Original line number Diff line number Diff line Loading @@ -4,12 +4,12 @@ package android.os; * @hide */ parcelable StatsDimensionsValueParcel { /** * Field equals: * - atomTag for top level StatsDimensionsValueParcel * - position in dimension for all other levels */ // Field equals atomTag for top level StatsDimensionsValueParcels or // positions in depth (1-indexed) for lower level parcels. int field; // Indicator for which type of value is stored. Should be set to one // of the constants in StatsDimensionsValue.java. int valueType; String stringValue; Loading apex/statsd/framework/java/android/os/StatsDimensionsValue.java +83 −161 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ public final class StatsDimensionsValue implements Parcelable { private static final String TAG = "StatsDimensionsValue"; // Values of the value type correspond to stats_log.proto's DimensionValue fields. // Keep constants in sync with services/include/android/os/StatsDimensionsValue.h. // Keep constants in sync with frameworks/base/cmds/statsd/src/HashableDimensionKey.cpp. /** Indicates that this holds a String. */ public static final int STRING_VALUE_TYPE = 2; /** Indicates that this holds an int. */ Loading @@ -72,17 +72,7 @@ public final class StatsDimensionsValue implements Parcelable { /** Indicates that this holds a List of StatsDimensionsValues. */ public static final int TUPLE_VALUE_TYPE = 7; /** Value of a stats_log.proto DimensionsValue.field. */ private final int mField; /** Type of stats_log.proto DimensionsValue.value, according to the VALUE_TYPEs above. */ private final int mValueType; /** * Value of a stats_log.proto DimensionsValue.value. * String, Integer, Long, Boolean, Float, or StatsDimensionsValue[]. */ private final Object mValue; // immutable or array of immutables private final StatsDimensionsValueParcel mInner; /** * Creates a {@code StatsDimensionValue} from a parcel. Loading @@ -90,51 +80,17 @@ public final class StatsDimensionsValue implements Parcelable { * @hide */ public StatsDimensionsValue(Parcel in) { mField = in.readInt(); mValueType = in.readInt(); mValue = readValueFromParcel(mValueType, in); mInner = StatsDimensionsValueParcel.CREATOR.createFromParcel(in); } /** * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel * TODO(b/149103391): Make StatsDimensionsValue a wrapper on top of * StatsDimensionsValueParcel. * * @hide */ public StatsDimensionsValue(StatsDimensionsValueParcel parcel) { mField = parcel.field; mValueType = parcel.valueType; switch (mValueType) { case STRING_VALUE_TYPE: mValue = parcel.stringValue; break; case INT_VALUE_TYPE: mValue = parcel.intValue; break; case LONG_VALUE_TYPE: mValue = parcel.longValue; break; case BOOLEAN_VALUE_TYPE: mValue = parcel.boolValue; break; case FLOAT_VALUE_TYPE: mValue = parcel.floatValue; break; case TUPLE_VALUE_TYPE: StatsDimensionsValue[] values = new StatsDimensionsValue[parcel.tupleValue.length]; for (int i = 0; i < parcel.tupleValue.length; i++) { values[i] = new StatsDimensionsValue(parcel.tupleValue[i]); } mValue = values; break; default: Log.w(TAG, "StatsDimensionsValueParcel contains bad valueType: " + mValueType); mValue = null; break; mInner = parcel; } } /** * Return the field, i.e. the tag of a statsd atom. Loading @@ -142,7 +98,7 @@ public final class StatsDimensionsValue implements Parcelable { * @return the field */ public int getField() { return mField; return mInner.field; } /** Loading @@ -152,13 +108,13 @@ public final class StatsDimensionsValue implements Parcelable { * null otherwise */ public String getStringValue() { try { if (mValueType == STRING_VALUE_TYPE) return (String) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == STRING_VALUE_TYPE) { return mInner.stringValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not string."); return null; } } /** * Retrieve the int held, if any. Loading @@ -166,13 +122,13 @@ public final class StatsDimensionsValue implements Parcelable { * @return the int held if {@link #getValueType()} == {@link #INT_VALUE_TYPE}, 0 otherwise */ public int getIntValue() { try { if (mValueType == INT_VALUE_TYPE) return (Integer) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == INT_VALUE_TYPE) { return mInner.intValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not int."); return 0; } } /** * Retrieve the long held, if any. Loading @@ -180,13 +136,13 @@ public final class StatsDimensionsValue implements Parcelable { * @return the long held if {@link #getValueType()} == {@link #LONG_VALUE_TYPE}, 0 otherwise */ public long getLongValue() { try { if (mValueType == LONG_VALUE_TYPE) return (Long) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == LONG_VALUE_TYPE) { return mInner.longValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not long."); return 0; } } /** * Retrieve the boolean held, if any. Loading @@ -195,13 +151,13 @@ public final class StatsDimensionsValue implements Parcelable { * false otherwise */ public boolean getBooleanValue() { try { if (mValueType == BOOLEAN_VALUE_TYPE) return (Boolean) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == BOOLEAN_VALUE_TYPE) { return mInner.boolValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not boolean."); return false; } } /** * Retrieve the float held, if any. Loading @@ -209,13 +165,13 @@ public final class StatsDimensionsValue implements Parcelable { * @return the float held if {@link #getValueType()} == {@link #FLOAT_VALUE_TYPE}, 0 otherwise */ public float getFloatValue() { try { if (mValueType == FLOAT_VALUE_TYPE) return (Float) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == FLOAT_VALUE_TYPE) { return mInner.floatValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not float."); return 0; } } /** * Retrieve the tuple, in the form of a {@link List} of {@link StatsDimensionsValue}, held, Loading @@ -226,19 +182,15 @@ public final class StatsDimensionsValue implements Parcelable { * null otherwise */ public List<StatsDimensionsValue> getTupleValueList() { if (mValueType != TUPLE_VALUE_TYPE) { return null; } try { StatsDimensionsValue[] orig = (StatsDimensionsValue[]) mValue; List<StatsDimensionsValue> copy = new ArrayList<>(orig.length); // Shallow copy since StatsDimensionsValue is immutable anyway for (int i = 0; i < orig.length; i++) { copy.add(orig[i]); if (mInner.valueType == TUPLE_VALUE_TYPE) { int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; List<StatsDimensionsValue> tupleValues = new ArrayList<>(length); for (int i = 0; i < length; i++) { tupleValues.add(new StatsDimensionsValue(mInner.tupleValue[i])); } return copy; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); return tupleValues; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not tuple."); return null; } } Loading @@ -257,7 +209,7 @@ public final class StatsDimensionsValue implements Parcelable { * @return the constant representing the type of value stored */ public int getValueType() { return mValueType; return mInner.valueType; } /** Loading @@ -267,7 +219,7 @@ public final class StatsDimensionsValue implements Parcelable { * @return true if {@link #getValueType()} is equal to {@code valueType}. */ public boolean isValueType(int valueType) { return mValueType == valueType; return mInner.valueType == valueType; } /** Loading @@ -280,26 +232,40 @@ public final class StatsDimensionsValue implements Parcelable { */ // Follows the format of statsd's dimension.h toString. public String toString() { try { StringBuilder sb = new StringBuilder(); sb.append(mField); sb.append(mInner.field); sb.append(":"); if (mValueType == TUPLE_VALUE_TYPE) { switch (mInner.valueType) { case STRING_VALUE_TYPE: sb.append(mInner.stringValue); break; case INT_VALUE_TYPE: sb.append(String.valueOf(mInner.intValue)); break; case LONG_VALUE_TYPE: sb.append(String.valueOf(mInner.longValue)); break; case BOOLEAN_VALUE_TYPE: sb.append(String.valueOf(mInner.boolValue)); break; case FLOAT_VALUE_TYPE: sb.append(String.valueOf(mInner.floatValue)); break; case TUPLE_VALUE_TYPE: sb.append("{"); StatsDimensionsValue[] sbvs = (StatsDimensionsValue[]) mValue; for (int i = 0; i < sbvs.length; i++) { sb.append(sbvs[i].toString()); int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; for (int i = 0; i < length; i++) { StatsDimensionsValue child = new StatsDimensionsValue(mInner.tupleValue[i]); sb.append(child.toString()); sb.append("|"); } sb.append("}"); } else { sb.append(mValue.toString()); break; default: Log.w(TAG, "Incorrect value type"); break; } return sb.toString(); } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } return ""; } /** Loading @@ -324,72 +290,28 @@ public final class StatsDimensionsValue implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mField); out.writeInt(mValueType); writeValueToParcel(mValueType, mValue, out, flags); mInner.writeToParcel(out, flags); } /** Writes mValue to a parcel. Returns true if succeeds. */ private static boolean writeValueToParcel(int valueType, Object value, Parcel out, int flags) { try { switch (valueType) { case STRING_VALUE_TYPE: out.writeString((String) value); return true; case INT_VALUE_TYPE: out.writeInt((Integer) value); return true; case LONG_VALUE_TYPE: out.writeLong((Long) value); return true; case BOOLEAN_VALUE_TYPE: out.writeBoolean((Boolean) value); return true; case FLOAT_VALUE_TYPE: out.writeFloat((Float) value); return true; case TUPLE_VALUE_TYPE: { StatsDimensionsValue[] values = (StatsDimensionsValue[]) value; out.writeInt(values.length); for (int i = 0; i < values.length; i++) { values[i].writeToParcel(out, flags); } return true; } default: Log.w(TAG, "readValue of an impossible type " + valueType); return false; } } catch (ClassCastException e) { Log.w(TAG, "writeValue cast failed", e); return false; } } /** Reads mValue from a parcel. */ private static Object readValueFromParcel(int valueType, Parcel parcel) { switch (valueType) { /** * Returns a string representation of the type of value stored. */ private String getValueTypeAsString() { switch (mInner.valueType) { case STRING_VALUE_TYPE: return parcel.readString(); return "string"; case INT_VALUE_TYPE: return parcel.readInt(); return "int"; case LONG_VALUE_TYPE: return parcel.readLong(); return "long"; case BOOLEAN_VALUE_TYPE: return parcel.readBoolean(); return "boolean"; case FLOAT_VALUE_TYPE: return parcel.readFloat(); case TUPLE_VALUE_TYPE: { final int sz = parcel.readInt(); StatsDimensionsValue[] values = new StatsDimensionsValue[sz]; for (int i = 0; i < sz; i++) { values[i] = new StatsDimensionsValue(parcel); } return values; } return "float"; case TUPLE_VALUE_TYPE: return "tuple"; default: Log.w(TAG, "readValue of an impossible type " + valueType); return null; return "unknown"; } } } apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.os; import static com.google.common.truth.Truth.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.List; @RunWith(JUnit4.class) public final class StatsDimensionsValueTest { @Test public void testConversionFromStructuredParcel() { int tupleField = 100; // atom id String stringValue = "Hello"; int intValue = 123; long longValue = 123456789L; float floatValue = 1.1f; boolean boolValue = true; // Construct structured parcel StatsDimensionsValueParcel sdvp = new StatsDimensionsValueParcel(); sdvp.field = tupleField; sdvp.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; sdvp.tupleValue = new StatsDimensionsValueParcel[5]; for (int i = 0; i < 5; i++) { sdvp.tupleValue[i] = new StatsDimensionsValueParcel(); sdvp.tupleValue[i].field = i + 1; } sdvp.tupleValue[0].valueType = StatsDimensionsValue.STRING_VALUE_TYPE; sdvp.tupleValue[1].valueType = StatsDimensionsValue.INT_VALUE_TYPE; sdvp.tupleValue[2].valueType = StatsDimensionsValue.LONG_VALUE_TYPE; sdvp.tupleValue[3].valueType = StatsDimensionsValue.FLOAT_VALUE_TYPE; sdvp.tupleValue[4].valueType = StatsDimensionsValue.BOOLEAN_VALUE_TYPE; sdvp.tupleValue[0].stringValue = stringValue; sdvp.tupleValue[1].intValue = intValue; sdvp.tupleValue[2].longValue = longValue; sdvp.tupleValue[3].floatValue = floatValue; sdvp.tupleValue[4].boolValue = boolValue; // Convert to StatsDimensionsValue and check result StatsDimensionsValue sdv = new StatsDimensionsValue(sdvp); assertThat(sdv.getField()).isEqualTo(tupleField); assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); assertThat(sdvChildren.size()).isEqualTo(5); for (int i = 0; i < 5; i++) { assertThat(sdvChildren.get(i).getField()).isEqualTo(i + 1); } assertThat(sdvChildren.get(0).getValueType()) .isEqualTo(StatsDimensionsValue.STRING_VALUE_TYPE); assertThat(sdvChildren.get(1).getValueType()) .isEqualTo(StatsDimensionsValue.INT_VALUE_TYPE); assertThat(sdvChildren.get(2).getValueType()) .isEqualTo(StatsDimensionsValue.LONG_VALUE_TYPE); assertThat(sdvChildren.get(3).getValueType()) .isEqualTo(StatsDimensionsValue.FLOAT_VALUE_TYPE); assertThat(sdvChildren.get(4).getValueType()) .isEqualTo(StatsDimensionsValue.BOOLEAN_VALUE_TYPE); assertThat(sdvChildren.get(0).getStringValue()).isEqualTo(stringValue); assertThat(sdvChildren.get(1).getIntValue()).isEqualTo(intValue); assertThat(sdvChildren.get(2).getLongValue()).isEqualTo(longValue); assertThat(sdvChildren.get(3).getFloatValue()).isEqualTo(floatValue); assertThat(sdvChildren.get(4).getBooleanValue()).isEqualTo(boolValue); // Ensure that StatsDimensionsValue and StatsDimensionsValueParcel are // parceled equivalently Parcel sdvpParcel = Parcel.obtain(); Parcel sdvParcel = Parcel.obtain(); sdvp.writeToParcel(sdvpParcel, 0); sdv.writeToParcel(sdvParcel, 0); assertThat(sdvpParcel.dataSize()).isEqualTo(sdvParcel.dataSize()); } @Test public void testNullTupleArray() { int tupleField = 100; // atom id StatsDimensionsValueParcel parcel = new StatsDimensionsValueParcel(); parcel.field = tupleField; parcel.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; parcel.tupleValue = null; StatsDimensionsValue sdv = new StatsDimensionsValue(parcel); assertThat(sdv.getField()).isEqualTo(tupleField); assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); assertThat(sdvChildren.size()).isEqualTo(0); } } Loading
apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl +5 −5 Original line number Diff line number Diff line Loading @@ -4,12 +4,12 @@ package android.os; * @hide */ parcelable StatsDimensionsValueParcel { /** * Field equals: * - atomTag for top level StatsDimensionsValueParcel * - position in dimension for all other levels */ // Field equals atomTag for top level StatsDimensionsValueParcels or // positions in depth (1-indexed) for lower level parcels. int field; // Indicator for which type of value is stored. Should be set to one // of the constants in StatsDimensionsValue.java. int valueType; String stringValue; Loading
apex/statsd/framework/java/android/os/StatsDimensionsValue.java +83 −161 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ public final class StatsDimensionsValue implements Parcelable { private static final String TAG = "StatsDimensionsValue"; // Values of the value type correspond to stats_log.proto's DimensionValue fields. // Keep constants in sync with services/include/android/os/StatsDimensionsValue.h. // Keep constants in sync with frameworks/base/cmds/statsd/src/HashableDimensionKey.cpp. /** Indicates that this holds a String. */ public static final int STRING_VALUE_TYPE = 2; /** Indicates that this holds an int. */ Loading @@ -72,17 +72,7 @@ public final class StatsDimensionsValue implements Parcelable { /** Indicates that this holds a List of StatsDimensionsValues. */ public static final int TUPLE_VALUE_TYPE = 7; /** Value of a stats_log.proto DimensionsValue.field. */ private final int mField; /** Type of stats_log.proto DimensionsValue.value, according to the VALUE_TYPEs above. */ private final int mValueType; /** * Value of a stats_log.proto DimensionsValue.value. * String, Integer, Long, Boolean, Float, or StatsDimensionsValue[]. */ private final Object mValue; // immutable or array of immutables private final StatsDimensionsValueParcel mInner; /** * Creates a {@code StatsDimensionValue} from a parcel. Loading @@ -90,51 +80,17 @@ public final class StatsDimensionsValue implements Parcelable { * @hide */ public StatsDimensionsValue(Parcel in) { mField = in.readInt(); mValueType = in.readInt(); mValue = readValueFromParcel(mValueType, in); mInner = StatsDimensionsValueParcel.CREATOR.createFromParcel(in); } /** * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel * TODO(b/149103391): Make StatsDimensionsValue a wrapper on top of * StatsDimensionsValueParcel. * * @hide */ public StatsDimensionsValue(StatsDimensionsValueParcel parcel) { mField = parcel.field; mValueType = parcel.valueType; switch (mValueType) { case STRING_VALUE_TYPE: mValue = parcel.stringValue; break; case INT_VALUE_TYPE: mValue = parcel.intValue; break; case LONG_VALUE_TYPE: mValue = parcel.longValue; break; case BOOLEAN_VALUE_TYPE: mValue = parcel.boolValue; break; case FLOAT_VALUE_TYPE: mValue = parcel.floatValue; break; case TUPLE_VALUE_TYPE: StatsDimensionsValue[] values = new StatsDimensionsValue[parcel.tupleValue.length]; for (int i = 0; i < parcel.tupleValue.length; i++) { values[i] = new StatsDimensionsValue(parcel.tupleValue[i]); } mValue = values; break; default: Log.w(TAG, "StatsDimensionsValueParcel contains bad valueType: " + mValueType); mValue = null; break; mInner = parcel; } } /** * Return the field, i.e. the tag of a statsd atom. Loading @@ -142,7 +98,7 @@ public final class StatsDimensionsValue implements Parcelable { * @return the field */ public int getField() { return mField; return mInner.field; } /** Loading @@ -152,13 +108,13 @@ public final class StatsDimensionsValue implements Parcelable { * null otherwise */ public String getStringValue() { try { if (mValueType == STRING_VALUE_TYPE) return (String) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == STRING_VALUE_TYPE) { return mInner.stringValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not string."); return null; } } /** * Retrieve the int held, if any. Loading @@ -166,13 +122,13 @@ public final class StatsDimensionsValue implements Parcelable { * @return the int held if {@link #getValueType()} == {@link #INT_VALUE_TYPE}, 0 otherwise */ public int getIntValue() { try { if (mValueType == INT_VALUE_TYPE) return (Integer) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == INT_VALUE_TYPE) { return mInner.intValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not int."); return 0; } } /** * Retrieve the long held, if any. Loading @@ -180,13 +136,13 @@ public final class StatsDimensionsValue implements Parcelable { * @return the long held if {@link #getValueType()} == {@link #LONG_VALUE_TYPE}, 0 otherwise */ public long getLongValue() { try { if (mValueType == LONG_VALUE_TYPE) return (Long) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == LONG_VALUE_TYPE) { return mInner.longValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not long."); return 0; } } /** * Retrieve the boolean held, if any. Loading @@ -195,13 +151,13 @@ public final class StatsDimensionsValue implements Parcelable { * false otherwise */ public boolean getBooleanValue() { try { if (mValueType == BOOLEAN_VALUE_TYPE) return (Boolean) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == BOOLEAN_VALUE_TYPE) { return mInner.boolValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not boolean."); return false; } } /** * Retrieve the float held, if any. Loading @@ -209,13 +165,13 @@ public final class StatsDimensionsValue implements Parcelable { * @return the float held if {@link #getValueType()} == {@link #FLOAT_VALUE_TYPE}, 0 otherwise */ public float getFloatValue() { try { if (mValueType == FLOAT_VALUE_TYPE) return (Float) mValue; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } if (mInner.valueType == FLOAT_VALUE_TYPE) { return mInner.floatValue; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not float."); return 0; } } /** * Retrieve the tuple, in the form of a {@link List} of {@link StatsDimensionsValue}, held, Loading @@ -226,19 +182,15 @@ public final class StatsDimensionsValue implements Parcelable { * null otherwise */ public List<StatsDimensionsValue> getTupleValueList() { if (mValueType != TUPLE_VALUE_TYPE) { return null; } try { StatsDimensionsValue[] orig = (StatsDimensionsValue[]) mValue; List<StatsDimensionsValue> copy = new ArrayList<>(orig.length); // Shallow copy since StatsDimensionsValue is immutable anyway for (int i = 0; i < orig.length; i++) { copy.add(orig[i]); if (mInner.valueType == TUPLE_VALUE_TYPE) { int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; List<StatsDimensionsValue> tupleValues = new ArrayList<>(length); for (int i = 0; i < length; i++) { tupleValues.add(new StatsDimensionsValue(mInner.tupleValue[i])); } return copy; } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); return tupleValues; } else { Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not tuple."); return null; } } Loading @@ -257,7 +209,7 @@ public final class StatsDimensionsValue implements Parcelable { * @return the constant representing the type of value stored */ public int getValueType() { return mValueType; return mInner.valueType; } /** Loading @@ -267,7 +219,7 @@ public final class StatsDimensionsValue implements Parcelable { * @return true if {@link #getValueType()} is equal to {@code valueType}. */ public boolean isValueType(int valueType) { return mValueType == valueType; return mInner.valueType == valueType; } /** Loading @@ -280,26 +232,40 @@ public final class StatsDimensionsValue implements Parcelable { */ // Follows the format of statsd's dimension.h toString. public String toString() { try { StringBuilder sb = new StringBuilder(); sb.append(mField); sb.append(mInner.field); sb.append(":"); if (mValueType == TUPLE_VALUE_TYPE) { switch (mInner.valueType) { case STRING_VALUE_TYPE: sb.append(mInner.stringValue); break; case INT_VALUE_TYPE: sb.append(String.valueOf(mInner.intValue)); break; case LONG_VALUE_TYPE: sb.append(String.valueOf(mInner.longValue)); break; case BOOLEAN_VALUE_TYPE: sb.append(String.valueOf(mInner.boolValue)); break; case FLOAT_VALUE_TYPE: sb.append(String.valueOf(mInner.floatValue)); break; case TUPLE_VALUE_TYPE: sb.append("{"); StatsDimensionsValue[] sbvs = (StatsDimensionsValue[]) mValue; for (int i = 0; i < sbvs.length; i++) { sb.append(sbvs[i].toString()); int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length; for (int i = 0; i < length; i++) { StatsDimensionsValue child = new StatsDimensionsValue(mInner.tupleValue[i]); sb.append(child.toString()); sb.append("|"); } sb.append("}"); } else { sb.append(mValue.toString()); break; default: Log.w(TAG, "Incorrect value type"); break; } return sb.toString(); } catch (ClassCastException e) { Log.w(TAG, "Failed to successfully get value", e); } return ""; } /** Loading @@ -324,72 +290,28 @@ public final class StatsDimensionsValue implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mField); out.writeInt(mValueType); writeValueToParcel(mValueType, mValue, out, flags); mInner.writeToParcel(out, flags); } /** Writes mValue to a parcel. Returns true if succeeds. */ private static boolean writeValueToParcel(int valueType, Object value, Parcel out, int flags) { try { switch (valueType) { case STRING_VALUE_TYPE: out.writeString((String) value); return true; case INT_VALUE_TYPE: out.writeInt((Integer) value); return true; case LONG_VALUE_TYPE: out.writeLong((Long) value); return true; case BOOLEAN_VALUE_TYPE: out.writeBoolean((Boolean) value); return true; case FLOAT_VALUE_TYPE: out.writeFloat((Float) value); return true; case TUPLE_VALUE_TYPE: { StatsDimensionsValue[] values = (StatsDimensionsValue[]) value; out.writeInt(values.length); for (int i = 0; i < values.length; i++) { values[i].writeToParcel(out, flags); } return true; } default: Log.w(TAG, "readValue of an impossible type " + valueType); return false; } } catch (ClassCastException e) { Log.w(TAG, "writeValue cast failed", e); return false; } } /** Reads mValue from a parcel. */ private static Object readValueFromParcel(int valueType, Parcel parcel) { switch (valueType) { /** * Returns a string representation of the type of value stored. */ private String getValueTypeAsString() { switch (mInner.valueType) { case STRING_VALUE_TYPE: return parcel.readString(); return "string"; case INT_VALUE_TYPE: return parcel.readInt(); return "int"; case LONG_VALUE_TYPE: return parcel.readLong(); return "long"; case BOOLEAN_VALUE_TYPE: return parcel.readBoolean(); return "boolean"; case FLOAT_VALUE_TYPE: return parcel.readFloat(); case TUPLE_VALUE_TYPE: { final int sz = parcel.readInt(); StatsDimensionsValue[] values = new StatsDimensionsValue[sz]; for (int i = 0; i < sz; i++) { values[i] = new StatsDimensionsValue(parcel); } return values; } return "float"; case TUPLE_VALUE_TYPE: return "tuple"; default: Log.w(TAG, "readValue of an impossible type " + valueType); return null; return "unknown"; } } }
apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.os; import static com.google.common.truth.Truth.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.List; @RunWith(JUnit4.class) public final class StatsDimensionsValueTest { @Test public void testConversionFromStructuredParcel() { int tupleField = 100; // atom id String stringValue = "Hello"; int intValue = 123; long longValue = 123456789L; float floatValue = 1.1f; boolean boolValue = true; // Construct structured parcel StatsDimensionsValueParcel sdvp = new StatsDimensionsValueParcel(); sdvp.field = tupleField; sdvp.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; sdvp.tupleValue = new StatsDimensionsValueParcel[5]; for (int i = 0; i < 5; i++) { sdvp.tupleValue[i] = new StatsDimensionsValueParcel(); sdvp.tupleValue[i].field = i + 1; } sdvp.tupleValue[0].valueType = StatsDimensionsValue.STRING_VALUE_TYPE; sdvp.tupleValue[1].valueType = StatsDimensionsValue.INT_VALUE_TYPE; sdvp.tupleValue[2].valueType = StatsDimensionsValue.LONG_VALUE_TYPE; sdvp.tupleValue[3].valueType = StatsDimensionsValue.FLOAT_VALUE_TYPE; sdvp.tupleValue[4].valueType = StatsDimensionsValue.BOOLEAN_VALUE_TYPE; sdvp.tupleValue[0].stringValue = stringValue; sdvp.tupleValue[1].intValue = intValue; sdvp.tupleValue[2].longValue = longValue; sdvp.tupleValue[3].floatValue = floatValue; sdvp.tupleValue[4].boolValue = boolValue; // Convert to StatsDimensionsValue and check result StatsDimensionsValue sdv = new StatsDimensionsValue(sdvp); assertThat(sdv.getField()).isEqualTo(tupleField); assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); assertThat(sdvChildren.size()).isEqualTo(5); for (int i = 0; i < 5; i++) { assertThat(sdvChildren.get(i).getField()).isEqualTo(i + 1); } assertThat(sdvChildren.get(0).getValueType()) .isEqualTo(StatsDimensionsValue.STRING_VALUE_TYPE); assertThat(sdvChildren.get(1).getValueType()) .isEqualTo(StatsDimensionsValue.INT_VALUE_TYPE); assertThat(sdvChildren.get(2).getValueType()) .isEqualTo(StatsDimensionsValue.LONG_VALUE_TYPE); assertThat(sdvChildren.get(3).getValueType()) .isEqualTo(StatsDimensionsValue.FLOAT_VALUE_TYPE); assertThat(sdvChildren.get(4).getValueType()) .isEqualTo(StatsDimensionsValue.BOOLEAN_VALUE_TYPE); assertThat(sdvChildren.get(0).getStringValue()).isEqualTo(stringValue); assertThat(sdvChildren.get(1).getIntValue()).isEqualTo(intValue); assertThat(sdvChildren.get(2).getLongValue()).isEqualTo(longValue); assertThat(sdvChildren.get(3).getFloatValue()).isEqualTo(floatValue); assertThat(sdvChildren.get(4).getBooleanValue()).isEqualTo(boolValue); // Ensure that StatsDimensionsValue and StatsDimensionsValueParcel are // parceled equivalently Parcel sdvpParcel = Parcel.obtain(); Parcel sdvParcel = Parcel.obtain(); sdvp.writeToParcel(sdvpParcel, 0); sdv.writeToParcel(sdvParcel, 0); assertThat(sdvpParcel.dataSize()).isEqualTo(sdvParcel.dataSize()); } @Test public void testNullTupleArray() { int tupleField = 100; // atom id StatsDimensionsValueParcel parcel = new StatsDimensionsValueParcel(); parcel.field = tupleField; parcel.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE; parcel.tupleValue = null; StatsDimensionsValue sdv = new StatsDimensionsValue(parcel); assertThat(sdv.getField()).isEqualTo(tupleField); assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE); List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList(); assertThat(sdvChildren.size()).isEqualTo(0); } }