release-request-07e0701a-6024-4964-a0bf-f87d472b7ee2-for-git_pi-release-4329913 snap-temp-L73100000101564133
Change-Id: I3656f11760ca4605840471a224fed4e6eb689da3
This commit is contained in:
@@ -1934,6 +1934,32 @@
|
||||
android:value="true" />
|
||||
</activity>
|
||||
|
||||
<activity android:name="Settings$DevelopmentSettingsDashboardActivity"
|
||||
android:label="@string/development_settings_title"
|
||||
android:icon="@drawable/ic_settings_development"
|
||||
android:taskAffinity="com.android.settings"
|
||||
android:parentActivityName="Settings">
|
||||
|
||||
<!-- Enable when deleting DevelopmentSettingsActivity
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
|
||||
<action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
-->
|
||||
<intent-filter android:priority="50">
|
||||
<action android:name="com.android.settings.action.SETTINGS" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.system" />
|
||||
<meta-data android:name="com.android.settings.summary"
|
||||
android:resource="@string/summary_empty"/>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.development.DevelopmentSettingsDashboardFragment" />
|
||||
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
|
||||
android:value="true" />
|
||||
</activity>
|
||||
|
||||
<!-- The opposite of DevelopmentSettingsActivity, it's no-op and only enabled when the real
|
||||
activity is disabled to be CTS compliant. -->
|
||||
<activity
|
||||
|
||||
@@ -138,10 +138,12 @@
|
||||
</LinearLayout>
|
||||
|
||||
<!-- right side: lock pattern -->
|
||||
<FrameLayout
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
style="@style/LockPatternContainerStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.0">
|
||||
android:layout_weight="1.0"
|
||||
android:paddingStart="0dp">
|
||||
|
||||
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
|
||||
android:layout_width="match_parent"
|
||||
@@ -149,7 +151,7 @@
|
||||
android:layout_gravity="center"
|
||||
android:background="@color/lock_pattern_background" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
|
||||
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
|
||||
|
||||
|
||||
@@ -96,10 +96,12 @@
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<FrameLayout
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
style="@style/LockPatternContainerStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
android:paddingStart="0dp">
|
||||
|
||||
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
|
||||
android:layout_width="match_parent"
|
||||
@@ -107,7 +109,7 @@
|
||||
android:layout_gravity="center"
|
||||
android:background="@color/lock_pattern_background" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
|
||||
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
|
||||
</com.android.setupwizardlib.GlifLayout>
|
||||
|
||||
@@ -64,19 +64,31 @@
|
||||
android:gravity="center"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingRight="0dp">
|
||||
|
||||
<TextView android:id="@+id/headerText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minLines="2"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="?attr/suwMarginSides"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1" />
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
style="@style/LockPatternContainerStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.android.internal.widget.LockPatternView
|
||||
android:id="@+id/lockPattern"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -61,14 +61,23 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
android:gravity="center"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingRight="0dp">
|
||||
|
||||
<com.android.internal.widget.LockPatternView
|
||||
android:id="@+id/lockPattern"
|
||||
android:layout_width="match_parent"
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
style="@style/LockPatternContainerStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="4"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.android.internal.widget.LockPatternView
|
||||
android:id="@+id/lockPattern"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.ConfirmDeviceCredentialsErrorText"
|
||||
@@ -77,9 +86,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginHorizontal="?attr/suwMarginSides"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:gravity="center_vertical"/>
|
||||
|
||||
<ImageView
|
||||
@@ -87,6 +95,7 @@
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="?attr/suwMarginSides"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:contentDescription="@string/confirm_fingerprint_icon_content_description"
|
||||
android:visibility="gone"/>
|
||||
|
||||
@@ -4630,6 +4630,12 @@
|
||||
<string name="background_activity_summary_off">App\'s background activity is limited when not in use</string>
|
||||
<!-- Summary for the background activity when it is disabled [CHAR_LIMIT=120] -->
|
||||
<string name="background_activity_summary_disabled">App not allowed to run in background</string>
|
||||
<!-- TODO: Pending UX review. Summary for the background activity when it is whitlisted [CHAR_LIMIT=120] -->
|
||||
<string name="background_activity_summary_whitelisted">App can not be optimized for battery use</string>
|
||||
<!-- TODO: Pending UX review. Title for the warning dialog to show to the user when limiting background activity for an app -->
|
||||
<string name="background_activity_warning_dialog_title">Limit background activity?</string>
|
||||
<!-- TODO: Pending UX review. Text for the warning dialog to show to the user when limiting background activity for an app -->
|
||||
<string name="background_activity_warning_dialog_text">If you limit background activity for an app, it may misbehave</string>
|
||||
|
||||
<!-- Title for the screen usage in power use UI [CHAR_LIMIT=60] -->
|
||||
<string name="device_screen_usage">Screen usage since full charge</string>
|
||||
|
||||
@@ -427,6 +427,16 @@
|
||||
|
||||
<style name="DreamStartButton" parent="android:Widget.Material.Button" />
|
||||
|
||||
<style name="LockPatternContainerStyle">
|
||||
<item name="android:maxHeight">400dp</item>
|
||||
<item name="android:maxWidth">420dp</item>
|
||||
<item name="android:minHeight">0dp</item>
|
||||
<item name="android:minWidth">0dp</item>
|
||||
<item name="android:paddingBottom">0dp</item>
|
||||
<item name="android:paddingHorizontal">44dp</item>
|
||||
<item name="android:paddingTop">0dp</item>
|
||||
</style>
|
||||
|
||||
<style name="LockPatternStyle">
|
||||
<item name="*android:regularColor">@color/lock_pattern_view_regular_color</item>
|
||||
<item name="*android:successColor">@color/lock_pattern_view_success_color</item>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.FeatureFlagUtils;
|
||||
|
||||
import com.android.settings.applications.AppOpsSummary;
|
||||
import com.android.settings.enterprise.EnterprisePrivacySettings;
|
||||
@@ -70,7 +71,17 @@ public class Settings extends SettingsActivity {
|
||||
}
|
||||
public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ }
|
||||
public static class StorageUseActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
/**
|
||||
* @deprecated in favor of {@link DevelopmentSettingsDashboardActivity}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class DevelopmentSettingsDashboardActivity extends SettingsActivity {
|
||||
public static final boolean isEnabled() {
|
||||
return FeatureFlagUtils.isEnabled("dev_option_v2");
|
||||
}
|
||||
}
|
||||
public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class CaptioningSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class AccessibilityInversionSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.settings.Settings.WifiSettingsActivity;
|
||||
import com.android.settings.backup.BackupSettingsActivity;
|
||||
@@ -58,7 +59,6 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.core.instrumentation.SharedPreferencesLogger;
|
||||
import com.android.settings.dashboard.DashboardFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardSummary;
|
||||
import com.android.settings.development.DevelopmentSettings;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.SearchActivity;
|
||||
import com.android.settings.wfd.WifiDisplaySettings;
|
||||
@@ -66,6 +66,7 @@ import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.SettingsDrawerActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -831,9 +832,16 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
|
||||
final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
|
||||
&& !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
|
||||
final boolean useDevOptionV2 = Settings.DevelopmentSettingsDashboardActivity.isEnabled();
|
||||
// Enable old Dev option if v2 is disabled
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.DevelopmentSettingsActivity.class.getName()),
|
||||
showDev, isAdmin)
|
||||
showDev && !useDevOptionV2, isAdmin)
|
||||
|| somethingChanged;
|
||||
// Enable new Dev option if v2 is enable
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.DevelopmentSettingsDashboardActivity.class.getName()),
|
||||
showDev && useDevOptionV2, isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
// Enable/disable backup settings depending on whether the user is admin.
|
||||
|
||||
@@ -66,6 +66,7 @@ import com.android.settings.datausage.DataUsageList;
|
||||
import com.android.settings.datausage.DataUsageSummary;
|
||||
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
|
||||
import com.android.settings.development.DevelopmentSettings;
|
||||
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
|
||||
import com.android.settings.deviceinfo.ImeiInformation;
|
||||
import com.android.settings.deviceinfo.PrivateVolumeForget;
|
||||
import com.android.settings.deviceinfo.PrivateVolumeSettings;
|
||||
@@ -177,6 +178,7 @@ public class SettingsGateway {
|
||||
PrivateVolumeSettings.class.getName(),
|
||||
PublicVolumeSettings.class.getName(),
|
||||
DevelopmentSettings.class.getName(),
|
||||
DevelopmentSettingsDashboardFragment.class.getName(),
|
||||
AndroidBeam.class.getName(),
|
||||
WifiDisplaySettings.class.getName(),
|
||||
PowerUsageSummary.class.getName(),
|
||||
|
||||
@@ -20,12 +20,14 @@ import android.util.ArrayMap;
|
||||
|
||||
import com.android.settings.DisplaySettings;
|
||||
import com.android.settings.SecuritySettings;
|
||||
import com.android.settings.Settings;
|
||||
import com.android.settings.accounts.AccountDetailDashboardFragment;
|
||||
import com.android.settings.accounts.UserAndAccountDashboardFragment;
|
||||
import com.android.settings.applications.AppAndNotificationDashboardFragment;
|
||||
import com.android.settings.applications.DefaultAppSettings;
|
||||
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
|
||||
import com.android.settings.development.DevelopmentSettings;
|
||||
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
|
||||
import com.android.settings.deviceinfo.StorageDashboardFragment;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.language.LanguageAndInputSettings;
|
||||
@@ -83,8 +85,13 @@ public class DashboardFragmentRegistry {
|
||||
SystemDashboardFragment.class.getName(), CategoryKey.CATEGORY_SYSTEM);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(LanguageAndInputSettings.class.getName(),
|
||||
CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
|
||||
CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
|
||||
if (Settings.DevelopmentSettingsDashboardActivity.isEnabled()) {
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettingsDashboardFragment.class.getName(),
|
||||
CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
|
||||
} else {
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
|
||||
CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
|
||||
}
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(ConfigureNotificationSettings.class.getName(),
|
||||
CategoryKey.CATEGORY_NOTIFICATIONS);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(LockscreenDashboardFragment.class.getName(),
|
||||
|
||||
@@ -110,7 +110,9 @@ import java.util.List;
|
||||
|
||||
/*
|
||||
* Displays preferences for application developers.
|
||||
* @deprecated in favor of {@link DevelopmentSettingsDashboardFragment}
|
||||
*/
|
||||
@Deprecated
|
||||
public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
|
||||
OnPreferenceChangeListener, SwitchBar.OnSwitchChangeListener, Indexable {
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment {
|
||||
|
||||
private static final String TAG = "DevSettingsDashboard";
|
||||
|
||||
private SwitchBar mSwitchBar;
|
||||
|
||||
public DevelopmentSettingsDashboardFragment() {
|
||||
super(UserManager.DISALLOW_DEBUGGING_FEATURES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DEVELOPMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHelpResource() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
Log.d(TAG, "Creating pref screen");
|
||||
return R.xml.development_prefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context);
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||
Context context, boolean enabled) {
|
||||
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.development_prefs;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context
|
||||
context) {
|
||||
return buildPreferenceControllers(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
|
||||
import com.android.settings.password.SetupChooseLockGeneric;
|
||||
import com.android.settings.password.SetupSkipDialog;
|
||||
import com.android.settings.password.StorageManagerWrapper;
|
||||
|
||||
public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
|
||||
private static final String KEY_LOCK_SCREEN_PRESENT = "wasLockScreenPresent";
|
||||
@@ -56,11 +57,14 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
|
||||
|
||||
@Override
|
||||
protected Intent getChooseLockIntent() {
|
||||
Intent intent = new Intent(this, SetupChooseLockGeneric.class)
|
||||
.putExtra(
|
||||
LockPatternUtils.PASSWORD_TYPE_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
|
||||
Intent intent = new Intent(this, SetupChooseLockGeneric.class);
|
||||
|
||||
if (StorageManagerWrapper.isFileEncryptedNativeOrEmulated()) {
|
||||
intent.putExtra(
|
||||
LockPatternUtils.PASSWORD_TYPE_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
|
||||
}
|
||||
SetupWizardUtils.copySetupExtras(getIntent(), intent);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,8 @@ import java.util.List;
|
||||
public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
ButtonActionDialogFragment.AppButtonsDialogListener,
|
||||
AnomalyDialogFragment.AnomalyDialogListener,
|
||||
LoaderManager.LoaderCallbacks<List<Anomaly>> {
|
||||
LoaderManager.LoaderCallbacks<List<Anomaly>>,
|
||||
BackgroundActivityPreferenceController.WarningConfirmationListener {
|
||||
|
||||
public static final String TAG = "AdvancedPowerUsageDetail";
|
||||
public static final String EXTRA_UID = "extra_uid";
|
||||
@@ -109,6 +110,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
@VisibleForTesting
|
||||
AnomalySummaryPreferenceController mAnomalySummaryPreferenceController;
|
||||
private AppButtonsPreferenceController mAppButtonsPreferenceController;
|
||||
private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;
|
||||
|
||||
private DevicePolicyManagerWrapper mDpm;
|
||||
private UserManager mUserManager;
|
||||
@@ -319,7 +321,9 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
final int uid = bundle.getInt(EXTRA_UID, 0);
|
||||
final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
|
||||
|
||||
controllers.add(new BackgroundActivityPreferenceController(context, uid));
|
||||
mBackgroundActivityPreferenceController = new BackgroundActivityPreferenceController(
|
||||
context, this, uid, packageName);
|
||||
controllers.add(mBackgroundActivityPreferenceController);
|
||||
controllers.add(new BatteryOptimizationPreferenceController(
|
||||
(SettingsActivity) getActivity(), this, packageName));
|
||||
mAppButtonsPreferenceController = new AppButtonsPreferenceController(
|
||||
@@ -364,4 +368,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
public void onLoaderReset(Loader<List<Anomaly>> loader) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLimitBackgroundActivity() {
|
||||
mBackgroundActivityPreferenceController.setUnchecked(
|
||||
findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,17 @@
|
||||
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.Dialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
@@ -29,6 +34,7 @@ import android.util.Log;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -45,54 +51,72 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
private final PackageManager mPackageManager;
|
||||
private final AppOpsManager mAppOpsManager;
|
||||
private final UserManager mUserManager;
|
||||
private final String[] mPackages;
|
||||
private final int mUid;
|
||||
@VisibleForTesting
|
||||
DevicePolicyManagerWrapper mDpm;
|
||||
|
||||
private Fragment mFragment;
|
||||
private String mTargetPackage;
|
||||
private boolean mIsPreOApp;
|
||||
private PowerWhitelistBackend mPowerWhitelistBackend;
|
||||
|
||||
public BackgroundActivityPreferenceController(Context context, int uid) {
|
||||
public BackgroundActivityPreferenceController(Context context, Fragment fragment,
|
||||
int uid, String packageName) {
|
||||
this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BackgroundActivityPreferenceController(Context context, Fragment fragment,
|
||||
int uid, String packageName, PowerWhitelistBackend backend) {
|
||||
super(context);
|
||||
mPowerWhitelistBackend = backend;
|
||||
mPackageManager = context.getPackageManager();
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mDpm = new DevicePolicyManagerWrapperImpl(
|
||||
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
|
||||
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||
mUid = uid;
|
||||
mPackages = mPackageManager.getPackagesForUid(mUid);
|
||||
mFragment = fragment;
|
||||
mTargetPackage = packageName;
|
||||
mIsPreOApp = isLegacyApp(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
final int mode = mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
|
||||
final boolean whitelisted = mPowerWhitelistBackend.isWhitelisted(mTargetPackage);
|
||||
// Set checked or not before we may set it disabled
|
||||
if (mode != AppOpsManager.MODE_ERRORED) {
|
||||
final boolean checked = mode != AppOpsManager.MODE_IGNORED;
|
||||
final boolean checked = whitelisted || mode != AppOpsManager.MODE_IGNORED;
|
||||
((SwitchPreference) preference).setChecked(checked);
|
||||
}
|
||||
if (mode == AppOpsManager.MODE_ERRORED
|
||||
if (whitelisted || mode == AppOpsManager.MODE_ERRORED
|
||||
|| Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mTargetPackage)) {
|
||||
preference.setEnabled(false);
|
||||
} else {
|
||||
preference.setEnabled(true);
|
||||
}
|
||||
|
||||
updateSummary(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mPackages == null) {
|
||||
return false;
|
||||
}
|
||||
for (final String packageName : mPackages) {
|
||||
if (isLegacyApp(packageName)) {
|
||||
mTargetPackage = packageName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return mTargetPackage != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
/**
|
||||
* Called from the warning dialog, if the user decides to go ahead and disable background
|
||||
* activity for this package
|
||||
*/
|
||||
public void setUnchecked(Preference preference) {
|
||||
if (mIsPreOApp) {
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_IGNORED);
|
||||
}
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_IGNORED);
|
||||
((SwitchPreference) preference).setChecked(false);
|
||||
updateSummary(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,19 +126,23 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean switchOn = (Boolean) newValue;
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
switchOn ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
|
||||
|
||||
final boolean switchOn = (Boolean) newValue;
|
||||
if (!switchOn) {
|
||||
final WarningDialogFragment dialogFragment = new WarningDialogFragment();
|
||||
dialogFragment.setTargetFragment(mFragment, 0);
|
||||
dialogFragment.show(mFragment.getFragmentManager(), TAG);
|
||||
return false;
|
||||
}
|
||||
if (mIsPreOApp) {
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
}
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
updateSummary(preference);
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String getTargetPackage() {
|
||||
return mTargetPackage;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isLegacyApp(final String packageName) {
|
||||
try {
|
||||
@@ -131,8 +159,12 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
|
||||
@VisibleForTesting
|
||||
void updateSummary(Preference preference) {
|
||||
if (mPowerWhitelistBackend.isWhitelisted(mTargetPackage)) {
|
||||
preference.setSummary(R.string.background_activity_summary_whitelisted);
|
||||
return;
|
||||
}
|
||||
final int mode = mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
|
||||
|
||||
if (mode == AppOpsManager.MODE_ERRORED) {
|
||||
preference.setSummary(R.string.background_activity_summary_disabled);
|
||||
@@ -142,4 +174,37 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
: R.string.background_activity_summary_off);
|
||||
}
|
||||
}
|
||||
|
||||
interface WarningConfirmationListener {
|
||||
void onLimitBackgroundActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning dialog to show to the user as turning off background activity can lead to
|
||||
* apps misbehaving as their background task scheduling guarantees will no longer be honored.
|
||||
*/
|
||||
public static class WarningDialogFragment extends InstrumentedDialogFragment {
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
// TODO (b/65494831): add metric id
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final WarningConfirmationListener listener =
|
||||
(WarningConfirmationListener) getTargetFragment();
|
||||
return new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.background_activity_warning_dialog_title)
|
||||
.setMessage(R.string.background_activity_warning_dialog_text)
|
||||
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
listener.onLimitBackgroundActivity();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.dlg_cancel, null)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -47,6 +48,7 @@ public class BatteryEntry {
|
||||
public static final int MSG_REPORT_FULLY_DRAWN = 2;
|
||||
|
||||
private static final String TAG = "BatteryEntry";
|
||||
private static final String PACKAGE_SYSTEM = "android";
|
||||
|
||||
static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>();
|
||||
|
||||
@@ -268,9 +270,11 @@ public class BatteryEntry {
|
||||
if (sipper.mPackages == null) {
|
||||
sipper.mPackages = pm.getPackagesForUid(uid);
|
||||
}
|
||||
if (sipper.mPackages != null) {
|
||||
String[] packageLabels = new String[sipper.mPackages.length];
|
||||
System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
|
||||
|
||||
final String[] packages = extractPackagesFromSipper(sipper);
|
||||
if (packages != null) {
|
||||
String[] packageLabels = new String[packages.length];
|
||||
System.arraycopy(packages, 0, packageLabels, 0, packages.length);
|
||||
|
||||
// Convert package names to user-facing labels where possible
|
||||
IPackageManager ipm = AppGlobals.getPackageManager();
|
||||
@@ -289,7 +293,7 @@ public class BatteryEntry {
|
||||
packageLabels[i] = label.toString();
|
||||
}
|
||||
if (ai.icon != 0) {
|
||||
defaultPackageName = sipper.mPackages[i];
|
||||
defaultPackageName = packages[i];
|
||||
icon = ai.loadIcon(pm);
|
||||
break;
|
||||
}
|
||||
@@ -303,7 +307,7 @@ public class BatteryEntry {
|
||||
name = packageLabels[0];
|
||||
} else {
|
||||
// Look for an official name for this UID.
|
||||
for (String pkgName : sipper.mPackages) {
|
||||
for (String pkgName : packages) {
|
||||
try {
|
||||
final PackageInfo pi = ipm.getPackageInfo(pkgName, 0 /* no flags */, userId);
|
||||
if (pi == null) {
|
||||
@@ -349,4 +353,11 @@ public class BatteryEntry {
|
||||
sHandler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
|
||||
}
|
||||
}
|
||||
|
||||
String[] extractPackagesFromSipper(BatterySipper sipper) {
|
||||
// Only use system package if uid is system uid, so it could find a consistent name and icon
|
||||
return sipper.getUid() == Process.SYSTEM_UID
|
||||
? new String[]{PACKAGE_SYSTEM}
|
||||
: sipper.mPackages;
|
||||
}
|
||||
}
|
||||
|
||||
29
src/com/android/settings/password/StorageManagerWrapper.java
Normal file
29
src/com/android/settings/password/StorageManagerWrapper.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.password;
|
||||
|
||||
import android.os.storage.StorageManager;
|
||||
|
||||
/**
|
||||
* Wrapper class to allow Robolectric to shadow methods introduced in newer API
|
||||
*/
|
||||
public class StorageManagerWrapper {
|
||||
|
||||
public static boolean isFileEncryptedNativeOrEmulated() {
|
||||
return StorageManager.isFileEncryptedNativeOrEmulated();
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,10 @@ import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
@@ -61,17 +63,18 @@ public class ValidatedEditTextPreference extends CustomEditTextPreference {
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
super.onBindDialogView(view);
|
||||
if (mValidator != null) {
|
||||
final EditText editText = view.findViewById(android.R.id.edit);
|
||||
if (editText != null) {
|
||||
editText.removeTextChangedListener(mTextWatcher);
|
||||
if (mIsPassword) {
|
||||
editText.setInputType(
|
||||
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
editText.setMaxLines(1);
|
||||
}
|
||||
editText.addTextChangedListener(mTextWatcher);
|
||||
final EditText editText = view.findViewById(android.R.id.edit);
|
||||
if (editText != null && !TextUtils.isEmpty(editText.getText())) {
|
||||
editText.setSelection(editText.getText().length());
|
||||
}
|
||||
if (mValidator != null && editText != null) {
|
||||
editText.removeTextChangedListener(mTextWatcher);
|
||||
if (mIsPassword) {
|
||||
editText.setInputType(
|
||||
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
editText.setMaxLines(1);
|
||||
}
|
||||
editText.addTextChangedListener(mTextWatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
com.android.settings.development.DevelopmentSettingsDashboardFragment
|
||||
com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard
|
||||
|
||||
46
tests/robotests/src/android/util/FeatureFlagUtils.java
Normal file
46
tests/robotests/src/android/util/FeatureFlagUtils.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 android.util;
|
||||
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* This class is only needed to get around Robolectric issue.
|
||||
*/
|
||||
public class FeatureFlagUtils {
|
||||
public static final String FFLAG_PREFIX = "sys.fflag.";
|
||||
public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override.";
|
||||
|
||||
/**
|
||||
* Whether or not a flag is enabled.
|
||||
*
|
||||
* @param feature the flag name
|
||||
* @return true if the flag is enabled (either by default in system, or override by user)
|
||||
*/
|
||||
public static boolean isEnabled(String feature) {
|
||||
// Tries to get feature flag from system property.
|
||||
// Step 1: check if feature flag has any override. Flag name: sys.fflag.override.<feature>
|
||||
String value = SystemProperties.get(FFLAG_OVERRIDE_PREFIX + feature);
|
||||
if (!TextUtils.isEmpty(value)) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
// Step 2: check if feature flag has any default value. Flag name: sys.fflag.<feature>
|
||||
value = SystemProperties.get(FFLAG_PREFIX + feature);
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.development;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
||||
shadows = {
|
||||
SettingsShadowResources.class,
|
||||
SettingsShadowResources.SettingsShadowTheme.class
|
||||
})
|
||||
public class DevelopmentSettingsDashboardFragmentTest {
|
||||
|
||||
private DevelopmentSettingsDashboardFragment mDashboard;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mDashboard = new DevelopmentSettingsDashboardFragment();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveHelpResource() {
|
||||
assertThat(mDashboard.getHelpResource()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLogAsFeatureFlagPage() {
|
||||
assertThat(mDashboard.getMetricsCategory())
|
||||
.isEqualTo(MetricsProto.MetricsEvent.DEVELOPMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchIndex_shouldIndexFromPrefXml() {
|
||||
final List<SearchIndexableResource> index =
|
||||
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||
.getXmlResourcesToIndex(RuntimeEnvironment.application, true);
|
||||
|
||||
assertThat(index.size()).isEqualTo(1);
|
||||
assertThat(index.get(0).xmlResId).isEqualTo(R.xml.development_prefs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchIndex_pageDisabled_shouldAddAllKeysToNonIndexable() {
|
||||
final Context appContext = RuntimeEnvironment.application;
|
||||
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
|
||||
|
||||
final List<String> nonIndexableKeys =
|
||||
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||
.getNonIndexableKeys(appContext);
|
||||
|
||||
assertThat(nonIndexableKeys).contains("development_prefs_screen");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
|
||||
final Context appContext = RuntimeEnvironment.application;
|
||||
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
|
||||
|
||||
final List<String> nonIndexableKeys =
|
||||
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||
.getNonIndexableKeys(appContext);
|
||||
|
||||
assertThat(nonIndexableKeys).doesNotContain("development_prefs_screen");
|
||||
}
|
||||
}
|
||||
@@ -23,28 +23,38 @@ import static org.robolectric.RuntimeEnvironment.application;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.fingerprint.SetupFingerprintEnrollIntroductionTest
|
||||
.ShadowStorageManagerWrapper;
|
||||
import com.android.settings.password.SetupChooseLockGeneric.SetupChooseLockGenericFragment;
|
||||
import com.android.settings.password.SetupSkipDialog;
|
||||
import com.android.settings.password.StorageManagerWrapper;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
|
||||
import com.android.settings.testutils.shadow.ShadowFingerprintManager;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadows.ShadowActivity;
|
||||
import org.robolectric.shadows.ShadowActivity.IntentForResult;
|
||||
import org.robolectric.shadows.ShadowKeyguardManager;
|
||||
import org.robolectric.util.ActivityController;
|
||||
|
||||
@@ -54,7 +64,9 @@ import org.robolectric.util.ActivityController;
|
||||
sdk = TestConfig.SDK_VERSION,
|
||||
shadows = {
|
||||
ShadowEventLogWriter.class,
|
||||
ShadowFingerprintManager.class,
|
||||
ShadowLockPatternUtils.class,
|
||||
ShadowStorageManagerWrapper.class,
|
||||
ShadowUserManager.class
|
||||
})
|
||||
public class SetupFingerprintEnrollIntroductionTest {
|
||||
@@ -68,12 +80,22 @@ public class SetupFingerprintEnrollIntroductionTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
RuntimeEnvironment.getRobolectricPackageManager()
|
||||
.setSystemFeature(PackageManager.FEATURE_FINGERPRINT, true);
|
||||
ShadowFingerprintManager.addToServiceMap();
|
||||
|
||||
final Intent intent = new Intent();
|
||||
mController = Robolectric.buildActivity(SetupFingerprintEnrollIntroduction.class, intent);
|
||||
|
||||
ShadowUserManager.getShadow().setUserInfo(0, mUserInfo);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowStorageManagerWrapper.reset();
|
||||
ShadowFingerprintManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyguardNotSecure_shouldFinishWithSetupSkipDialogResultSkip() {
|
||||
getShadowKeyguardManager().setIsKeyguardSecure(false);
|
||||
@@ -188,8 +210,41 @@ public class SetupFingerprintEnrollIntroductionTest {
|
||||
assertThat(Shadows.shadowOf(activity).getResultIntent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockPattern() {
|
||||
ShadowStorageManagerWrapper.sIsFileEncrypted = false;
|
||||
|
||||
mController.create().postCreate(null).resume();
|
||||
|
||||
SetupFingerprintEnrollIntroduction activity = mController.get();
|
||||
|
||||
final Button nextButton = activity.findViewById(R.id.fingerprint_next_button);
|
||||
nextButton.performClick();
|
||||
|
||||
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
|
||||
IntentForResult startedActivity = shadowActivity.getNextStartedActivityForResult();
|
||||
assertThat(startedActivity).isNotNull();
|
||||
assertThat(startedActivity.intent.hasExtra(
|
||||
SetupChooseLockGenericFragment.EXTRA_PASSWORD_QUALITY)).isFalse();
|
||||
}
|
||||
|
||||
|
||||
private ShadowKeyguardManager getShadowKeyguardManager() {
|
||||
return Shadows.shadowOf(application.getSystemService(KeyguardManager.class));
|
||||
}
|
||||
|
||||
@Implements(StorageManagerWrapper.class)
|
||||
public static class ShadowStorageManagerWrapper {
|
||||
|
||||
private static boolean sIsFileEncrypted = true;
|
||||
|
||||
public static void reset() {
|
||||
sIsFileEncrypted = true;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static boolean isFileEncryptedNativeOrEmulated() {
|
||||
return sIsFileEncrypted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,25 @@
|
||||
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.UserManager;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
@@ -38,22 +49,17 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.robolectric.shadows.ShadowAlertDialog;
|
||||
import org.robolectric.shadows.ShadowDialog;
|
||||
import org.robolectric.util.FragmentTestUtil;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class BackgroundActivityPreferenceControllerTest {
|
||||
private static final int UID_NORMAL = 1234;
|
||||
private static final int UID_SPECIAL = 2345;
|
||||
private static final int UID_LOW_SDK = 1234;
|
||||
private static final int UID_HIGH_SDK = 3456;
|
||||
private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
|
||||
private static final String LOW_SDK_PACKAGE = "com.android.package.low";
|
||||
private static final String[] PACKAGES_NORMAL = {LOW_SDK_PACKAGE};
|
||||
private static final String[] PACKAGES_SPECIAL = {HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE};
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
@@ -71,6 +77,10 @@ public class BackgroundActivityPreferenceControllerTest {
|
||||
private DevicePolicyManager mDevicePolicyManager;
|
||||
@Mock
|
||||
private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
|
||||
@Mock
|
||||
private AdvancedPowerUsageDetail mFragment;
|
||||
@Mock
|
||||
private PowerWhitelistBackend mPowerWhitelistBackend;
|
||||
private BackgroundActivityPreferenceController mController;
|
||||
private SwitchPreference mPreference;
|
||||
private Context mShadowContext;
|
||||
@@ -85,19 +95,19 @@ public class BackgroundActivityPreferenceControllerTest {
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
|
||||
mDevicePolicyManager);
|
||||
when(mPackageManager.getPackagesForUid(UID_NORMAL)).thenReturn(PACKAGES_NORMAL);
|
||||
when(mPackageManager.getPackagesForUid(UID_SPECIAL)).thenReturn(PACKAGES_SPECIAL);
|
||||
|
||||
when(mPackageManager.getApplicationInfo(HIGH_SDK_PACKAGE, PackageManager.GET_META_DATA))
|
||||
.thenReturn(mHighApplicationInfo);
|
||||
when(mPackageManager.getApplicationInfo(LOW_SDK_PACKAGE, PackageManager.GET_META_DATA))
|
||||
.thenReturn(mLowApplicationInfo);
|
||||
|
||||
when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(false);
|
||||
mHighApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
|
||||
mLowApplicationInfo.targetSdkVersion = Build.VERSION_CODES.L;
|
||||
|
||||
mPreference = new SwitchPreference(mShadowContext);
|
||||
mController = spy(new BackgroundActivityPreferenceController(mContext, UID_NORMAL));
|
||||
mController.isAvailable();
|
||||
mController = spy(new BackgroundActivityPreferenceController(
|
||||
mContext, mFragment, UID_LOW_SDK, LOW_SDK_PACKAGE, mPowerWhitelistBackend));
|
||||
mController.mDpm = mDevicePolicyManagerWrapper;
|
||||
}
|
||||
|
||||
@@ -105,49 +115,66 @@ public class BackgroundActivityPreferenceControllerTest {
|
||||
public void testOnPreferenceChange_TurnOnCheck_MethodInvoked() {
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL,
|
||||
mController.getTargetPackage(), AppOpsManager.MODE_ALLOWED);
|
||||
verify(mController).updateSummary(mPreference);
|
||||
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
|
||||
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
assertThat(mPreference.getSummary())
|
||||
.isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPreferenceChange_TurnOffCheck_MethodInvoked() {
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
|
||||
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL,
|
||||
mController.getTargetPackage(), AppOpsManager.MODE_IGNORED);
|
||||
verify(mController).updateSummary(mPreference);
|
||||
public void testOnPreferenceChange_TurnOnCheckHighSDK_MethodInvoked() {
|
||||
mController = new BackgroundActivityPreferenceController(mContext, mFragment, UID_HIGH_SDK,
|
||||
HIGH_SDK_PACKAGE, mPowerWhitelistBackend);
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_HIGH_SDK,
|
||||
HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
|
||||
verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_HIGH_SDK,
|
||||
HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
|
||||
assertThat(mPreference.getSummary())
|
||||
.isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_CheckOn_SetCheckedTrue() {
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_DEFAULT);
|
||||
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
verify(mController).updateSummary(mPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_CheckOff_SetCheckedFalse() {
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_IGNORED);
|
||||
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
verify(mController).updateSummary(mPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_whitelisted() {
|
||||
when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(true);
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.getSummary()).isEqualTo(
|
||||
mShadowContext.getText(R.string.background_activity_summary_whitelisted));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateSummary_modeError_showSummaryDisabled() {
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_ERRORED);
|
||||
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ERRORED);
|
||||
final CharSequence expectedSummary = mShadowContext.getText(
|
||||
R.string.background_activity_summary_disabled);
|
||||
mController.updateSummary(mPreference);
|
||||
@@ -157,9 +184,8 @@ public class BackgroundActivityPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void testUpdateSummary_modeDefault_showSummaryOn() {
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_DEFAULT);
|
||||
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_DEFAULT);
|
||||
final CharSequence expectedSummary = mShadowContext.getText(
|
||||
R.string.background_activity_summary_on);
|
||||
|
||||
@@ -170,9 +196,8 @@ public class BackgroundActivityPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void testUpdateSummary_modeIgnored_showSummaryOff() {
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_IGNORED);
|
||||
when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
|
||||
LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
|
||||
final CharSequence expectedSummary = mShadowContext.getText(
|
||||
R.string.background_activity_summary_off);
|
||||
|
||||
@@ -182,31 +207,30 @@ public class BackgroundActivityPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPackageAvailable_SdkLowerThanO_ReturnTrue() {
|
||||
public void testIsLegacyApp_SdkLowerThanO_ReturnTrue() {
|
||||
assertThat(mController.isLegacyApp(LOW_SDK_PACKAGE)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPackageAvailable_SdkLargerOrEqualThanO_ReturnFalse() {
|
||||
public void testIsLegacyApp_SdkLargerOrEqualThanO_ReturnFalse() {
|
||||
assertThat(mController.isLegacyApp(HIGH_SDK_PACKAGE)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiplePackages_ReturnStatusForTargetPackage() {
|
||||
mController = new BackgroundActivityPreferenceController(mContext, UID_SPECIAL);
|
||||
mController.mDpm = mDevicePolicyManagerWrapper;
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, LOW_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_ALLOWED);
|
||||
when(mAppOpsManager
|
||||
.checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, HIGH_SDK_PACKAGE))
|
||||
.thenReturn(AppOpsManager.MODE_IGNORED);
|
||||
public void testIsAvailable_ReturnTrue() {
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
final boolean available = mController.isAvailable();
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(available).isTrue();
|
||||
// Should get status from LOW_SDK_PACKAGE
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
@Test
|
||||
public void testWarningDialog() {
|
||||
BackgroundActivityPreferenceController.WarningDialogFragment dialogFragment =
|
||||
new BackgroundActivityPreferenceController.WarningDialogFragment();
|
||||
dialogFragment.setTargetFragment(mFragment, 0);
|
||||
FragmentTestUtil.startFragment(dialogFragment);
|
||||
final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
|
||||
ShadowAlertDialog shadowDialog = shadowOf(dialog);
|
||||
final Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
shadowDialog.clickOn(okButton.getId());
|
||||
verify(mFragment).onLimitBackgroundActivity();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.internal.os.BatterySipper;
|
||||
@@ -46,9 +47,12 @@ import static org.mockito.Mockito.when;
|
||||
public class BatteryEntryTest {
|
||||
|
||||
private static final int APP_UID = 123;
|
||||
private static final int SYSTEM_UID = Process.SYSTEM_UID;
|
||||
private static final String APP_DEFAULT_PACKAGE_NAME = "com.android.test";
|
||||
private static final String APP_LABEL = "Test App Name";
|
||||
private static final String HIGH_DRAIN_PACKAGE = "com.android.test.screen";
|
||||
private static final String ANDROID_PACKAGE = "android";
|
||||
private static final String[] SYSTEM_PACKAGES = {HIGH_DRAIN_PACKAGE, ANDROID_PACKAGE};
|
||||
|
||||
@Rule public MockitoRule mocks = MockitoJUnit.rule();
|
||||
|
||||
@@ -84,6 +88,18 @@ public class BatteryEntryTest {
|
||||
return sipper;
|
||||
}
|
||||
|
||||
private BatteryEntry createBatteryEntryForSystem() {
|
||||
return new BatteryEntry(mockContext, mockHandler, mockUserManager, createSipperForSystem());
|
||||
}
|
||||
|
||||
private BatterySipper createSipperForSystem() {
|
||||
BatterySipper sipper =
|
||||
new BatterySipper(DrainType.APP, new FakeUid(SYSTEM_UID), 0 /* power use */);
|
||||
sipper.packageWithHighestDrain = HIGH_DRAIN_PACKAGE;
|
||||
sipper.mPackages = SYSTEM_PACKAGES;
|
||||
return sipper;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void batteryEntryForApp_shouldSetDefaultPackageNameAndLabel() throws Exception {
|
||||
BatteryEntry entry = createBatteryEntryForApp();
|
||||
@@ -118,7 +134,22 @@ public class BatteryEntryTest {
|
||||
new String[]{APP_DEFAULT_PACKAGE_NAME, "package2", "package3"});
|
||||
|
||||
BatteryEntry entry = createBatteryEntryForApp();
|
||||
|
||||
|
||||
assertThat(entry.getLabel()).isEqualTo(HIGH_DRAIN_PACKAGE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractPackageFromSipper_systemSipper_returnSystemPackage() {
|
||||
BatteryEntry entry = createBatteryEntryForSystem();
|
||||
|
||||
assertThat(entry.extractPackagesFromSipper(entry.sipper)).isEqualTo(
|
||||
new String[]{ANDROID_PACKAGE});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractPackageFromSipper_normalSipper_returnDefaultPakcage() {
|
||||
BatteryEntry entry = createBatteryEntryForApp();
|
||||
|
||||
assertThat(entry.extractPackagesFromSipper(entry.sipper)).isEqualTo(entry.sipper.mPackages);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.Resetter;
|
||||
import org.robolectric.internal.ShadowExtractor;
|
||||
import org.robolectric.shadows.ShadowContextImpl;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@Implements(FingerprintManager.class)
|
||||
public class ShadowFingerprintManager {
|
||||
|
||||
private static Map<String, String> getSystemServiceMap() {
|
||||
return ReflectionHelpers.getStaticField(ShadowContextImpl.class, "SYSTEM_SERVICE_MAP");
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this in @Before of a test to add FingerprintManager to Robolectric's system service
|
||||
* map. Otherwise getSystemService(FINGERPRINT_SERVICE) will return null.
|
||||
*/
|
||||
public static void addToServiceMap() {
|
||||
getSystemServiceMap().put(Context.FINGERPRINT_SERVICE, FingerprintManager.class.getName());
|
||||
}
|
||||
|
||||
@Resetter
|
||||
public static void reset() {
|
||||
getSystemServiceMap().remove(Context.FINGERPRINT_SERVICE);
|
||||
}
|
||||
|
||||
public boolean hardwareDetected = true;
|
||||
|
||||
@NonNull
|
||||
private List<Fingerprint> mFingerprints = Collections.emptyList();
|
||||
|
||||
@Implementation
|
||||
public boolean isHardwareDetected() {
|
||||
return hardwareDetected;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean hasEnrolledFingerprints() {
|
||||
return !mFingerprints.isEmpty();
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public List<Fingerprint> getEnrolledFingerprints() {
|
||||
return mFingerprints;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public 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) ShadowExtractor.extract(
|
||||
RuntimeEnvironment.application.getSystemService(FingerprintManager.class));
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,10 @@ import org.robolectric.annotation.Config;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@@ -58,10 +59,36 @@ public class ValidatedEditTextPreferenceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindDialogView_noTextWatcher_shouldDoNothing() {
|
||||
public void bindDialogView_nullEditText_shouldNotCrash() {
|
||||
when(mView.findViewById(android.R.id.edit)).thenReturn(null);
|
||||
// should not crash trying to get the EditText text
|
||||
mPreference.onBindDialogView(mView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindDialogView_emptyEditText_shouldNotSetSelection() {
|
||||
final String testText = "";
|
||||
final EditText editText = spy(new EditText(RuntimeEnvironment.application));
|
||||
editText.setText(testText);
|
||||
when(mView.findViewById(android.R.id.edit)).thenReturn(editText);
|
||||
|
||||
mPreference.onBindDialogView(mView);
|
||||
|
||||
verifyZeroInteractions(mView);
|
||||
// no need to setSelection if text was empty
|
||||
verify(editText, never()).setSelection(anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindDialogView_nonemptyEditText_shouldSetSelection() {
|
||||
final String testText = "whatever";
|
||||
final EditText editText = spy(new EditText(RuntimeEnvironment.application));
|
||||
editText.setText(testText);
|
||||
when(mView.findViewById(android.R.id.edit)).thenReturn(editText);
|
||||
|
||||
mPreference.onBindDialogView(mView);
|
||||
|
||||
// selection should be set to end of string
|
||||
verify(editText).setSelection(testText.length());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user