/* * Copyright (C) 2018 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.app.admin; import android.annotation.Nullable; import android.content.ComponentName; import android.stats.devicepolicy.nano.StringList; import com.android.framework.protobuf.nano.MessageNano; import com.android.internal.util.FrameworkStatsLog; import java.util.Arrays; import java.util.Objects; /** * A wrapper for logging managed device events using {@link StatsLog}. *

* This class allows chaining - each of its methods returns a reference to the current instance. *

* Example usage: *

 * import android.stats.devicepolicy.DevicePolicyEnums;
 *
 * DevicePolicyEventLogger
 *     .createEvent(DevicePolicyEnums.USER_RESTRICTION_CHANGED)
 *     .setAdmin(who)
 *     .setString(key)
 *     .setBoolean(enabledFromThisOwner)
 *     .write();
 * 
* * @see StatsLog * @hide */ public class DevicePolicyEventLogger { private final int mEventId; private int mIntValue; private boolean mBooleanValue; private long mTimePeriodMs; private String[] mStringArrayValue; private String mAdminPackageName; private DevicePolicyEventLogger(int eventId) { mEventId = eventId; } /** * Creates a new {@link DevicePolicyEventLogger} instance for the specified * eventId. * * @param eventId one of {@link android.stats.devicepolicy.DevicePolicyEnums} as defined in * core/proto/android/stats/devicepolicy/device_policy_enums.proto */ public static DevicePolicyEventLogger createEvent(int eventId) { return new DevicePolicyEventLogger(eventId); } /** * Returns the event id. */ public int getEventId() { return mEventId; } /** * Sets a generic int value. */ public DevicePolicyEventLogger setInt(int value) { mIntValue = value; return this; } /** * Returns the generic int value. */ public int getInt() { return mIntValue; } /** * Sets a generic boolean value. */ public DevicePolicyEventLogger setBoolean(boolean value) { mBooleanValue = value; return this; } /** * Returns the generic boolean value. */ public boolean getBoolean() { return mBooleanValue; } /** * Sets a time period in milliseconds. */ public DevicePolicyEventLogger setTimePeriod(long timePeriodMillis) { mTimePeriodMs = timePeriodMillis; return this; } /** * Returns the time period in milliseconds. */ public long getTimePeriod() { return mTimePeriodMs; } /** * Sets generic String values. */ public DevicePolicyEventLogger setStrings(String... values) { mStringArrayValue = values; return this; } /** * Sets generic String values. *

* {@link #write()} logs the concatenation of value and values, * in that order. */ public DevicePolicyEventLogger setStrings(String value, String[] values) { Objects.requireNonNull(values, "values parameter cannot be null"); mStringArrayValue = new String[values.length + 1]; mStringArrayValue[0] = value; System.arraycopy(values, 0, mStringArrayValue, 1, values.length); return this; } /** * Sets generic String values. *

* {@link #write()} logs the concatenation of value1, value2 * and values, in that order. */ public DevicePolicyEventLogger setStrings(String value1, String value2, String[] values) { Objects.requireNonNull(values, "values parameter cannot be null"); mStringArrayValue = new String[values.length + 2]; mStringArrayValue[0] = value1; mStringArrayValue[1] = value2; System.arraycopy(values, 0, mStringArrayValue, 2, values.length); return this; } /** * Returns a copy of the generic String[] value. */ public String[] getStringArray() { if (mStringArrayValue == null) { return null; } return Arrays.copyOf(mStringArrayValue, mStringArrayValue.length); } /** * Sets the package name of the admin application. */ public DevicePolicyEventLogger setAdmin(@Nullable String packageName) { mAdminPackageName = packageName; return this; } /** * Sets the package name of the admin application from the {@link ComponentName}. */ public DevicePolicyEventLogger setAdmin(@Nullable ComponentName componentName) { mAdminPackageName = (componentName != null ? componentName.getPackageName() : null); return this; } /** * Returns the package name of the admin application. */ public String getAdminPackageName() { return mAdminPackageName; } /** * Writes the metric to {@link StatsLog}. */ public void write() { byte[] bytes = stringArrayValueToBytes(mStringArrayValue); FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_POLICY_EVENT, mEventId, mAdminPackageName, mIntValue, mBooleanValue, mTimePeriodMs, bytes); } /** * Converts the String[] array to byte[]. *

* We can't log String[] using {@link StatsLog}. The convention is to assign * the array to a proto object and convert it to byte[]. */ private static byte[] stringArrayValueToBytes(String[] array) { if (array == null) { return null; } StringList stringList = new StringList(); stringList.stringValue = array; return MessageNano.toByteArray(stringList); } }