Bug 965371 - Part 1: introduce v3 environment format. r=mcomella

This commit is contained in:
Richard Newman 2014-05-09 19:19:13 -07:00
parent 99c8b4cf33
commit 9cf7154a60
12 changed files with 362 additions and 35 deletions

View File

@ -513,9 +513,11 @@ sync_java_files = [
'background/fxa/PasswordStretcher.java',
'background/fxa/QuickPasswordStretcher.java',
'background/fxa/SkewHandler.java',
'background/healthreport/AndroidConfigurationProvider.java',
'background/healthreport/Environment.java',
'background/healthreport/EnvironmentBuilder.java',
'background/healthreport/EnvironmentV1.java',
'background/healthreport/EnvironmentV2.java',
'background/healthreport/HealthReportBroadcastReceiver.java',
'background/healthreport/HealthReportBroadcastService.java',
'background/healthreport/HealthReportDatabases.java',

View File

@ -0,0 +1,77 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.background.healthreport;
import org.mozilla.gecko.background.healthreport.Environment.UIType;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder.ConfigurationProvider;
import org.mozilla.gecko.sync.jpake.stage.GetRequestStage.GetStepTimerTask;
import org.mozilla.gecko.util.HardwareUtils;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics;
public class AndroidConfigurationProvider implements ConfigurationProvider {
private static final float MILLIMETERS_PER_INCH = 25.4f;
private final Configuration configuration;
private final DisplayMetrics displayMetrics;
public AndroidConfigurationProvider(final Context context) {
final Resources resources = context.getResources();
this.configuration = resources.getConfiguration();
this.displayMetrics = resources.getDisplayMetrics();
HardwareUtils.init(context);
}
@Override
public boolean hasHardwareKeyboard() {
return configuration.keyboard != Configuration.KEYBOARD_NOKEYS;
}
@Override
public UIType getUIType() {
if (HardwareUtils.isLargeTablet()) {
return UIType.LARGE_TABLET;
}
if (HardwareUtils.isSmallTablet()) {
return UIType.SMALL_TABLET;
}
return UIType.DEFAULT;
}
@Override
public int getUIModeType() {
return configuration.uiMode & Configuration.UI_MODE_TYPE_MASK;
}
@Override
public int getScreenLayoutSize() {
return configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
}
/**
* Calculate screen horizontal width, in millimeters.
* This is approximate, will be wrong on some devices, and
* most likely doesn't include screen area that the app doesn't own.
* http://stackoverflow.com/questions/2193457/is-there-a-way-to-determine-android-physical-screen-height-in-cm-or-inches
*/
@Override
public int getScreenXInMM() {
return Math.round((displayMetrics.widthPixels / displayMetrics.xdpi) * MILLIMETERS_PER_INCH);
}
/**
* @see #getScreenXInMM() for caveats.
*/
@Override
public int getScreenYInMM() {
return Math.round((displayMetrics.heightPixels / displayMetrics.ydpi) * MILLIMETERS_PER_INCH);
}
}

View File

@ -18,14 +18,61 @@ package org.mozilla.gecko.background.healthreport;
* registered an <code>Environment</code>, don't do so again; start from scratch.
*
*/
public abstract class Environment extends EnvironmentV1 {
public abstract class Environment extends EnvironmentV2 {
// Version 2 adds osLocale, appLocale, acceptLangSet, and distribution.
public static final int CURRENT_VERSION = 2;
// Version 3 adds device characteristics.
public static final int CURRENT_VERSION = 3;
public String osLocale; // The Android OS "Locale" value.
public String appLocale;
public int acceptLangSet;
public String distribution; // ID + version. Typically empty.
public static enum UIType {
// Corresponds to the typical phone interface.
DEFAULT("default"),
// Corresponds to a device for which Fennec is displaying the large tablet UI.
LARGE_TABLET("largetablet"),
// Corresponds to a device for which Fennec is displaying the small tablet UI.
SMALL_TABLET("smalltablet");
private final String label;
private UIType(final String label) {
this.label = label;
}
public String toString() {
return this.label;
}
public static UIType fromLabel(final String label) {
for (UIType type : UIType.values()) {
if (type.label.equals(label)) {
return type;
}
}
throw new IllegalArgumentException("Bad enum value: " + label);
}
}
public UIType uiType = UIType.DEFAULT;
/**
* Mask of Configuration#uiMode. E.g., UI_MODE_TYPE_CAR.
*/
public int uiMode = 0; // UI_MODE_TYPE_UNDEFINED = 0
/**
* Computed physical dimensions in millimeters.
*/
public int screenXInMM;
public int screenYInMM;
/**
* One of the Configuration#SCREENLAYOUT_SIZE_* constants.
*/
public int screenLayout = 0; // SCREENLAYOUT_SIZE_UNDEFINED = 0
public boolean hasHardwareKeyboard;
public Environment() {
this(Environment.HashAppender.class);
@ -40,10 +87,12 @@ public abstract class Environment extends EnvironmentV1 {
protected void appendHash(EnvironmentAppender appender) {
super.appendHash(appender);
// v2.
appender.append(osLocale);
appender.append(appLocale);
appender.append(acceptLangSet);
appender.append(distribution);
// v3.
appender.append(hasHardwareKeyboard ? 1 : 0);
appender.append(uiType.toString());
appender.append(uiMode);
appender.append(screenLayout);
appender.append(screenXInMM);
appender.append(screenYInMM);
}
}

View File

@ -11,6 +11,7 @@ import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.SysInfo;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.Environment.UIType;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
@ -68,8 +69,20 @@ public class EnvironmentBuilder {
public JSONObject getAddonsJSON();
}
public static interface ConfigurationProvider {
public boolean hasHardwareKeyboard();
public UIType getUIType();
public int getUIModeType();
public int getScreenLayoutSize();
public int getScreenXInMM();
public int getScreenYInMM();
}
protected static void populateEnvironment(Environment e,
ProfileInformationProvider info) {
ProfileInformationProvider info,
ConfigurationProvider config) {
e.cpuCount = SysInfo.getCPUCount();
e.memoryMB = SysInfo.getMemSize();
@ -135,6 +148,14 @@ public class EnvironmentBuilder {
e.osLocale = info.getOSLocale();
e.appLocale = info.getAppLocale();
e.acceptLangSet = info.isAcceptLangUserSet() ? 1 : 0;
// v3 environment fields.
e.hasHardwareKeyboard = config.hasHardwareKeyboard();
e.uiType = config.getUIType();
e.uiMode = config.getUIModeType();
e.screenLayout = config.getScreenLayoutSize();
e.screenXInMM = config.getScreenXInMM();
e.screenYInMM = config.getScreenYInMM();
}
/**
@ -144,14 +165,14 @@ public class EnvironmentBuilder {
* @param info a source of profile data
* @return the new {@link Environment}
*/
public static Environment getCurrentEnvironment(ProfileInformationProvider info) {
public static Environment getCurrentEnvironment(ProfileInformationProvider info, ConfigurationProvider config) {
Environment e = new Environment() {
@Override
public int register() {
return 0;
}
};
populateEnvironment(e, info);
populateEnvironment(e, info, config);
return e;
}
@ -159,9 +180,10 @@ public class EnvironmentBuilder {
* @return the current environment's ID in the provided storage layer
*/
public static int registerCurrentEnvironment(final HealthReportStorage storage,
final ProfileInformationProvider info) {
final ProfileInformationProvider info,
final ConfigurationProvider config) {
Environment e = storage.getEnvironment();
populateEnvironment(e, info);
populateEnvironment(e, info, config);
e.register();
Logger.debug(LOG_TAG, "Registering current environment: " + e.getHash() + " = " + e.id);
return e.id;

View File

@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.background.healthreport;
public abstract class EnvironmentV2 extends EnvironmentV1 {
private static final int VERSION = 2;
public String osLocale;
public String appLocale;
public int acceptLangSet;
public String distribution;
public EnvironmentV2(Class<? extends EnvironmentAppender> appenderClass) {
super(appenderClass);
version = VERSION;
}
@Override
protected void appendHash(EnvironmentAppender appender) {
super.appendHash(appender);
// v2.
appender.append(osLocale);
appender.append(appLocale);
appender.append(acceptLangSet);
appender.append(distribution);
}
}

View File

@ -141,7 +141,12 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
"distribution", "osLocale", "appLocale", "acceptLangSet",
// Joined to the add-ons table.
"addonsBody"
"addonsBody",
// v3.
"hasHardwareKeyboard",
"uiMode", "uiType",
"screenLayout", "screenXInMM", "screenYInMM"
};
public static final String[] COLUMNS_MEASUREMENT_DETAILS = new String[] {"id", "name", "version"};
@ -190,7 +195,7 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
protected final HealthReportSQLiteOpenHelper helper;
public static class HealthReportSQLiteOpenHelper extends SQLiteOpenHelper {
public static final int CURRENT_VERSION = 6;
public static final int CURRENT_VERSION = 7;
public static final String LOG_TAG = "HealthReportSQL";
/**
@ -287,6 +292,14 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
" acceptLangSet INTEGER, " +
" addonsID INTEGER, " +
" hasHardwareKeyboard INTEGER, " +
" uiMode INTEGER, " +
" uiType TEXT, " +
" screenLayout INTEGER, " +
" screenXInMM INTEGER, " +
" screenYInMM INTEGER, " +
" FOREIGN KEY (addonsID) REFERENCES addons(id) ON DELETE RESTRICT, " +
" UNIQUE (hash) " +
")");
@ -395,7 +408,15 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
" e.osLocale AS osLocale, " +
" e.appLocale AS appLocale, " +
" e.acceptLangSet AS acceptLangSet, " +
" addons.body AS addonsBody " +
" addons.body AS addonsBody, " +
" e.hasHardwareKeyboard AS hasHardwareKeyboard, " +
" e.uiMode AS uiMode, " +
" e.uiType AS uiType, " +
" e.screenLayout AS screenLayout, " +
" e.screenXInMM AS screenXInMM, " +
" e.screenYInMM AS screenYInMM " +
"FROM environments AS e, addons " +
"WHERE e.addonsID = addons.id");
}
@ -449,6 +470,21 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
createAddonsEnvironmentsView(db);
}
private void upgradeDatabaseFrom6to7(SQLiteDatabase db) {
db.execSQL("DROP VIEW environments_with_addons");
// Add fields to environment (default to empty string and 0).
db.execSQL("ALTER TABLE environments ADD COLUMN hasHardwareKeyboard INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE environments ADD COLUMN uiMode INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE environments ADD COLUMN uiType TEXT DEFAULT ''");
db.execSQL("ALTER TABLE environments ADD COLUMN screenLayout INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE environments ADD COLUMN screenXInMM INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE environments ADD COLUMN screenYInMM INTEGER DEFAULT 0");
// Recreate view.
createAddonsEnvironmentsView(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion >= newVersion) {
@ -466,6 +502,8 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
upgradeDatabaseFrom4to5(db);
case 5:
upgradeDatabaseFrom5to6(db);
case 6:
upgradeDatabaseFrom6to7(db);
}
} catch (Exception e) {
Logger.error(LOG_TAG, "Failure in onUpgrade.", e);
@ -599,6 +637,12 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
v.put("osLocale", osLocale);
v.put("appLocale", appLocale);
v.put("acceptLangSet", acceptLangSet);
v.put("hasHardwareKeyboard", hasHardwareKeyboard ? 1 : 0);
v.put("uiMode", uiMode);
v.put("uiType", uiType.toString());
v.put("screenLayout", screenLayout);
v.put("screenXInMM", screenXInMM);
v.put("screenYInMM", screenYInMM);
final SQLiteDatabase db = storage.helper.getWritableDatabase();
@ -685,6 +729,9 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
public void init(ContentValues v) {
version = v.containsKey("version") ? v.getAsInteger("version") : Environment.CURRENT_VERSION;
Logger.debug(LOG_TAG, "Initializing environment with version " + version);
profileCreation = v.getAsInteger("profileCreation");
cpuCount = v.getAsInteger("cpuCount");
memoryMB = v.getAsInteger("memoryMB");
@ -720,6 +767,15 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
// Nothing we can do.
}
if (version >= 3) {
hasHardwareKeyboard = v.getAsInteger("hasHardwareKeyboard") != 0;
uiMode = v.getAsInteger("uiMode");
uiType = UIType.fromLabel(v.getAsString("uiType"));
screenLayout = v.getAsInteger("screenLayout");
screenXInMM = v.getAsInteger("screenXInMM");
screenYInMM = v.getAsInteger("screenYInMM");
}
this.hash = null;
this.id = -1;
}
@ -771,6 +827,15 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
// Nothing we can do.
}
if (this.version >= 3) {
hasHardwareKeyboard = cursor.getInt(i++) != 0;
uiMode = cursor.getInt(i++);
uiType = UIType.fromLabel(cursor.getString(i++));
screenLayout = cursor.getInt(i++);
screenXInMM = cursor.getInt(i++);
screenYInMM = cursor.getInt(i++);
}
return cursor.moveToNext();
}

View File

@ -12,6 +12,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.background.common.DateUtils.DateFormatter;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder.ConfigurationProvider;
import org.mozilla.gecko.background.healthreport.HealthReportStorage.Field;
import android.database.Cursor;
@ -42,7 +43,7 @@ public class HealthReportGenerator {
* @return null if no environment could be computed, or else the resulting document.
* @throws JSONException if there was an error adding environment data to the resulting document.
*/
public JSONObject generateDocument(long since, long lastPingTime, String profilePath) throws JSONException {
public JSONObject generateDocument(long since, long lastPingTime, String profilePath, ConfigurationProvider config) throws JSONException {
Logger.info(LOG_TAG, "Generating FHR document from " + since + "; last ping " + lastPingTime);
Logger.pii(LOG_TAG, "Generating for profile " + profilePath);
@ -51,7 +52,8 @@ public class HealthReportGenerator {
Logger.warn(LOG_TAG, "Not enough profile information to compute current environment.");
return null;
}
Environment current = EnvironmentBuilder.getCurrentEnvironment(cache);
Environment current = EnvironmentBuilder.getCurrentEnvironment(cache, config);
return generateDocument(since, lastPingTime, current);
}
@ -275,6 +277,7 @@ public class HealthReportGenerator {
JSONObject gecko = getGeckoInfo(e, current);
JSONObject appinfo = getAppInfo(e, current);
JSONObject counts = getAddonCounts(e, current);
JSONObject config = getDeviceConfig(e, current);
JSONObject out = new JSONObject();
if (age != null)
@ -292,12 +295,65 @@ public class HealthReportGenerator {
if (active != null)
out.put("org.mozilla.addons.active", active);
if (config != null)
out.put("org.mozilla.device.config", config);
if (current == null) {
out.put("hash", e.getHash());
}
return out;
}
// v3 environment fields.
private static JSONObject getDeviceConfig(Environment e, Environment current) throws JSONException {
JSONObject config = new JSONObject();
int changes = 0;
if (e.version < 3) {
return null;
}
if (current != null && current.version < 3) {
return getDeviceConfig(e, null);
}
if (current == null || current.hasHardwareKeyboard != e.hasHardwareKeyboard) {
config.put("hasHardwareKeyboard", e.hasHardwareKeyboard);
changes++;
}
if (current == null || current.screenLayout != e.screenLayout) {
config.put("screenLayout", e.screenLayout);
changes++;
}
if (current == null || current.screenXInMM != e.screenXInMM) {
config.put("screenXInMM", e.screenXInMM);
changes++;
}
if (current == null || current.screenYInMM != e.screenYInMM) {
config.put("screenYInMM", e.screenYInMM);
changes++;
}
if (current == null || current.uiType != e.uiType) {
config.put("uiType", e.uiType.toString());
changes++;
}
if (current == null || current.uiMode != e.uiMode) {
config.put("uiMode", e.uiMode);
changes++;
}
if (current != null && changes == 0) {
return null;
}
config.put("_v", 1);
return config;
}
private static JSONObject getProfileAge(Environment e, Environment current) throws JSONException {
JSONObject age = new JSONObject();
int changes = 0;
@ -421,6 +477,7 @@ public class HealthReportGenerator {
switch (e.version) {
// There's a straightforward correspondence between environment versions
// and appinfo versions.
case 3:
case 2:
appinfo.put("_v", 3);
break;
@ -433,6 +490,7 @@ public class HealthReportGenerator {
}
switch (e.version) {
case 3:
case 2:
if (populateAppInfoV2(appinfo, e, current, outdated)) {
changed = true;

View File

@ -5,8 +5,10 @@
package org.mozilla.gecko.background.healthreport.prune;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.AndroidConfigurationProvider;
import org.mozilla.gecko.background.healthreport.Environment;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder.ConfigurationProvider;
import org.mozilla.gecko.background.healthreport.HealthReportDatabaseStorage;
import org.mozilla.gecko.background.healthreport.ProfileInformationCache;
@ -24,6 +26,7 @@ public class PrunePolicyDatabaseStorage implements PrunePolicyStorage {
private final Context context;
private final String profilePath;
private final ConfigurationProvider config;
private ContentProviderClient client;
private HealthReportDatabaseStorage storage;
@ -33,6 +36,7 @@ public class PrunePolicyDatabaseStorage implements PrunePolicyStorage {
public PrunePolicyDatabaseStorage(final Context context, final String profilePath) {
this.context = context;
this.profilePath = profilePath;
this.config = new AndroidConfigurationProvider(context);
this.currentEnvironmentID = -1;
}
@ -128,7 +132,7 @@ public class PrunePolicyDatabaseStorage implements PrunePolicyStorage {
if (!cache.restoreUnlessInitialized()) {
throw new IllegalStateException("Current environment unknown.");
}
final Environment env = EnvironmentBuilder.getCurrentEnvironment(cache);
final Environment env = EnvironmentBuilder.getCurrentEnvironment(cache, config);
currentEnvironmentID = env.register();
}
return currentEnvironmentID;

View File

@ -17,8 +17,10 @@ import org.mozilla.gecko.background.bagheera.BagheeraClient;
import org.mozilla.gecko.background.bagheera.BagheeraRequestDelegate;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.AndroidConfigurationProvider;
import org.mozilla.gecko.background.healthreport.Environment;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder.ConfigurationProvider;
import org.mozilla.gecko.background.healthreport.HealthReportConstants;
import org.mozilla.gecko.background.healthreport.HealthReportDatabaseStorage;
import org.mozilla.gecko.background.healthreport.HealthReportGenerator;
@ -42,11 +44,13 @@ public class AndroidSubmissionClient implements SubmissionClient {
protected final Context context;
protected final SharedPreferences sharedPreferences;
protected final String profilePath;
protected final ConfigurationProvider config;
public AndroidSubmissionClient(Context context, SharedPreferences sharedPreferences, String profilePath) {
this.context = context;
this.sharedPreferences = sharedPreferences;
this.profilePath = profilePath;
this.config = new AndroidConfigurationProvider(context);
}
public SharedPreferences getSharedPreferences() {
@ -88,7 +92,7 @@ public class AndroidSubmissionClient implements SubmissionClient {
final SubmissionsTracker tracker) throws JSONException {
final long since = localTime - GlobalConstants.MILLISECONDS_PER_SIX_MONTHS;
final HealthReportGenerator generator = tracker.getGenerator();
return generator.generateDocument(since, last, profilePath);
return generator.generateDocument(since, last, profilePath, config);
}
protected void uploadPayload(String id, String payload, Collection<String> oldIds, BagheeraRequestDelegate uploadDelegate) {
@ -348,7 +352,7 @@ public class AndroidSubmissionClient implements SubmissionClient {
}
protected int registerCurrentEnvironment() {
return EnvironmentBuilder.registerCurrentEnvironment(storage, profileCache);
return EnvironmentBuilder.registerCurrentEnvironment(storage, profileCache, config);
}
protected void incrementFirstUploadAttemptCount() {
@ -399,7 +403,7 @@ public class AndroidSubmissionClient implements SubmissionClient {
@Override
public JSONObject generateDocument(long since, long lastPingTime,
String generationProfilePath) throws JSONException {
String generationProfilePath, ConfigurationProvider providedConfig) throws JSONException {
// Let's make sure we have an accurate locale.
BrowserLocaleManager.getInstance().getAndApplyPersistedLocale(context);
@ -410,7 +414,7 @@ public class AndroidSubmissionClient implements SubmissionClient {
final Environment environment = getCurrentEnvironment();
document = super.generateDocument(since, lastPingTime, environment);
} else {
document = super.generateDocument(since, lastPingTime, generationProfilePath);
document = super.generateDocument(since, lastPingTime, generationProfilePath, providedConfig);
}
if (document == null) {
@ -420,7 +424,7 @@ public class AndroidSubmissionClient implements SubmissionClient {
}
protected Environment getCurrentEnvironment() {
return EnvironmentBuilder.getCurrentEnvironment(profileCache);
return EnvironmentBuilder.getCurrentEnvironment(profileCache, config);
}
}

View File

@ -55,7 +55,8 @@ public class TestEnvironmentBuilder extends FakeProfileTestCase {
cache.completeInitialization();
assertTrue(cache.getFile().exists());
Environment environment = EnvironmentBuilder.getCurrentEnvironment(cache);
final AndroidConfigurationProvider configProvider = new AndroidConfigurationProvider(context);
Environment environment = EnvironmentBuilder.getCurrentEnvironment(cache, configProvider);
assertEquals(AppConstants.MOZ_APP_BUILDID, environment.appBuildID);
assertEquals("Android", environment.os);
assertTrue(100 < environment.memoryMB); // Seems like a sane lower bound...
@ -63,14 +64,20 @@ public class TestEnvironmentBuilder extends FakeProfileTestCase {
assertEquals(1, environment.isBlocklistEnabled);
assertEquals(0, environment.isTelemetryEnabled);
assertEquals(expectedDays, environment.profileCreation);
assertEquals(EnvironmentBuilder.getCurrentEnvironment(cache).getHash(),
assertEquals(EnvironmentBuilder.getCurrentEnvironment(cache, configProvider).getHash(),
environment.getHash());
// v3 sanity.
assertEquals(configProvider.hasHardwareKeyboard(), environment.hasHardwareKeyboard);
assertEquals(configProvider.getScreenXInMM(), environment.screenXInMM);
assertTrue(1 < environment.screenXInMM);
assertTrue(2000 > environment.screenXInMM);
cache.beginInitialization();
cache.setBlocklistEnabled(false);
cache.completeInitialization();
assertFalse(EnvironmentBuilder.getCurrentEnvironment(cache).getHash()
assertFalse(EnvironmentBuilder.getCurrentEnvironment(cache, configProvider).getHash()
.equals(environment.getHash()));
}
}

View File

@ -67,7 +67,10 @@ public class TestHealthReportGenerator extends FakeProfileTestCase {
+ "nullnullnullnullnullnull00000";
// v2 fields.
private static final String EXPECTED_MOCK_BASE_HASH_SUFFIX = "null" + "null" + 0 + "null";
private static final String EXPECTED_MOCK_BASE_HASH_SUFFIX_V2 = "null" + "null" + 0 + "null";
// v3 fields.
private static final String EXPECTED_MOCK_BASE_HASH_SUFFIX_V3 = "" + 0 + "default" + 0 + 0 + 0 + 0;
public void testHashing() throws JSONException {
MockHealthReportDatabaseStorage storage = new MockHealthReportDatabaseStorage(context, fakeProfileDirectory);
@ -105,10 +108,14 @@ public class TestHealthReportGenerator extends FakeProfileTestCase {
"}");
env.addons.put("{addonA}", addonA1);
assertEquals(EXPECTED_MOCK_BASE_HASH + addonAHash + EXPECTED_MOCK_BASE_HASH_SUFFIX, env.getHash());
assertEquals(EXPECTED_MOCK_BASE_HASH + addonAHash +
EXPECTED_MOCK_BASE_HASH_SUFFIX_V2 +
EXPECTED_MOCK_BASE_HASH_SUFFIX_V3, env.getHash());
env.addons.put("{addonA}", addonA1rev);
assertEquals(EXPECTED_MOCK_BASE_HASH + addonAHash + EXPECTED_MOCK_BASE_HASH_SUFFIX, env.getHash());
assertEquals(EXPECTED_MOCK_BASE_HASH + addonAHash +
EXPECTED_MOCK_BASE_HASH_SUFFIX_V2 +
EXPECTED_MOCK_BASE_HASH_SUFFIX_V3, env.getHash());
}
private void assertJSONDiff(JSONObject source, JSONObject diff) throws JSONException {

View File

@ -7,6 +7,7 @@ import java.util.Collection;
import org.mozilla.gecko.background.bagheera.BagheeraRequestDelegate;
import org.mozilla.gecko.background.healthreport.Environment;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder.ConfigurationProvider;
import org.mozilla.gecko.background.healthreport.HealthReportStorage;
import org.mozilla.gecko.background.healthreport.HealthReportDatabaseStorage;
import org.mozilla.gecko.background.healthreport.MockHealthReportDatabaseStorage.PrepopulatedMockHealthReportDatabaseStorage;
@ -20,6 +21,7 @@ import org.mozilla.gecko.background.testhelpers.StubDelegate;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.SharedPreferences;
import org.json.JSONException;
import org.json.JSONObject;
@ -95,7 +97,7 @@ public class TestAndroidSubmissionClient extends FakeProfileTestCase {
public class MockTrackingGenerator extends TrackingGenerator {
@Override
public JSONObject generateDocument(final long localTime, final long last,
final String profilePath) throws JSONException {
final String profilePath, ConfigurationProvider config) throws JSONException {
switch (documentStatus) {
case VALID:
return new JSONObject(); // Beyond == null, we don't check for valid FHR documents.
@ -103,7 +105,7 @@ public class TestAndroidSubmissionClient extends FakeProfileTestCase {
case NULL:
// The overridden method should return null since we return a null has for the current
// Environment.
return super.generateDocument(localTime, last, profilePath);
return super.generateDocument(localTime, last, profilePath, config);
case EXCEPTION:
throw new IllegalStateException("Intended Exception");