Use binary resource support in robolectric

The resources available to tests are now exactly the merged resources
located in the APK under test.

Bug: 74359828
Test: make -j56 RunSettingsRoboTests
Change-Id: I050db81a92decefea23314b5ec7a62f77ff4bb2b
This commit is contained in:
James Lemieux
2018-12-07 12:56:49 -08:00
committed by Fan Zhang
parent 1f5fab1480
commit f1dade40d2
1005 changed files with 3187 additions and 5478 deletions

View File

@@ -19,8 +19,6 @@ package com.android.settings.testutils;
import android.content.Intent;
import android.os.BatteryManager;
import java.lang.reflect.Field;
public class BatteryTestUtils {
public static Intent getChargingIntent() {
@@ -39,7 +37,7 @@ public class BatteryTestUtils {
BatteryManager.BATTERY_STATUS_DISCHARGING);
}
public static Intent getCustomBatteryIntent(int plugged, int level, int scale, int status) {
private static Intent getCustomBatteryIntent(int plugged, int level, int scale, int status) {
Intent intent = new Intent();
intent.putExtra(BatteryManager.EXTRA_PLUGGED, plugged);
intent.putExtra(BatteryManager.EXTRA_LEVEL, level);
@@ -48,16 +46,4 @@ public class BatteryTestUtils {
return intent;
}
public static void clearStaticInstance(Class clazz, String fieldName) {
Field instance;
try {
instance = clazz.getDeclaredField(fieldName);
instance.setAccessible(true);
instance.set(null, null);
} catch (Exception e) {
throw new RuntimeException();
}
}
}

View File

@@ -22,7 +22,7 @@ import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.slices.SlicesDatabaseHelper;
import java.lang.reflect.Field;
import org.robolectric.util.ReflectionHelpers;
public class DatabaseTestUtils {
@@ -36,41 +36,17 @@ public class DatabaseTestUtils {
SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(context);
helper.close();
Field instance;
Class clazz = SlicesDatabaseHelper.class;
try {
instance = clazz.getDeclaredField("sSingleton");
instance.setAccessible(true);
instance.set(null, null);
} catch (Exception e) {
throw new RuntimeException();
}
ReflectionHelpers.setStaticField(SlicesDatabaseHelper.class, "sSingleton", null);
}
private static void clearAnomalyDb(Context context) {
AnomalyDatabaseHelper helper = AnomalyDatabaseHelper.getInstance(context);
helper.close();
Field instance;
Class clazz = AnomalyDatabaseHelper.class;
try {
instance = clazz.getDeclaredField("sSingleton");
instance.setAccessible(true);
instance.set(null, null);
} catch (Exception e) {
throw new RuntimeException();
}
ReflectionHelpers.setStaticField(AnomalyDatabaseHelper.class, "sSingleton", null);
}
private static void clearAnomalyDbManager() {
Field instance;
Class clazz = BatteryDatabaseManager.class;
try {
instance = clazz.getDeclaredField("sSingleton");
instance.setAccessible(true);
instance.set(null, null);
} catch (Exception e) {
throw new RuntimeException();
}
ReflectionHelpers.setStaticField(BatteryDatabaseManager.class, "sSingleton", null);
}
}

View File

@@ -21,8 +21,7 @@ import android.content.Context;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.slices.CopyableSlice;
public class FakeCopyableController extends BasePreferenceController implements
CopyableSlice {
public class FakeCopyableController extends BasePreferenceController implements CopyableSlice {
public FakeCopyableController(Context context, String preferenceKey) {
super(context, preferenceKey);

View File

@@ -15,7 +15,7 @@
*/
package com.android.settings.testutils;
import static org.mockito.Matchers.anyString;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

View File

@@ -50,5 +50,4 @@ public class FakeIndexProvider implements Indexable {
return result;
}
};
}

View File

@@ -23,24 +23,24 @@ import com.android.settings.core.SliderPreferenceController;
public class FakeSliderController extends SliderPreferenceController {
private final String settingKey = "fake_slider_key";
public static final String AVAILABILITY_KEY = "fake_slider_availability_key";
public static final int MAX_STEPS = 9;
private static final String SETTING_KEY = "fake_slider_key";
public FakeSliderController(Context context, String key) {
super(context, key);
}
@Override
public int getSliderPosition() {
return Settings.System.getInt(mContext.getContentResolver(), settingKey, 0);
return Settings.System.getInt(mContext.getContentResolver(), SETTING_KEY, 0);
}
@Override
public boolean setSliderPosition(int position) {
return Settings.System.putInt(mContext.getContentResolver(), settingKey, position);
return Settings.System.putInt(mContext.getContentResolver(), SETTING_KEY, position);
}
@Override
@@ -50,8 +50,7 @@ public class FakeSliderController extends SliderPreferenceController {
@Override
public int getAvailabilityStatus() {
return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, AVAILABLE);
return Settings.Global.getInt(mContext.getContentResolver(), AVAILABILITY_KEY, AVAILABLE);
}
@Override

View File

@@ -26,15 +26,15 @@ import com.android.settings.core.TogglePreferenceController;
public class FakeToggleController extends TogglePreferenceController {
private String settingKey = "toggle_key";
public static final String AVAILABILITY_KEY = "fake_toggle_availability_key";
public static final IntentFilter INTENT_FILTER = new IntentFilter(
WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
private final int ON = 1;
private final int OFF = 0;
private static final String SETTING_KEY = "toggle_key";
private static final int ON = 1;
private static final int OFF = 0;
private boolean mIsAsyncUpdate = false;
@@ -45,12 +45,12 @@ public class FakeToggleController extends TogglePreferenceController {
@Override
public boolean isChecked() {
return Settings.System.getInt(mContext.getContentResolver(),
settingKey, OFF) == ON;
SETTING_KEY, OFF) == ON;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.System.putInt(mContext.getContentResolver(), settingKey,
return Settings.System.putInt(mContext.getContentResolver(), SETTING_KEY,
isChecked ? ON : OFF);
}

View File

@@ -15,8 +15,7 @@ public class FakeUnavailablePreferenceController extends BasePreferenceControlle
@Override
public int getAvailabilityStatus() {
return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, 0);
return Settings.Global.getInt(mContext.getContentResolver(), AVAILABILITY_KEY, 0);
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* 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.
@@ -13,100 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.testutils;
import org.junit.runners.model.InitializationError;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.res.Fs;
import org.robolectric.res.ResourcePath;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
/**
* Custom test runner for the testing of BluetoothPairingDialogs. This is needed because the
* default behavior for robolectric is just to grab the resource directory in the target package.
* We want to override this to add several spanning different projects.
*/
public class SettingsRobolectricTestRunner extends RobolectricTestRunner {
/**
* We don't actually want to change this behavior, so we just call super.
*/
public SettingsRobolectricTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
/**
* We are going to create our own custom manifest so that we can add multiple resource
* paths to it. This lets us access resources in both Settings and SettingsLib in our tests.
*/
@Override
protected AndroidManifest getAppManifest(Config config) {
try {
// Using the manifest file's relative path, we can figure out the application directory.
final URL appRoot = new URL("file:packages/apps/Settings/");
final URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
final URL resDir = new URL(appRoot, "tests/robotests/res");
final URL assetsDir = new URL(appRoot, "tests/robotests/assets");
// By adding any resources from libraries we need the AndroidManifest, we can access
// them from within the parallel universe's resource loader.
return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
Fs.fromURL(assetsDir), "com.android.settings") {
@Override
public List<ResourcePath> getIncludedResourcePaths() {
final List<ResourcePath> paths = super.getIncludedResourcePaths();
addIncludedResourcePaths(paths);
return paths;
}
};
} catch (MalformedURLException e) {
throw new RuntimeException("SettingsRobolectricTestRunner failure", e);
}
}
public static void addIncludedResourcePaths(List<ResourcePath> paths) {
try {
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:packages/apps/Settings/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/AppPreference/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/HelpUtils/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/RestrictedLockUtils/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SearchWidget/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/ActionButtonsPreference/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SettingsLayoutPreference/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:external/setupcompat/main/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:external/setupdesign/main/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/target/common/obj/JAVA_LIBRARIES/robolectric_android-all-stub_intermediates/classes/raw-res/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/extras/material-design-x/com.google.android.material_material-nodeps/android_common/aar/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.cardview_cardview-nodeps/android_common/aar/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.slice_slice-view-nodeps/android_common/aar/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.preference_preference-nodeps/android_common/aar/res")), null));
} catch (MalformedURLException e) {
throw new RuntimeException("SettingsRobolectricTestRunner failure", e);
}
}
}

View File

@@ -1,35 +0,0 @@
/*
* 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 com.android.settings.testutils;
import android.content.pm.ApplicationInfo;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.IconDrawableFactory;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(IconDrawableFactory.class)
public class ShadowIconDrawableFactory {
@Implementation
public Drawable getBadgedIcon(ApplicationInfo appInfo) {
return new ColorDrawable(Color.BLUE);
}
}

View File

@@ -1,41 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.bluetooth.BluetoothDevice;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(BluetoothDevice.class)
public class SettingsShadowBluetoothDevice {
private String mAddress;
public void __constructor__(String address) {
mAddress = address;
}
@Implementation
public String getAddress() {
return mAddress;
}
@Implementation
public int hashCode() {
return mAddress.hashCode();
}
}

View File

@@ -1,37 +1,19 @@
package com.android.settings.testutils.shadow;
import static android.util.TypedValue.TYPE_REFERENCE;
import static org.robolectric.RuntimeEnvironment.application;
import static org.robolectric.shadow.api.Shadow.directlyOn;
import android.annotation.DimenRes;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import androidx.annotation.ArrayRes;
import androidx.annotation.ColorRes;
import androidx.annotation.Nullable;
import com.android.settings.R;
import org.robolectric.android.XmlResourceParserImpl;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadows.ShadowResources;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import org.w3c.dom.Node;
/**
* Shadow Resources and Theme classes to handle resource references that Robolectric shadows cannot
@@ -46,9 +28,7 @@ public class SettingsShadowResources extends ShadowResources {
private static SparseArray<Object> sResourceOverrides = new SparseArray<>();
public static void overrideResource(int id, Object value) {
synchronized (sResourceOverrides) {
sResourceOverrides.put(id, value);
}
sResourceOverrides.put(id, value);
}
public static void overrideResource(String name, Object value) {
@@ -61,75 +41,12 @@ public class SettingsShadowResources extends ShadowResources {
}
public static void reset() {
synchronized (sResourceOverrides) {
sResourceOverrides.clear();
}
sResourceOverrides.clear();
}
@Implementation
public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
// Handle requests for private dimension resources,
// TODO: Consider making a set of private dimension resource ids if this happens repeatedly.
if (id == com.android.internal.R.dimen.preference_fragment_padding_bottom) {
return 0;
}
return directlyOn(realResources, Resources.class).getDimensionPixelSize(id);
}
@Implementation
public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
if (id == R.color.battery_icon_color_error) {
return Color.WHITE;
}
return directlyOn(realResources, Resources.class).getColor(id, theme);
}
@Implementation
public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
throws NotFoundException {
if (id == com.android.internal.R.color.text_color_primary) {
return ColorStateList.valueOf(Color.WHITE);
}
return directlyOn(realResources, Resources.class).getColorStateList(id, theme);
}
/**
* Deprecated because SDK 24+ uses
* {@link SettingsShadowResourcesImpl#loadDrawable(Resources, TypedValue, int, int, Theme)}
*
* TODO: Delete when all tests have been migrated to sdk 26
*/
@Deprecated
@Implementation
public Drawable loadDrawable(TypedValue value, int id, Theme theme)
throws NotFoundException {
// The drawable item in switchbar_background.xml refers to a very recent color attribute
// that Robolectric isn't yet aware of.
// TODO: Remove this once Robolectric is updated.
if (id == R.drawable.switchbar_background) {
return new ColorDrawable();
} else if (id == R.drawable.ic_launcher_settings) {
// ic_launcher_settings uses adaptive-icon, which is not supported by robolectric,
// change it to a normal drawable.
id = R.drawable.ic_settings_wireless;
} else if (id == R.drawable.app_filter_spinner_background) {
id = R.drawable.ic_expand_more_inverse;
}
return super.loadDrawable(value, id, theme);
}
@Implementation
public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
// The Robolectric isn't aware of resources in settingslib, so we need to stub it here
if (id == com.android.settings.R.array.batterymeter_bolt_points
|| id == com.android.settings.R.array.batterymeter_plus_points) {
return new int[2];
}
final Object override;
synchronized (sResourceOverrides) {
override = sResourceOverrides.get(id);
}
protected int[] getIntArray(@ArrayRes int id) throws NotFoundException {
final Object override = sResourceOverrides.get(id);
if (override instanceof int[]) {
return (int[]) override;
}
@@ -137,11 +54,8 @@ public class SettingsShadowResources extends ShadowResources {
}
@Implementation
public String getString(int id) {
final Object override;
synchronized (sResourceOverrides) {
override = sResourceOverrides.get(id);
}
protected String getString(int id) {
final Object override = sResourceOverrides.get(id);
if (override instanceof String) {
return (String) override;
}
@@ -150,11 +64,8 @@ public class SettingsShadowResources extends ShadowResources {
}
@Implementation
public int getInteger(int id) {
final Object override;
synchronized (sResourceOverrides) {
override = sResourceOverrides.get(id);
}
protected int getInteger(int id) {
final Object override = sResourceOverrides.get(id);
if (override instanceof Integer) {
return (Integer) override;
}
@@ -163,66 +74,12 @@ public class SettingsShadowResources extends ShadowResources {
}
@Implementation
public boolean getBoolean(int id) {
final Object override;
synchronized (sResourceOverrides) {
override = sResourceOverrides.get(id);
}
protected boolean getBoolean(int id) {
final Object override = sResourceOverrides.get(id);
if (override instanceof Boolean) {
return (boolean) override;
}
return directlyOn(realResources, Resources.class, "getBoolean",
ClassParameter.from(int.class, id));
}
@Implements(value = Theme.class)
public static class SettingsShadowTheme extends ShadowLegacyTheme {
@RealObject
Theme realTheme;
@Implementation
protected TypedArray obtainStyledAttributes(
AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
// Replace all private string references with a placeholder.
if (set != null) {
synchronized (set) {
for (int i = 0; i < set.getAttributeCount(); ++i) {
final String attributeValue = set.getAttributeValue(i);
final Node node = ReflectionHelpers.callInstanceMethod(
XmlResourceParserImpl.class, set, "getAttributeAt",
ReflectionHelpers.ClassParameter.from(int.class, i));
if (attributeValue.contains("attr/fingerprint_layout_theme")) {
// Workaround for https://github.com/robolectric/robolectric/issues/2641
node.setNodeValue("@style/FingerprintLayoutTheme");
}
}
}
}
return super.obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes);
}
@Implementation
public synchronized boolean resolveAttribute(int resid, TypedValue outValue,
boolean resolveRefs) {
// The real Resources instance in Robolectric tests somehow fails to find the
// preferenceTheme attribute in the layout. Let's do it ourselves.
if (getResources().getResourceName(resid)
.equals("com.android.settings:attr/preferenceTheme")) {
final int preferenceThemeResId =
getResources().getIdentifier(
"PreferenceTheme", "style", "com.android.settings");
outValue.type = TYPE_REFERENCE;
outValue.data = preferenceThemeResId;
outValue.resourceId = preferenceThemeResId;
return true;
}
return directlyOn(realTheme, Theme.class)
.resolveAttribute(resid, outValue, resolveRefs);
}
private Resources getResources() {
return ReflectionHelpers.callInstanceMethod(ShadowLegacyTheme.class, this, "getResources");
}
}
}

View File

@@ -1,63 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.res.Resources;
import android.content.res.ResourcesImpl;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import com.android.settings.R;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowLegacyResourcesImpl;
@Implements(
value = ResourcesImpl.class,
isInAndroidSdk = false,
minSdk = 26
)
public class SettingsShadowResourcesImpl extends ShadowLegacyResourcesImpl {
@Implementation
public Drawable loadDrawable(Resources wrapper, TypedValue value, int id, int density,
Resources.Theme theme) {
// The drawable item in switchbar_background.xml refers to a very recent color attribute
// that Robolectric isn't yet aware of.
// TODO: Remove this once Robolectric is updated.
if (id == R.drawable.switchbar_background
|| id == R.color.ripple_material_light
|| id == R.color.ripple_material_dark) {
return new ColorDrawable();
} else if (id == R.drawable.ic_launcher_settings) {
// ic_launcher_settings uses adaptive-icon, which is not supported by robolectric,
// change it to a normal drawable.
id = R.drawable.ic_settings_wireless;
} else if (id == R.drawable.app_filter_spinner_background) {
id = R.drawable.ic_expand_more_inverse;
} else if (id == R.drawable.color_bar_progress
|| id == R.drawable.ring_progress) {
// color_bar_progress and ring_progress use hidden resources, so just use the regular
// progress_horizontal drawable
id = android.R.drawable.progress_horizontal;
}
return super.loadDrawable(wrapper, value, id, density, theme);
}
}

View File

@@ -1,47 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import static org.robolectric.shadow.api.Shadow.directlyOn;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import androidx.annotation.Nullable;
import androidx.annotation.StyleableRes;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadows.ShadowTypedArray;
@Implements(value = TypedArray.class)
public class SettingsShadowTypedArray extends ShadowTypedArray {
@RealObject
TypedArray realTypedArray;
@Implementation
@Nullable
public ColorStateList getColorStateList(@StyleableRes int index) {
if (index == com.android.internal.R.styleable.TextView_textColorLink) {
return ColorStateList.valueOf(Color.WHITE);
}
return directlyOn(realTypedArray, TypedArray.class).getColorStateList(index);
}
}

View File

@@ -25,7 +25,7 @@ import org.robolectric.annotation.Implements;
public class ShadowAccessPoint {
@Implementation
public String getSavedNetworkSummary() {
protected String getSavedNetworkSummary() {
return "saved";
}
}

View File

@@ -1,49 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.view.accessibility.AccessibilityManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.ArrayList;
import java.util.List;
@Implements(AccessibilityManager.class)
public class ShadowAccessibilityManager {
private static final List<AccessibilityServiceInfo> mInstalledAccessibilityList =
new ArrayList<>();
public static void addAccessibilityService(String serviceName) {
AccessibilityServiceInfo serviceInfo = new AccessibilityServiceInfo();
serviceInfo.setComponentName(ComponentName.unflattenFromString(serviceName));
mInstalledAccessibilityList.add(serviceInfo);
}
@Implementation
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
return mInstalledAccessibilityList;
}
@Implementation
public static boolean isAccessibilityButtonSupported() {
return true;
}
}

View File

@@ -31,7 +31,7 @@ public class ShadowAccessibilityServiceInfo {
}
@Implementation
public ComponentName getComponentName() {
protected ComponentName getComponentName() {
return sComponentName;
}
}

View File

@@ -36,7 +36,7 @@ public class ShadowAccountManager {
private static final Map<Integer, List<Account>> sAccountsByUserId = new HashMap<>();
@Implementation
public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
protected AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
return sAuthenticators.values().toArray(new AuthenticatorDescription[sAuthenticators.size()]);
}
@@ -50,7 +50,7 @@ public class ShadowAccountManager {
}
@Implementation @NonNull
public Account[] getAccountsAsUser(int userId) {
protected Account[] getAccountsAsUser(int userId) {
if (sAccountsByUserId.containsKey(userId)) {
return sAccountsByUserId.get(userId).toArray(new Account[0]);
} else {

View File

@@ -26,7 +26,7 @@ public class ShadowActivityManager {
private static int sCurrentUserId = 0;
@Implementation
public static int getCurrentUser() {
protected static int getCurrentUser() {
return sCurrentUserId;
}

View File

@@ -1,44 +0,0 @@
/*
* 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.testutils.shadow;
import android.app.Activity;
import androidx.loader.app.LoaderManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowActivity;
/*
* Shadow for {@link Activity} that has LoadManager accessors.
*/
@Implements(Activity.class)
public class ShadowActivityWithLoadManager extends ShadowActivity {
private LoaderManager mLoaderManager;
@Implementation
public LoaderManager getLoaderManager() {
return mLoaderManager;
}
// Non-Android setter.
public void setLoaderManager(LoaderManager loaderManager) {
mLoaderManager = loaderManager;
}
}

View File

@@ -25,12 +25,12 @@ import org.robolectric.annotation.Implements;
public class ShadowAppInfoBase {
@Implementation
public void onResume() {
protected void onResume() {
// No-op.
}
@Implementation
public void onPause() {
protected void onPause() {
// No-op.
}
}

View File

@@ -26,7 +26,7 @@ import org.robolectric.annotation.Implements;
@Implements(ApplicationsState.class)
public class ShadowApplicationsState {
@Implementation
public Looper getBackgroundLooper() {
protected Looper getBackgroundLooper() {
return Looper.getMainLooper();
}
}

View File

@@ -28,12 +28,12 @@ import org.robolectric.annotation.Implements;
public class ShadowAudioHelper {
@Implementation
public boolean isSingleVolume() {
protected boolean isSingleVolume() {
return true;
}
@Implementation
public int getManagedProfileId(UserManager um) {
protected int getManagedProfileId(UserManager um) {
return UserHandle.USER_CURRENT;
}
}

View File

@@ -31,9 +31,9 @@ import android.media.AudioDeviceCallback;
import android.media.AudioManager;
import android.os.Handler;
import java.util.List;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
@@ -43,8 +43,7 @@ public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManag
private int mRingerMode;
private int mDeviceCodes;
private boolean mMusicActiveRemotely;
private boolean mBluetoothScoOn;
private ArrayList<AudioDeviceCallback> mDeviceCallbacks = new ArrayList();
private List<AudioDeviceCallback> mDeviceCallbacks = new ArrayList<>();
@Implementation
private int getRingerModeInternal() {
@@ -100,11 +99,4 @@ public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManag
return 0;
}
}
public void setBluetoothScoOn(boolean bluetoothScoOn) {
mBluetoothScoOn = bluetoothScoOn;
}
@Implementation
public boolean isBluetoothScoOn() { return mBluetoothScoOn; }
}

View File

@@ -1,31 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import androidx.core.text.BidiFormatter;
import androidx.core.text.TextDirectionHeuristicCompat;
import org.robolectric.annotation.Implements;
@Implements(BidiFormatter.class)
public class ShadowBidiFormatter {
public CharSequence unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic,
boolean isolate) {
return str;
}
}

View File

@@ -28,10 +28,10 @@ import java.util.List;
public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBluetoothAdapter {
private int mState;
private List<Integer> mSupportedProfiles = new ArrayList<Integer>();
private List<Integer> mSupportedProfiles = new ArrayList<>();
@Implementation
public List<Integer> getSupportedProfiles() {
protected List<Integer> getSupportedProfiles() {
return mSupportedProfiles;
}
@@ -44,7 +44,7 @@ public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBlueto
}
@Implementation
public int getConnectionState() {
protected int getConnectionState() {
return mState;
}

View File

@@ -29,32 +29,32 @@ public class ShadowBluetoothDevice extends org.robolectric.shadows.ShadowBluetoo
private int mSimAccessPermission = BluetoothDevice.ACCESS_UNKNOWN;
@Implementation
public void setMessageAccessPermission(int value) {
protected void setMessageAccessPermission(int value) {
mMessageAccessPermission = value;
}
@Implementation
public int getMessageAccessPermission() {
protected int getMessageAccessPermission() {
return mMessageAccessPermission;
}
@Implementation
public void setPhonebookAccessPermission(int value) {
protected void setPhonebookAccessPermission(int value) {
mPhonebookAccessPermission = value;
}
@Implementation
public int getPhonebookAccessPermission() {
protected int getPhonebookAccessPermission() {
return mPhonebookAccessPermission;
}
@Implementation
public void setSimAccessPermission(int value) {
protected void setSimAccessPermission(int value) {
mSimAccessPermission = value;
}
@Implementation
public int getSimAccessPermission() {
protected int getSimAccessPermission() {
return mSimAccessPermission;
}
}

View File

@@ -1,32 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(BluetoothPan.class)
public class ShadowBluetoothPan {
@Implementation
public void __constructor__(Context context, BluetoothProfile.ServiceListener l) {
// Do nothing, implement it to avoid null pointer error inside BluetoothPan
}
}

View File

@@ -27,12 +27,11 @@ import org.robolectric.annotation.Resetter;
@Implements(Utils.class)
public class ShadowBluetoothUtils {
public static LocalBluetoothManager sLocalBluetoothManager;
@Implementation
public static LocalBluetoothManager getLocalBtManager(Context context) {
protected static LocalBluetoothManager getLocalBtManager(Context context) {
return sLocalBluetoothManager;
}

View File

@@ -38,7 +38,7 @@ public class ShadowCachedBluetoothDeviceManager {
}
@Implementation
public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
protected synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
return mCachedDevices;
}
}

View File

@@ -35,7 +35,7 @@ public class ShadowConnectivityManager extends org.robolectric.shadows.ShadowCon
}
@Implementation
public boolean isNetworkSupported(int networkType) {
protected boolean isNetworkSupported(int networkType) {
return mSupportedNetworkTypes.get(networkType);
}
@@ -44,7 +44,7 @@ public class ShadowConnectivityManager extends org.robolectric.shadows.ShadowCon
}
@Implementation
public boolean isTetheringSupported() {
protected boolean isTetheringSupported() {
return mTetheringSupported;
}

View File

@@ -42,12 +42,12 @@ public class ShadowContentResolver {
private static Map<Integer, Boolean> sMasterSyncAutomatically = new HashMap<>();
@Implementation
public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
protected static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
return sSyncAdapterTypes;
}
@Implementation
public final Cursor query(Uri uri, String[] projection, String selection,
protected final Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
MatrixCursor.RowBuilder builder = cursor.newRow()
@@ -56,26 +56,26 @@ public class ShadowContentResolver {
}
@Implementation
public static int getIsSyncableAsUser(Account account, String authority, int userId) {
protected static int getIsSyncableAsUser(Account account, String authority, int userId) {
return sSyncable.containsKey(authority) ? sSyncable.get(authority) : 1;
}
@Implementation
public static boolean getSyncAutomaticallyAsUser(Account account, String authority,
protected static boolean getSyncAutomaticallyAsUser(Account account, String authority,
int userId) {
return sSyncAutomatically.containsKey(authority) ? sSyncAutomatically.get(authority) : true;
}
@Implementation
public static void setSyncAutomaticallyAsUser(Account account, String authority, boolean sync,
int userId) {
protected static void setSyncAutomaticallyAsUser(Account account, String authority,
boolean sync, int userId) {
if (TextUtils.isEmpty(authority)) {
throw new IllegalArgumentException("Authority must be non-empty");
}
}
@Implementation
public static boolean getMasterSyncAutomaticallyAsUser(int userId) {
protected static boolean getMasterSyncAutomaticallyAsUser(int userId) {
return sMasterSyncAutomatically.containsKey(userId)
? sMasterSyncAutomatically.get(userId) : true;
}

View File

@@ -1,40 +0,0 @@
/*
* 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.testutils.shadow;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.UserHandle;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowContextImpl;
/*
* Shadow for {@link ContextImpl} that has registerReceiverAsUser method.
*/
@Implements(className = ShadowContextImpl.CLASS_NAME)
public class ShadowContextImplWithRegisterReceiver extends ShadowContextImpl {
@Implementation
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
}

View File

@@ -11,12 +11,12 @@ public class ShadowDataSaverBackend {
private static boolean isEnabled = true;
@Implementation
public boolean isDataSaverEnabled() {
protected boolean isDataSaverEnabled() {
return isEnabled;
}
@Implementation
public void setDataSaverEnabled(boolean enabled) {
protected void setDataSaverEnabled(boolean enabled) {
isEnabled = enabled;
}
}

View File

@@ -17,25 +17,25 @@ public class ShadowDataUsageUtils {
public static int DEFAULT_SUBSCRIPTION_ID = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@Implementation
public static boolean hasMobileData(Context context) {
protected static boolean hasMobileData(Context context) {
return IS_MOBILE_DATA_SUPPORTED;
}
@Implementation
public static boolean hasWifiRadio(Context context) {
protected static boolean hasWifiRadio(Context context) {
return IS_WIFI_SUPPORTED;
}
@Implementation
public static int getDefaultSubscriptionId(Context context) {
protected static int getDefaultSubscriptionId(Context context) {
return DEFAULT_SUBSCRIPTION_ID;
}
@Implementation
public static boolean hasSim(Context context) {
protected static boolean hasSim(Context context) {
return HAS_SIM;
}
@Implementation
public static boolean hasEthernet(Context context) { return false; }
protected static boolean hasEthernet(Context context) { return false; }
}

View File

@@ -1,37 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.Context;
import android.content.pm.ResolveInfo;
import com.android.settings.search.DatabaseIndexingUtils;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
/**
* Shadow of {@link DatabaseIndexingUtils}
*/
@Implements(DatabaseIndexingUtils.class)
public class ShadowDatabaseIndexingUtils {
@Implementation
public static boolean isWellKnownProvider(ResolveInfo info, Context context) {
return true;
}
}

View File

@@ -5,7 +5,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.os.PersistableBundle;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
@@ -13,7 +12,6 @@ import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -23,7 +21,7 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
private final Map<Integer, Long> mProfileTimeouts = new HashMap<>();
private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>();
private boolean mIsAdminActiveAsUser = false;
ComponentName mDeviceOwnerComponentName;
private ComponentName mDeviceOwnerComponentName;
private int mDeviceOwnerUserId = -1;
public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) {
@@ -31,29 +29,28 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
}
@Implementation
public @Nullable
CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
protected @Nullable CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
int userHandle) {
return mSupportMessagesMap.get(Objects.hash(admin, userHandle));
}
@Implementation
public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
protected boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
return mIsAdminActiveAsUser;
}
@Implementation
public int getDeviceOwnerUserId() {
protected int getDeviceOwnerUserId() {
return mDeviceOwnerUserId;
}
@Implementation
public long getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle) {
protected long getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle) {
return mProfileTimeouts.getOrDefault(userHandle, 0L);
}
@Implementation
public ComponentName getDeviceOwnerComponentOnAnyUser() {
protected ComponentName getDeviceOwnerComponentOnAnyUser() {
return mDeviceOwnerComponentName;
}
@@ -77,10 +74,4 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
return (ShadowDevicePolicyManager) Shadow.extract(
RuntimeEnvironment.application.getSystemService(DevicePolicyManager.class));
}
public @Nullable
List<PersistableBundle> getTrustAgentConfiguration(
@Nullable ComponentName admin, @NonNull ComponentName agent) {
return null;
}
}

View File

@@ -12,13 +12,14 @@ import org.robolectric.annotation.Implements;
@Implements(DoubleTwistPreferenceController.class)
public class ShadowDoubleTwistPreferenceController {
private static int sManagedProfileId = UserHandle.USER_NULL;
@Implementation
public static boolean isGestureAvailable(Context context) {
protected static boolean isGestureAvailable(Context context) {
return true;
}
@Implementation
public static int getManagedProfileId(UserManager userManager) {
protected static int getManagedProfileId(UserManager userManager) {
return sManagedProfileId;
}

View File

@@ -1,42 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.text.DynamicLayout;
import android.text.Layout.Directions;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(DynamicLayout.class)
public class ShadowDynamicLayout {
@Implementation
public int getLineTop(int line) {
return 0;
}
@Implementation
public int getLineStart(int line) {
return 0;
}
@Implementation
public final Directions getLineDirections(int line) {
return new Directions(new int[]{0, 1});
}
}

View File

@@ -42,9 +42,8 @@ public class ShadowEntityHeaderController {
}
@Implementation
public static EntityHeaderController newInstance(Activity activity, Fragment fragment,
protected static EntityHeaderController newInstance(Activity activity, Fragment fragment,
View header) {
return sMockController;
}
}
}

View File

@@ -1,33 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.Context;
import com.android.settingslib.core.instrumentation.EventLogWriter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(value = EventLogWriter.class, callThroughByDefault = false)
public class ShadowEventLogWriter {
@Implementation
public void visible(Context context, int source, int category) {
}
}

View File

@@ -19,64 +19,16 @@ package com.android.settings.testutils.shadow;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import androidx.annotation.NonNull;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
@Implements(FingerprintManager.class)
public class ShadowFingerprintManager extends org.robolectric.shadows.ShadowFingerprintManager {
public boolean hardwareDetected = true;
@NonNull
private List<Fingerprint> mFingerprints = Collections.emptyList();
@Implementation
protected boolean isHardwareDetected() {
return hardwareDetected;
}
@Implementation
protected boolean hasEnrolledFingerprints() {
return !mFingerprints.isEmpty();
}
@Implementation
protected List<Fingerprint> getEnrolledFingerprints() {
return mFingerprints;
}
@Implementation
protected List<Fingerprint> getEnrolledFingerprints(int userId) {
return mFingerprints;
}
public void setEnrolledFingerprints(Fingerprint... fingerprints) {
mFingerprints = Arrays.asList(fingerprints);
}
public void setDefaultFingerprints(int num) {
setEnrolledFingerprints(
IntStream.range(0, num)
.mapToObj(i -> new Fingerprint(
"Fingerprint " + i,
0, /* groupId */
i, /* fingerId */
0 /* deviceId */))
.toArray(Fingerprint[]::new));
}
public static ShadowFingerprintManager get() {
return (ShadowFingerprintManager) Shadow.extract(
RuntimeEnvironment.application.getSystemService(FingerprintManager.class));
return getEnrolledFingerprints();
}
}

View File

@@ -17,31 +17,22 @@
package com.android.settings.testutils.shadow;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
/**
* Override the {@link #setTargetFragment(Fragment, int)} to skip an illegal state exception
* in SDK 26. SDK 26 requires that the target fragment be in the same {@link FragmentManager} as
* the current {@link Fragment}. This is infeasible with our current framework.
*/
@Implements(
value = Fragment.class,
minSdk = 26
)
@Implements(value = Fragment.class)
public class ShadowFragment {
private Fragment mTargetFragment;
@Implementation
public void setTargetFragment(Fragment fragment, int requestCode) {
protected void setTargetFragment(Fragment fragment, int requestCode) {
mTargetFragment = fragment;
}
@Implementation
final public Fragment getTargetFragment() {
protected Fragment getTargetFragment() {
return mTargetFragment;
}
}

View File

@@ -42,7 +42,7 @@ public class ShadowHelpUtils {
}
@Implementation
public static Intent getHelpIntent(Context context, String helpUriString,
protected static Intent getHelpIntent(Context context, String helpUriString,
String backupContext) {
mGetHelpIntentCalled = true;
return new Intent().setClassName(

View File

@@ -36,12 +36,12 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
private int mDeviceId;
@Implementation
public static int[] getDeviceIds() {
protected static int[] getDeviceIds() {
return sDeviceIds;
}
@Implementation
public static InputDevice getDevice(int id) {
protected static InputDevice getDevice(int id) {
return sDeviceMap.get(id);
}
@@ -56,7 +56,7 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
}
@Implementation
public int getId() {
protected int getId() {
return mDeviceId;
}
@@ -70,6 +70,4 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
public void setId(int id) {
mDeviceId = id;
}
}

View File

@@ -27,31 +27,31 @@ import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
* Shadow for {@ InputManager} that has assessors for registered {@link InputDeviceListener}s.
/**
* Shadow for {@link InputManager} that has accessors for registered
* {@link InputManager.InputDeviceListener}s.
*/
@Implements(value = InputManager.class, callThroughByDefault = false)
public class ShadowInputManager {
private ArrayList<InputManager.InputDeviceListener> mInputDeviceListeners;
private List<InputManager.InputDeviceListener> mInputDeviceListeners;
@Implementation
public void __constructor__(IInputManager service) {
protected void __constructor__(IInputManager service) {
mInputDeviceListeners = new ArrayList<>();
}
@Implementation
public static InputManager getInstance() {
protected static InputManager getInstance() {
return ReflectionHelpers.callConstructor(
InputManager.class,
from(IInputManager.class, null));
}
@Implementation
public void registerInputDeviceListener(InputManager.InputDeviceListener listener,
protected void registerInputDeviceListener(InputManager.InputDeviceListener listener,
Handler handler) {
// TODO: Use handler.
if (!mInputDeviceListeners.contains(listener)) {
@@ -60,14 +60,7 @@ public class ShadowInputManager {
}
@Implementation
public void unregisterInputDeviceListener(InputManager.InputDeviceListener listener) {
if (mInputDeviceListeners.contains(listener)) {
mInputDeviceListeners.remove(listener);
}
}
// Non-Android accessor.
public List<InputManager.InputDeviceListener> getRegisteredInputDeviceListeners() {
return Collections.unmodifiableList(mInputDeviceListeners);
protected void unregisterInputDeviceListener(InputManager.InputDeviceListener listener) {
mInputDeviceListeners.remove(listener);
}
}

View File

@@ -42,7 +42,7 @@ public class ShadowInputMethodManagerWithMethodList extends ShadowInputMethodMan
}
@Implementation
public List<InputMethodInfo> getInputMethodList() {
protected List<InputMethodInfo> getInputMethodList() {
return mInputMethodInfos;
}

View File

@@ -33,7 +33,7 @@ public class ShadowKeyStore {
}
@Implementation
public boolean isHardwareBacked() {
protected boolean isHardwareBacked() {
return sIsHardwareBacked;
}

View File

@@ -1,55 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(LocalBluetoothAdapter.class)
public class ShadowLocalBluetoothAdapter {
private static String sName;
private boolean isBluetoothEnabled = true;
public static void setName(String name) {
sName = name;
}
@Implementation
public String getName() {
return sName;
}
@Implementation
public boolean isEnabled() {
return isBluetoothEnabled;
}
@Implementation
public boolean enable() {
isBluetoothEnabled = true;
return true;
}
@Implementation
public boolean disable() {
isBluetoothEnabled = false;
return true;
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.Context;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.robolectric.annotation.Implements;
@Implements(LocalBluetoothProfileManager.class)
public class ShadowLocalBluetoothProfileManager {
public void __constructor__(Context context,
LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
BluetoothEventManager eventManager) {
}
}

View File

@@ -29,45 +29,34 @@ import java.util.List;
@Implements(LockPatternUtils.class)
public class ShadowLockPatternUtils {
private int mPasswordQuality = 1;
private static boolean sDeviceEncryptionEnabled;
@Implementation
public boolean isSecure(int id) {
protected boolean isSecure(int id) {
return true;
}
@Implementation
public int getActivePasswordQuality(int userId) {
protected int getActivePasswordQuality(int userId) {
return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}
@Implementation
public int getKeyguardStoredPasswordQuality(int userHandle) {
return mPasswordQuality;
protected int getKeyguardStoredPasswordQuality(int userHandle) {
return 1;
}
@Implementation
public static boolean isDeviceEncryptionEnabled() {
protected static boolean isDeviceEncryptionEnabled() {
return sDeviceEncryptionEnabled;
}
@Implementation
public List<ComponentName> getEnabledTrustAgents(int userId) {
protected List<ComponentName> getEnabledTrustAgents(int userId) {
return null;
}
public static void setDeviceEncryptionEnabled(boolean deviceEncryptionEnabled) {
sDeviceEncryptionEnabled = deviceEncryptionEnabled;
}
// Non-Android accessor.
public int getPasswordQuality() {
return mPasswordQuality;
}
// Non-Android accessor.
public void setPasswordQuality(int passwordQuality) {
mPasswordQuality = passwordQuality;
}
}

View File

@@ -1,52 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import static org.robolectric.RuntimeEnvironment.application;
import android.media.MediaRouter;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import java.util.concurrent.CopyOnWriteArrayList;
@Implements(value = MediaRouter.class)
public class ShadowMediaRouter extends org.robolectric.shadows.ShadowMediaRouter {
MediaRouter.RouteInfo mSelectedRoute;
final CopyOnWriteArrayList<MediaRouter.Callback> mCallbacks =
new CopyOnWriteArrayList<>();
public MediaRouter.RouteInfo getSelectedRoute(int type) {
return mSelectedRoute;
}
public void addCallback(int types, MediaRouter.Callback cb) {
mCallbacks.add(cb);
}
public void removeCallback(MediaRouter.Callback cb) {
if (mCallbacks.contains(cb)) {
mCallbacks.remove(cb);
}
}
public static ShadowMediaRouter getShadow() {
return Shadow.extract(application.getSystemService(MediaRouter.class));
}
}

View File

@@ -36,30 +36,30 @@ public class ShadowNfcAdapter {
private boolean mIsNfcEnabled = false;
@Implementation
public void enableReaderMode(Activity activity, NfcAdapter.ReaderCallback callback, int flags,
Bundle extras) {
protected void enableReaderMode(Activity activity, NfcAdapter.ReaderCallback callback,
int flags, Bundle extras) {
sReaderModeEnabled = true;
}
@Implementation
public static NfcAdapter getDefaultAdapter(Context context) {
protected static NfcAdapter getDefaultAdapter(Context context) {
return ReflectionHelpers.callConstructor(
NfcAdapter.class, ClassParameter.from(Context.class, context));
}
@Implementation
public boolean isEnabled() {
protected boolean isEnabled() {
return mIsNfcEnabled;
}
@Implementation
public boolean enable() {
protected boolean enable() {
mIsNfcEnabled = true;
return true;
}
@Implementation
public boolean disable() {
protected boolean disable() {
mIsNfcEnabled = false;
return true;
}

View File

@@ -27,15 +27,13 @@ public class ShadowNotificationManager {
private int mZenMode;
@Implementation
public void setZenMode(int mode, Uri conditionId, String reason) {
protected void setZenMode(int mode, Uri conditionId, String reason) {
mZenMode = mode;
}
@Implementation
public int getZenMode() {
protected int getZenMode() {
return mZenMode;
}
}

View File

@@ -40,7 +40,7 @@ public class ShadowOs {
private static final byte[] IPV6_BYTES = new byte[16];
@Implementation
public static InetAddress inet_pton(int family, String address) {
protected static InetAddress inet_pton(int family, String address) {
if ((AF_INET == family && IPV4_PATTERN.matcher(address).find()) ||
(AF_INET6 == family && IPV6_PATTERN.matcher(address).find())) {
try {

View File

@@ -1,63 +0,0 @@
/*
* 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.testutils.shadow;
import static org.robolectric.util.ReflectionHelpers.ClassParameter.from;
import android.content.Context;
import android.os.Looper;
import android.os.UserHandle;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowMessageQueue;
/*
* Shadow for hidden {@link PackageMonitor}.
*/
@Implements(value = PackageMonitor.class, isInAndroidSdk = false)
public class ShadowPackageMonitor {
@RealObject
private PackageMonitor mPackageMonitor;
@Implementation
public void register(Context context, Looper thread, UserHandle user, boolean externalStorage) {
// Call through to @RealObject's method.
Shadow.directlyOn(mPackageMonitor, PackageMonitor.class, "register",
from(Context.class, context), from(Looper.class, thread),
from(UserHandle.class, user), from(Boolean.TYPE, externalStorage));
// When <code>thread</code> is null, the {@link BackgroundThread} is used. Here we have to
// setup background Robolectric scheduler for it.
if (thread == null) {
setupBackgroundThreadScheduler();
}
}
private static void setupBackgroundThreadScheduler() {
ShadowMessageQueue shadowMessageQueue = Shadow.extract(
BackgroundThread.getHandler().getLooper().getQueue());
shadowMessageQueue.setScheduler(
ShadowApplication.getInstance().getBackgroundThreadScheduler());
}
}

View File

@@ -16,17 +16,17 @@ public class ShadowParcel {
public static boolean sReadBoolResult;
@Implementation
public int readInt() {
protected int readInt() {
return sReadIntResult;
}
@Implementation
public void writeInt(int val) {
protected void writeInt(int val) {
sWriteIntResult = val;
}
@Implementation
public boolean readBoolean() {
protected boolean readBoolean() {
return sReadBoolResult;
}
}

View File

@@ -1,91 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.core.content.PermissionChecker;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* This class provides shadow for API that is not supported in current roboletric
*/
@Implements(PermissionChecker.class)
public class ShadowPermissionChecker {
private static Map<PermissionInfo, Integer> sPermissions = new HashMap<>();
public static void clear() {
sPermissions.clear();
}
public static void addPermission(String permission, int pid, int uid, String packageName,
int permissionValue) {
sPermissions.put(new PermissionInfo(permission, pid, uid, packageName), permissionValue);
}
@Implementation
public static int checkPermission(@NonNull Context context, @NonNull String permission,
int pid, int uid, String packageName) {
return sPermissions.getOrDefault(new PermissionInfo(permission, pid, uid, packageName),
PackageManager.PERMISSION_DENIED);
}
private static class PermissionInfo {
private final int mPid;
private final int mUid;
private final String mPackageName;
private final String mPermission;
public PermissionInfo(String permission, int pid, int uid, String packageName) {
mPid = pid;
mUid = uid;
mPackageName = packageName;
mPermission = permission;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PermissionInfo)) {
return false;
}
final PermissionInfo other = (PermissionInfo) obj;
return mPid == other.mPid
&& mUid == other.mUid
&& TextUtils.equals(mPackageName, other.mPackageName)
&& TextUtils.equals(mPermission, other.mPermission);
}
@Override
public int hashCode() {
return Objects.hash(mPid, mUid, mPackageName, mPermission);
}
}
}

View File

@@ -26,22 +26,22 @@ import org.robolectric.annotation.Implements;
public class ShadowPowerManager {
@Implementation
public int getMinimumScreenBrightnessSetting() {
protected int getMinimumScreenBrightnessSetting() {
return 0;
}
@Implementation
public int getMaximumScreenBrightnessSetting() {
protected int getMaximumScreenBrightnessSetting() {
return 0;
}
@Implementation
public int getMinimumScreenBrightnessForVrSetting() {
protected int getMinimumScreenBrightnessForVrSetting() {
return 0;
}
@Implementation
public int getMaximumScreenBrightnessForVrSetting() {
protected int getMaximumScreenBrightnessForVrSetting() {
return 0;
}
}

View File

@@ -22,7 +22,7 @@ import org.robolectric.annotation.Implements;
@Implements(PowerWhitelistBackend.class)
public class ShadowPowerWhitelistBackend {
public void __constructor__() {
protected void __constructor__() {
// Do nothing
}
}

View File

@@ -1,18 +0,0 @@
package com.android.settings.testutils.shadow;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(android.os.Process.class)
public class ShadowProcess {
private static int sUid;
public static void setMyUid(int uid) {
sUid = uid;
}
@Implementation
public static int myUid() {
return sUid;
}
}

View File

@@ -29,7 +29,7 @@ public class ShadowRecoverySystem {
private static int sWipeEuiccCalledCount;
@Implementation
public static boolean wipeEuiccData(Context context, final String packageName) {
protected static boolean wipeEuiccData(Context context, final String packageName) {
sWipeEuiccCalledCount++;
return true;
}

View File

@@ -29,7 +29,7 @@ public class ShadowRestrictedLockUtils {
private static boolean sAdminSupportDetailsIntentLaunched;
@Implementation
public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
protected static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
sAdminSupportDetailsIntentLaunched = true;
}
@@ -40,6 +40,4 @@ public class ShadowRestrictedLockUtils {
public static void clearAdminSupportDetailsIntentLaunch() {
sAdminSupportDetailsIntentLaunched = false;
}
}

View File

@@ -48,7 +48,7 @@ public class ShadowRestrictedLockUtilsInternal {
}
@Implementation
public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
protected static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
String packageName, int userId) {
if (sIsRestricted) {
return new EnforcedAdmin();
@@ -60,7 +60,7 @@ public class ShadowRestrictedLockUtilsInternal {
}
@Implementation
public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
protected static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
String accountType, int userId) {
if (accountType == null) {
return null;
@@ -79,25 +79,25 @@ public class ShadowRestrictedLockUtilsInternal {
}
@Implementation
public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
protected static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
int features, final @UserIdInt int userId) {
return (sKeyguardDisabledFeatures & features) == 0 ? null : new EnforcedAdmin();
}
@Implementation
public static boolean hasBaseUserRestriction(Context context,
protected static boolean hasBaseUserRestriction(Context context,
String userRestriction, int userId) {
return sIsRestricted;
}
@Implementation
public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
protected static EnforcedAdmin checkIfRestrictionEnforced(Context context,
String userRestriction, int userId) {
return sIsRestricted ? new EnforcedAdmin() : null;
}
@Implementation
public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) {
protected static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) {
return sMaximumTimeToLockIsSet ? new EnforcedAdmin() : null;
}
@@ -132,5 +132,4 @@ public class ShadowRestrictedLockUtilsInternal {
public static void setMaximumTimeToLockIsSet(boolean isSet) {
sMaximumTimeToLockIsSet = isSet;
}
}

View File

@@ -13,7 +13,7 @@ public class ShadowRestrictionUtils {
private static boolean isRestricted = false;
@Implementation
public EnforcedAdmin checkIfRestrictionEnforced(Context context, String restriction) {
protected EnforcedAdmin checkIfRestrictionEnforced(Context context, String restriction) {
if (isRestricted) {
return new EnforcedAdmin();
}

View File

@@ -25,20 +25,22 @@ import org.robolectric.annotation.Implements;
@Implements(RotationPolicy.class)
public class ShadowRotationPolicy {
private static boolean rotationLockEnabled = false;
private static boolean rotationSupported = true;
@Implementation
public static void setRotationLock(Context context, final boolean enabled) {
protected static void setRotationLock(Context context, final boolean enabled) {
rotationLockEnabled = enabled;
}
@Implementation
public static boolean isRotationLocked(Context context) {
protected static boolean isRotationLocked(Context context) {
return rotationLockEnabled;
}
@Implementation
public static boolean isRotationSupported(Context context) {
protected static boolean isRotationSupported(Context context) {
return rotationSupported;
}

View File

@@ -1,40 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.os.AsyncTask;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowAsyncTask;
import java.util.concurrent.Executor;
/**
* Shadow async task to handle runnables in roboletric
*/
@Implements(AsyncTask.class)
public class ShadowRunnableAsyncTask<Params, Progress, Result> extends
ShadowAsyncTask<Params, Progress, Result> {
@Implementation
public AsyncTask<Params, Progress, Result> executeOnExecutor(Executor executor,
Params... params) {
return super.execute(params);
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.Context;
import android.permission.RuntimePermissionPresenter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(RuntimePermissionPresenter.class)
public class ShadowRuntimePermissionPresenter {
private static RuntimePermissionPresenter mRuntimePermissionPresenter;
@Implementation
public static RuntimePermissionPresenter getInstance(Context context) {
return mRuntimePermissionPresenter;
}
public static void setRuntimePermissionPresenter(
RuntimePermissionPresenter runtimePermissionPresenter) {
mRuntimePermissionPresenter = runtimePermissionPresenter;
}
}

View File

@@ -1,39 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.os.Bundle;
import com.android.settings.SettingsPreferenceFragment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
/**
* Shadow of {@link SettingsPreferenceFragment}.
*
* Override the {@link #onCreate(Bundle)} to skip a null pointer exception in
* {@link android.content.res.Resources.Theme}, much the same as {@link ShadowDashboardFragment}.
*/
@Implements(SettingsPreferenceFragment.class)
public class ShadowSettingsPreferenceFragment {
@Implementation
public void onCreate(Bundle savedInstanceState) {
// do nothing
}
}

View File

@@ -1,65 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import static org.robolectric.RuntimeEnvironment.application;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import java.util.List;
@Implements(ShortcutManager.class)
public class ShadowShortcutManager extends org.robolectric.shadows.ShadowShortcutManager {
private List<ShortcutInfo> mPinnedShortcuts;
private List<ShortcutInfo> mLastUpdatedShortcuts;
@Resetter
public void reset() {
mPinnedShortcuts = null;
mLastUpdatedShortcuts = null;
}
public static ShadowShortcutManager get() {
return Shadow.extract(application.getSystemService(ShortcutManager.class));
}
@Implementation
public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) {
mLastUpdatedShortcuts = shortcutInfoList;
return true;
}
public List<ShortcutInfo> getLastUpdatedShortcuts() {
return mLastUpdatedShortcuts;
}
@Implementation
public List<ShortcutInfo> getPinnedShortcuts() {
return mPinnedShortcuts;
}
public void setPinnedShortcuts(List<ShortcutInfo> shortcutInfos) {
mPinnedShortcuts = shortcutInfos;
}
}

View File

@@ -48,27 +48,27 @@ public class ShadowStorageManager {
}
@Implementation
public VolumeInfo findVolumeById(String id) {
protected VolumeInfo findVolumeById(String id) {
return createVolumeInfo(id);
}
@Implementation
public DiskInfo findDiskById(String id) {
protected DiskInfo findDiskById(String id) {
return new DiskInfo(id, DiskInfo.FLAG_SD);
}
@Implementation
public VolumeRecord findRecordByUuid(String fsUuid) {
protected VolumeRecord findRecordByUuid(String fsUuid) {
return createVolumeRecord(fsUuid);
}
@Implementation
public void unmount(String volId) {
protected void unmount(String volId) {
sIsUnmountCalled = true;
}
@Implementation
public void forgetVolume(String fsUuid) {
protected void forgetVolume(String fsUuid) {
sIsForgetCalled = true;
}

View File

@@ -1,76 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.ContentResolver;
import android.provider.Settings;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
@Implements(Settings.System.class)
public class ShadowSystemSettings {
private static final Map<String, Object> sValueMap = new HashMap<>();
@Implementation
public static boolean putInt(ContentResolver resolver, String name, int value) {
sValueMap.put(name, value);
return true;
}
@Implementation
public static boolean putString(ContentResolver resolver, String name, String value) {
sValueMap.put(name, value);
return true;
}
@Implementation
public static String getString(ContentResolver resolver, String name) {
return (String) sValueMap.get(name);
}
@Implementation
public static String getStringForUser(ContentResolver resolver, String name, int userHandle) {
return getString(resolver, name);
}
@Implementation
public static boolean putIntForUser(ContentResolver cr, String name, int value,
int userHandle) {
return putInt(cr, name, value);
}
@Implementation
public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
return getInt(cr, name, def);
}
@Implementation
public static int getInt(ContentResolver resolver, String name, int defaultValue) {
Integer value = (Integer) sValueMap.get(name);
return value == null ? defaultValue : value;
}
public static void reset() {
sValueMap.clear();
}
}

View File

@@ -1,48 +0,0 @@
/*
* 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.testutils.shadow;
import android.icu.util.ULocale;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.Locale;
/**
* Important: The current robolectric doesn't support API 24, so I copy the code
* from API 24 here to make it compatible. Once robolectric is upgraded to 24,
* We can delete this shadow class.
**/
@Implements(TextUtils.class)
public class ShadowTextUtils {
@Implementation
public static int getLayoutDirectionFromLocale(Locale locale) {
return ((locale != null && !locale.equals(Locale.ROOT)
&& ULocale.forLocale(locale).isRightToLeft())
// If forcing into RTL layout mode, return RTL as default
|| SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false))
? View.LAYOUT_DIRECTION_RTL
: View.LAYOUT_DIRECTION_LTR;
}
}

View File

@@ -33,22 +33,21 @@ public class ShadowThreadUtils {
}
@Implementation
public static void postOnBackgroundThread(Runnable runnable) {
protected static void postOnBackgroundThread(Runnable runnable) {
runnable.run();
}
@Implementation
public static void postOnMainThread(Runnable runnable) {
protected static void postOnMainThread(Runnable runnable) {
runnable.run();
}
@Implementation
public static boolean isMainThread() {
protected static boolean isMainThread() {
return sIsMainThread;
}
public static void setIsMainThread(boolean isMainThread) {
sIsMainThread = isMainThread;
}
}

View File

@@ -1,38 +0,0 @@
package com.android.settings.testutils.shadow;
import android.content.Intent;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadows.ShadowService;
/**
* Shadow for {@link TileService}.
*/
@Implements(TileService.class)
public class ShadowTileService extends ShadowService {
@RealObject TileService realService;
private Tile mTile;
public void __constructor__() { }
@Implementation
public final Tile getQsTile() {
return mTile;
}
@Implementation
public final void startActivityAndCollapse(Intent intent) {
realService.startActivity(intent);
}
// Non-Android setter.
public void setTile(Tile tile) {
mTile = tile;
}
}

View File

@@ -32,19 +32,17 @@ import java.util.Map;
@Implements(TileUtils.class)
public class ShadowTileUtils {
public static final int ICON_RES_ID = R.drawable.ic_settings;
public static final String MOCK_SUMMARY = "summary";
@Implementation
public static String getTextFromUri(Context context, String uriString,
protected static String getTextFromUri(Context context, String uriString,
Map<String, IContentProvider> providerMap, String key) {
return MOCK_SUMMARY;
}
@Implementation
public static Pair<String, Integer> getIconFromUri(Context context, String packageName,
protected static Pair<String, Integer> getIconFromUri(Context context, String packageName,
String uriString, Map<String, IContentProvider> providerMap) {
return Pair.create(RuntimeEnvironment.application.getPackageName(), ICON_RES_ID);
return Pair.create(RuntimeEnvironment.application.getPackageName(), R.drawable.ic_settings);
}
}

View File

@@ -1,35 +0,0 @@
/*
* 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.testutils.shadow;
import android.icu.text.TimeZoneNames;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
/**
* TimeZoneNames.getDisplayName tries to access files which doesn't exist for Robolectric. Stub it
* out for a naive implementation.
*/
@Implements(TimeZoneNames.class)
public class ShadowTimeZoneNames {
@Implementation
public String getDisplayName(String tzID, TimeZoneNames.NameType type, long date) {
return "[DisplayName]" + tzID;
}
}

View File

@@ -21,13 +21,9 @@ import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import com.android.settings.Utils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.SearchFeatureProviderImpl;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -44,12 +40,12 @@ public class ShadowUtils {
private static Map<String, String> sAppNameMap;
@Implementation
public static int enforceSameOwner(Context context, int userId) {
protected static int enforceSameOwner(Context context, int userId) {
return userId;
}
@Implementation
public static FingerprintManager getFingerprintManagerOrNull(Context context) {
protected static FingerprintManager getFingerprintManagerOrNull(Context context) {
return sFingerprintManager;
}
@@ -80,7 +76,7 @@ public class ShadowUtils {
* Returns true if Monkey is running.
*/
@Implementation
public static boolean isMonkeyRunning() {
protected static boolean isMonkeyRunning() {
return sIsUserAMonkey;
}
@@ -89,17 +85,17 @@ public class ShadowUtils {
}
@Implementation
public static ComponentName getDeviceOwnerComponent(Context context) {
protected static ComponentName getDeviceOwnerComponent(Context context) {
return sDeviceOwnerComponentName;
}
@Implementation
public static int getManagedProfileId(UserManager um, int parentUserId) {
protected static int getManagedProfileId(UserManager um, int parentUserId) {
return UserHandle.USER_NULL;
}
@Implementation
public static CharSequence getApplicationLabel(Context context, String packageName) {
protected static CharSequence getApplicationLabel(Context context, String packageName) {
if (sAppNameMap != null) {
return sAppNameMap.get(packageName);
}
@@ -107,7 +103,7 @@ public class ShadowUtils {
}
@Implementation
public static boolean isPackageEnabled(Context context, String packageName) {
protected static boolean isPackageEnabled(Context context, String packageName) {
return true;
}

View File

@@ -37,23 +37,23 @@ public class ShadowWifiManager extends org.robolectric.shadows.ShadowWifiManager
@HiddenApi // @SystemApi
@Implementation
public void connect(WifiConfiguration config, WifiManager.ActionListener listener) {
protected void connect(WifiConfiguration config, WifiManager.ActionListener listener) {
savedWifiConfig = config;
}
@HiddenApi
@Implementation
public void save(WifiConfiguration config, WifiManager.ActionListener listener) {
protected void save(WifiConfiguration config, WifiManager.ActionListener listener) {
savedWifiConfig = config;
}
@Implementation
public List<PasspointConfiguration> getPasspointConfigurations() {
protected List<PasspointConfiguration> getPasspointConfigurations() {
return Collections.emptyList();
}
@Implementation
public boolean isDualModeSupported() {
protected boolean isDualModeSupported() {
return false;
}

View File

@@ -23,18 +23,15 @@ import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
/**
* Shadown class for WifiP2pManager.
* Shadow class for WifiP2pManager.
*/
@Implements(value = WifiP2pManager.class)
public class ShadowWifiP2pManager extends org.robolectric.shadows.ShadowWifiP2pManager {
private static int sFactoryResetCount;
/**
* factoryReset mock method.
*/
@Implementation
public void factoryReset(WifiP2pManager.Channel c, WifiP2pManager.ActionListener listener) {
protected void factoryReset(WifiP2pManager.Channel c, WifiP2pManager.ActionListener listener) {
if (c != null) {
sFactoryResetCount++;
} else {
@@ -42,9 +39,6 @@ public class ShadowWifiP2pManager extends org.robolectric.shadows.ShadowWifiP2pM
}
}
/**
* Reset variables in shadow class.
*/
@Resetter
public static void reset() {
sFactoryResetCount = 0;

View File

@@ -1,53 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.content.Context;
import com.android.settingslib.datetime.ZoneGetter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
@Implements(ZoneGetter.class)
public class ShadowZoneGetter {
@Implementation
public static List<Map<String, Object>> getZonesList(Context context) {
List<Map<String, Object>> zones = new ArrayList<>();
zones.add(createDisplayEntry(TimeZone.getDefault(), "gmt-1:00", "FakePlace", 10000));
return zones;
}
private static Map<String, Object> createDisplayEntry(
TimeZone tz, CharSequence gmtOffsetText, CharSequence displayName, int offsetMillis) {
Map<String, Object> map = new HashMap<>();
map.put(ZoneGetter.KEY_ID, tz.getID());
map.put(ZoneGetter.KEY_DISPLAYNAME, displayName.toString());
map.put(ZoneGetter.KEY_DISPLAY_LABEL, displayName);
map.put(ZoneGetter.KEY_GMT, gmtOffsetText.toString());
map.put(ZoneGetter.KEY_OFFSET_LABEL, gmtOffsetText);
map.put(ZoneGetter.KEY_OFFSET, offsetMillis);
return map;
}
}

View File

@@ -1,52 +0,0 @@
/*
* 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 com.android.settings.testutils.shadow;
import android.icu.util.TimeZone;
import com.android.settingslib.datetime.ZoneGetter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Implements(ZoneGetter.ZoneGetterData.class)
public class ShadowZoneGetterData {
private static final Map<String, List<String>> TIME_ZONE_LOOKUP = new HashMap<>();
static {
TIME_ZONE_LOOKUP.put("FR", Collections.singletonList(
TimeZone.getTimeZone("Europe/Paris", TimeZone.TIMEZONE_JDK).getID()));
TIME_ZONE_LOOKUP.put("ML", Collections.singletonList(
TimeZone.getTimeZone("Europe/Amsterdam", TimeZone.TIMEZONE_JDK).getID()));
TIME_ZONE_LOOKUP.put("US", Arrays.asList(
TimeZone.getTimeZone("America/New_York", TimeZone.TIMEZONE_JDK).getID()));
TIME_ZONE_LOOKUP.put("JP", Collections.singletonList(
TimeZone.getTimeZone("Asia/Tokyo", TimeZone.TIMEZONE_JDK).getID()));
}
@Implementation
public List<String> lookupTimeZoneIdsByCountry(String country) {
return TIME_ZONE_LOOKUP.get(country);
}
}