Move SharedPreferenceLogger to instrumentation package.

Bug: 30914916
Test: SettingsUnitTests and RunSettingsRoboTests

- Added interface to abstract logger
- Added test for SharePrefLogger
- Moved Existing tests for instrumentation to robotests.

Change-Id: I2b431ea4b0fd09d0f11389d8b9181448f08a52c5
This commit is contained in:
Fan Zhang
2016-08-18 16:04:19 -07:00
parent cbb2f5f498
commit 5f79ae9677
9 changed files with 184 additions and 26 deletions

View File

@@ -71,6 +71,7 @@ import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.VrListenerSettings; import com.android.settings.applications.VrListenerSettings;
import com.android.settings.applications.WriteSettingsDetails; import com.android.settings.applications.WriteSettingsDetails;
import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.core.instrumentation.SharedPreferencesLogger;
import com.android.settings.dashboard.DashboardContainerFragment; import com.android.settings.dashboard.DashboardContainerFragment;
import com.android.settings.dashboard.SearchResultsSummary; import com.android.settings.dashboard.SearchResultsSummary;
import com.android.settings.datausage.DataUsageSummary; import com.android.settings.datausage.DataUsageSummary;

View File

@@ -21,9 +21,9 @@ import android.content.Context;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
/** /**
* Pass-through Metrics logger for {@link MetricsLogger}. * {@link LogWriter} that writes data to eventlog.
*/ */
public class EventLogWriter { public class EventLogWriter implements LogWriter {
public void visible(Context context, int category) { public void visible(Context context, int category) {
MetricsLogger.visible(context, category); MetricsLogger.visible(context, category);

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2016 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 com.android.settings.core.instrumentation;
import android.content.Context;
/**
* Generic log writer interface.
*/
public interface LogWriter {
/**
* Logs a visibility event when view becomes visible.
*/
void visible(Context context, int category);
/**
* Logs a visibility event when view becomes hidden.
*/
void hidden(Context context, int category);
/**
* Logs an user action.
*/
void action(Context context, int category);
/**
* Logs an user action.
*/
void action(Context context, int category, int value);
/**
* Logs an user action.
*/
void action(Context context, int category, boolean value);
/**
* Logs an user action.
*/
void action(Context context, int category, String pkg);
/**
* Logs a count.
*/
void count(Context context, String name, int value);
/**
* Logs a histogram event.
*/
void histogram(Context context, String name, int bucket);
}

View File

@@ -16,11 +16,13 @@
package com.android.settings.core.instrumentation; package com.android.settings.core.instrumentation;
import android.support.annotation.VisibleForTesting;
public class MetricsFactory { public class MetricsFactory {
private static MetricsFactory sInstance; private static MetricsFactory sInstance;
private EventLogWriter mLogger; private LogWriter mLogger;
public static MetricsFactory get() { public static MetricsFactory get() {
if (sInstance == null) { if (sInstance == null) {
@@ -29,10 +31,15 @@ public class MetricsFactory {
return sInstance; return sInstance;
} }
public EventLogWriter getLogger() { public LogWriter getLogger() {
if (mLogger == null) { if (mLogger == null) {
mLogger = new EventLogWriter(); mLogger = new EventLogWriter();
} }
return mLogger; return mLogger;
} }
@VisibleForTesting
void setLogger(LogWriter logger) {
mLogger = logger;
}
} }

View File

@@ -12,9 +12,7 @@
* permissions and limitations under the License. * permissions and limitations under the License.
*/ */
package com.android.settings; package com.android.settings.core.instrumentation;
import com.android.internal.logging.MetricsLogger;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.ComponentName; import android.content.ComponentName;
@@ -23,7 +21,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.Map; import java.util.Map;
@@ -33,10 +31,12 @@ public class SharedPreferencesLogger implements SharedPreferences {
private final String mTag; private final String mTag;
private final Context mContext; private final Context mContext;
private final LogWriter mLogWriter;
public SharedPreferencesLogger(Context context, String tag) { public SharedPreferencesLogger(Context context, String tag) {
mContext = context; mContext = context;
mTag = tag; mTag = tag;
mLogWriter = MetricsFactory.get().getLogger();
} }
@Override @Override
@@ -95,12 +95,12 @@ public class SharedPreferencesLogger implements SharedPreferences {
} }
private void logValue(String key, String value) { private void logValue(String key, String value) {
MetricsLogger.count(mContext, mTag + "/" + key + "|" + value, 1); mLogWriter.count(mContext, mTag + "/" + key + "|" + value, 1);
} }
private void logPackageName(String key, String value) { private void logPackageName(String key, String value) {
MetricsLogger.count(mContext, mTag + "/" + key, 1); mLogWriter.count(mContext, mTag + "/" + key, 1);
MetricsLogger.action(mContext, MetricsEvent.ACTION_GENERIC_PACKAGE, mLogWriter.action(mContext, MetricsEvent.ACTION_GENERIC_PACKAGE,
mTag + "/" + key + "|" + value); mTag + "/" + key + "|" + value);
} }

View File

@@ -24,22 +24,22 @@ import android.content.Context;
public class VisibilityLoggerMixin { public class VisibilityLoggerMixin {
private final Instrumentable mInstrumentable; private final Instrumentable mInstrumentable;
private final EventLogWriter mEventLogWriter; private final LogWriter mLogWriter;
public VisibilityLoggerMixin(Instrumentable instrumentable) { public VisibilityLoggerMixin(Instrumentable instrumentable) {
this(instrumentable, MetricsFactory.get().getLogger()); this(instrumentable, MetricsFactory.get().getLogger());
} }
public VisibilityLoggerMixin(Instrumentable instrumentable, EventLogWriter eventLogWriter) { public VisibilityLoggerMixin(Instrumentable instrumentable, LogWriter logWriter) {
mInstrumentable = instrumentable; mInstrumentable = instrumentable;
mEventLogWriter = eventLogWriter; mLogWriter = logWriter;
} }
public void onResume(Context context) { public void onResume(Context context) {
mEventLogWriter.visible(context, mInstrumentable.getMetricsCategory()); mLogWriter.visible(context, mInstrumentable.getMetricsCategory());
} }
public void onPause(Context context) { public void onPause(Context context) {
mEventLogWriter.hidden(context, mInstrumentable.getMetricsCategory()); mLogWriter.hidden(context, mInstrumentable.getMetricsCategory());
} }
} }

View File

@@ -15,16 +15,17 @@
*/ */
package com.android.settings.core.instrumentation; package com.android.settings.core.instrumentation;
import android.support.test.filters.SmallTest; import com.android.settings.TestConfig;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class) @RunWith(RobolectricTestRunner.class)
@SmallTest @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class MetricsFactoryTest { public class MetricsFactoryTest {
@Test @Test
@@ -37,8 +38,8 @@ public class MetricsFactoryTest {
@Test @Test
public void factoryShouldCacheLogger() { public void factoryShouldCacheLogger() {
MetricsFactory factory = MetricsFactory.get(); MetricsFactory factory = MetricsFactory.get();
EventLogWriter logger1 = factory.getLogger(); LogWriter logger1 = factory.getLogger();
EventLogWriter logger2 = factory.getLogger(); LogWriter logger2 = factory.getLogger();
assertTrue(logger1 == logger2); assertTrue(logger1 == logger2);
} }
} }

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2016 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 com.android.settings.core.instrumentation;
import android.content.Context;
import com.android.settings.TestConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SharedPreferenceLoggerTest {
private static final String TEST_TAG = "tag";
private static final String TEST_KEY = "key";
@Mock
private LogWriter mLogWriter;
private ShadowApplication mApplication;
private SharedPreferencesLogger mSharedPrefLogger;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
mApplication = ShadowApplication.getInstance();
MetricsFactory.get().setLogger(mLogWriter);
mSharedPrefLogger = new SharedPreferencesLogger(
mApplication.getApplicationContext(), TEST_TAG);
}
@Test
public void putInt_shouldLogCount() {
mSharedPrefLogger.edit().putInt(TEST_KEY, 1);
verify(mLogWriter).count(any(Context.class), anyString(), anyInt());
}
@Test
public void putBoolean_shouldLogCount() {
mSharedPrefLogger.edit().putBoolean(TEST_KEY, true);
verify(mLogWriter).count(any(Context.class), anyString(), anyInt());
}
@Test
public void putLong_shouldLogCount() {
mSharedPrefLogger.edit().putLong(TEST_KEY, 1);
verify(mLogWriter).count(any(Context.class), anyString(), anyInt());
}
@Test
public void putFloat_shouldLogCount() {
mSharedPrefLogger.edit().putInt(TEST_KEY, 1);
verify(mLogWriter).count(any(Context.class), anyString(), anyInt());
}
}

View File

@@ -16,22 +16,25 @@
package com.android.settings.core.instrumentation; package com.android.settings.core.instrumentation;
import android.content.Context; import android.content.Context;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4; import com.android.settings.TestConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@RunWith(AndroidJUnit4.class)
@SmallTest @RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class VisibilityLoggerMixinTest { public class VisibilityLoggerMixinTest {
@Mock @Mock