Unify action buttons to a common widget (part 1)

- Create a preference type to host action button preferences.
- Convert app battery usage page to use the new preference
- Convert wifi detail page to use the new preference

Change-Id: I60bc473986ab46f2897e2537eb0e013fa813a4fc
Fix: 63991885
Test: robotests
This commit is contained in:
Fan Zhang
2017-07-27 12:14:59 -07:00
parent 373a9c5cca
commit 2d28a4ceb4
11 changed files with 486 additions and 136 deletions

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:paddingTop="4dp"
android:paddingStart="68dp"
android:paddingEnd="8dp"
android:orientation="horizontal">
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1_positive"
style="@style/AppActionPrimaryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingEnd="8dp" />
<Button
android:id="@+id/button1_negative"
style="@style/ActionSecondaryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingStart="8dp" />
</FrameLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content">
<Button
android:id="@+id/button2_positive"
style="@style/AppActionPrimaryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingStart="8dp" />
<Button
android:id="@+id/button2_negative"
style="@style/ActionSecondaryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingStart="8dp" />
</FrameLayout>
</LinearLayout>

View File

@@ -423,6 +423,8 @@
<style name="AppActionPrimaryButton" parent="android:Widget.Material.Button.Colored"/>
<style name="ActionSecondaryButton" parent="android:Widget.Material.Button"/>
<style name="DreamStartButton" parent="android:Widget.Material.Button" />
<style name="LockPatternStyle">

View File

@@ -23,10 +23,8 @@
android:selectable="false"
android:order="-10000"/>
<com.android.settings.applications.LayoutPreference
<com.android.settings.widget.ActionButtonPreference
android:key="action_buttons"
android:layout="@layout/app_action_buttons"
android:selectable="false"
android:order="-9999"/>
<Preference

View File

@@ -26,9 +26,8 @@
<PreferenceCategory
android:key="general_details_category" >
<!-- Buttons -->
<com.android.settings.applications.LayoutPreference
<com.android.settings.widget.ActionButtonPreference
android:key="buttons"
android:layout="@layout/wifi_network_details_two_buttons_panel"
android:selectable="false" />
<com.android.settings.wifi.WifiDetailPreference

View File

@@ -37,23 +37,22 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import android.view.View;
import android.webkit.IWebViewUpdateService;
import android.widget.Button;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -79,7 +78,7 @@ import java.util.List;
//TODO(b/35810915): Make InstalledAppDetails use this controller
public class AppButtonsPreferenceController extends AbstractPreferenceController implements
PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause, OnDestroy,
View.OnClickListener, ApplicationsState.Callbacks {
ApplicationsState.Callbacks {
public static final String APP_CHG = "chg";
private static final String TAG = "AppButtonsPrefCtl";
@@ -95,13 +94,11 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
@VisibleForTesting
PackageInfo mPackageInfo;
@VisibleForTesting
Button mForceStopButton;
@VisibleForTesting
Button mUninstallButton;
@VisibleForTesting
String mPackageName;
@VisibleForTesting
boolean mDisableAfterUninstall = false;
@VisibleForTesting
ActionButtonPreference mButtonsPref;
private final int mRequestUninstall;
private final int mRequestRemoveDeviceAdmin;
@@ -115,7 +112,6 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin;
private MetricsFeatureProvider mMetricsFeatureProvider;
private LayoutPreference mButtonsPref;
private int mUserId;
private boolean mUpdatedSysApp = false;
private boolean mListeningToPackageRemove = false;
@@ -165,14 +161,14 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
mButtonsPref = (LayoutPreference) screen.findPreference(KEY_ACTION_BUTTONS);
mUninstallButton = (Button) mButtonsPref.findViewById(R.id.left_button);
mUninstallButton.setText(R.string.uninstall_text);
mForceStopButton = (Button) mButtonsPref.findViewById(R.id.right_button);
mForceStopButton.setText(R.string.force_stop);
mForceStopButton.setEnabled(false);
mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
.setButton1Text(R.string.uninstall_text)
.setButton2Text(R.string.force_stop)
.setButton1OnClickListener(new UninstallAndDisableButtonListener())
.setButton2OnClickListener(new ForceStopButtonListener())
.setButton1Positive(false)
.setButton2Positive(false)
.setButton2Enabled(false);
}
}
@@ -207,11 +203,11 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
mSession.release();
}
@Override
public void onClick(View v) {
final String packageName = mAppEntry.info.packageName;
final int id = v.getId();
if (id == R.id.left_button) {
private class UninstallAndDisableButtonListener implements View.OnClickListener {
@Override
public void onClick(View v) {
final String packageName = mAppEntry.info.packageName;
// Uninstall
if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
stopListeningToPackageRemove();
@@ -254,7 +250,13 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
} else {
uninstallPkg(packageName, false, false);
}
} else if (id == R.id.right_button) {
}
}
private class ForceStopButtonListener implements View.OnClickListener {
@Override
public void onClick(View v) {
// force stop
if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
@@ -363,7 +365,7 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
final boolean isBundled = (mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
boolean enabled = true;
if (isBundled) {
enabled = handleDisableable(mUninstallButton);
enabled = handleDisableable();
} else {
if ((mPackageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0
&& mUserManager.getUsers().size() >= 2) {
@@ -428,11 +430,7 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
enabled = false;
}
mUninstallButton.setEnabled(enabled);
if (enabled) {
// Register listener
mUninstallButton.setOnClickListener(this);
}
mButtonsPref.setButton1Enabled(enabled);
}
/**
@@ -477,12 +475,12 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
// User can't force stop device admin.
Log.w(TAG, "User can't force stop device admin");
updateForceStopButtonInner(false);
updateForceStopButtonInner(false /* enabled */);
} else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
// If the app isn't explicitly stopped, then always show the
// force stop button.
Log.w(TAG, "App is not explicitly stopped");
updateForceStopButtonInner(true);
updateForceStopButtonInner(true /* enabled */);
} else {
Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
Uri.fromParts("package", mAppEntry.info.packageName, null));
@@ -499,10 +497,9 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
@VisibleForTesting
void updateForceStopButtonInner(boolean enabled) {
if (mAppsControlDisallowedBySystem) {
mForceStopButton.setEnabled(false);
mButtonsPref.setButton2Enabled(false);
} else {
mForceStopButton.setEnabled(enabled);
mForceStopButton.setOnClickListener(this);
mButtonsPref.setButton2Enabled(enabled);
}
}
@@ -538,7 +535,7 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
}
@VisibleForTesting
boolean handleDisableable(Button button) {
boolean handleDisableable() {
boolean disableable = false;
// Try to prevent the user from bricking their phone
// by not allowing disabling of apps signed with the
@@ -546,12 +543,16 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
if (mHomePackages.contains(mAppEntry.info.packageName)
|| isSystemPackage(mActivity.getResources(), mPm, mPackageInfo)) {
// Disable button for core system applications.
button.setText(R.string.disable_text);
mButtonsPref.setButton1Text(R.string.disable_text)
.setButton1Positive(false);
} else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
button.setText(R.string.disable_text);
mButtonsPref.setButton1Text(R.string.disable_text)
.setButton1Positive(false);
disableable = true;
} else {
button.setText(R.string.enable_text);
mButtonsPref.setButton1Text(R.string.enable_text)
.setButton1Positive(true);
disableable = true;
}

View File

@@ -0,0 +1,186 @@
/*
* 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.widget;
import android.content.Context;
import android.support.annotation.StringRes;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import com.android.settings.R;
public class ActionButtonPreference extends Preference {
private final ButtonInfo mButton1Info = new ButtonInfo();
private final ButtonInfo mButton2Info = new ButtonInfo();
public ActionButtonPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public ActionButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public ActionButtonPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ActionButtonPreference(Context context) {
super(context);
init();
}
private void init() {
setLayoutResource(R.layout.two_action_buttons);
setSelectable(false);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.setDividerAllowedAbove(false);
holder.setDividerAllowedBelow(false);
mButton1Info.mPositiveButton = (Button) holder.findViewById(R.id.button1_positive);
mButton1Info.mNegativeButton = (Button) holder.findViewById(R.id.button1_negative);
mButton2Info.mPositiveButton = (Button) holder.findViewById(R.id.button2_positive);
mButton2Info.mNegativeButton = (Button) holder.findViewById(R.id.button2_negative);
mButton1Info.setUpButton();
mButton2Info.setUpButton();
}
public ActionButtonPreference setButton1Text(@StringRes int textResId) {
final String newText = getContext().getString(textResId);
if (!TextUtils.equals(newText, mButton1Info.mText)) {
mButton1Info.mText = newText;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton1Enabled(boolean isEnabled) {
if (isEnabled != mButton1Info.mIsEnabled) {
mButton1Info.mIsEnabled = isEnabled;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton2Text(@StringRes int textResId) {
final String newText = getContext().getString(textResId);
if (!TextUtils.equals(newText, mButton2Info.mText)) {
mButton2Info.mText = newText;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton2Enabled(boolean isEnabled) {
if (isEnabled != mButton2Info.mIsEnabled) {
mButton2Info.mIsEnabled = isEnabled;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton1OnClickListener(View.OnClickListener listener) {
if (listener != mButton1Info.mListener) {
mButton1Info.mListener = listener;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton2OnClickListener(View.OnClickListener listener) {
if (listener != mButton2Info.mListener) {
mButton2Info.mListener = listener;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton1Positive(boolean isPositive) {
if (isPositive != mButton1Info.mIsPositive) {
mButton1Info.mIsPositive = isPositive;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton2Positive(boolean isPositive) {
if (isPositive != mButton2Info.mIsPositive) {
mButton2Info.mIsPositive = isPositive;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton1Visible(boolean isPositive) {
if (isPositive != mButton1Info.mIsVisible) {
mButton1Info.mIsVisible = isPositive;
notifyChanged();
}
return this;
}
public ActionButtonPreference setButton2Visible(boolean isPositive) {
if (isPositive != mButton2Info.mIsVisible) {
mButton2Info.mIsVisible = isPositive;
notifyChanged();
}
return this;
}
static class ButtonInfo {
private Button mPositiveButton;
private Button mNegativeButton;
private CharSequence mText;
private View.OnClickListener mListener;
private boolean mIsPositive = true;
private boolean mIsEnabled = true;
private boolean mIsVisible = true;
void setUpButton() {
setUpButton(mPositiveButton);
setUpButton(mNegativeButton);
if (!mIsVisible) {
mPositiveButton.setVisibility(View.INVISIBLE);
mNegativeButton.setVisibility(View.INVISIBLE);
} else if (mIsPositive) {
mPositiveButton.setVisibility(View.VISIBLE);
mNegativeButton.setVisibility(View.INVISIBLE);
} else {
mPositiveButton.setVisibility(View.INVISIBLE);
mNegativeButton.setVisibility(View.VISIBLE);
}
}
private void setUpButton(Button button) {
button.setText(mText);
button.setOnClickListener(mListener);
button.setEnabled(mIsEnabled);
}
}
}

View File

@@ -58,6 +58,7 @@ import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.vpn2.ConnectivityManagerWrapper;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.WifiDetailPreference;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -127,10 +128,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
private final MetricsFeatureProvider mMetricsFeatureProvider;
// UI elements - in order of appearance
private LayoutPreference mButtonsPref;
private ActionButtonPreference mButtonsPref;
private EntityHeaderController mEntityHeaderController;
private Button mForgetButton;
private Button mSignInButton;
private WifiDetailPreference mSignalStrengthPref;
private WifiDetailPreference mLinkSpeedPref;
private WifiDetailPreference mFrequencyPref;
@@ -244,9 +243,13 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
setupEntityHeader(screen);
mButtonsPref = (LayoutPreference) screen.findPreference(KEY_BUTTONS_PREF);
mSignInButton = mButtonsPref.findViewById(R.id.signin_button);
mSignInButton.setOnClickListener(view -> signIntoNetwork());
mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_BUTTONS_PREF))
.setButton1Text(R.string.forget)
.setButton1Positive(false)
.setButton2Text(R.string.support_sign_in_button_text)
.setButton1OnClickListener(view -> forgetNetwork())
.setButton2Positive(true)
.setButton2OnClickListener(view -> signIntoNetwork());
mSignalStrengthPref =
(WifiDetailPreference) screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
@@ -264,8 +267,6 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
mSecurityPref.setDetailText(mAccessPoint.getSecurityString(false /* concise */));
mForgetButton = mButtonsPref.findViewById(R.id.forget_button);
mForgetButton.setOnClickListener(view -> forgetNetwork());
}
private void setupEntityHeader(PreferenceScreen screen) {
@@ -318,7 +319,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
}
// Update whether the forgot button should be displayed.
mForgetButton.setVisibility(canForgetNetwork() ? View.VISIBLE : View.INVISIBLE);
mButtonsPref.setButton1Visible(canForgetNetwork());
refreshNetworkState();
@@ -393,9 +394,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
}
private void updateIpLayerInfo() {
mSignInButton.setVisibility(canSignIntoNetwork() ? View.VISIBLE : View.INVISIBLE);
mButtonsPref.setVisible(mForgetButton.getVisibility() == View.VISIBLE
|| mSignInButton.getVisibility() == View.VISIBLE);
mButtonsPref.setButton2Visible(canSignIntoNetwork());
mButtonsPref.setVisible(canSignIntoNetwork() || canForgetNetwork());
if (mNetwork == null || mLinkProperties == null) {
mIpAddressPref.setVisible(false);

View File

@@ -17,11 +17,8 @@ package com.android.settings.deviceinfo.storage;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -44,7 +41,6 @@ import android.widget.LinearLayout;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.SubSettings;
import com.android.settings.TestConfig;
import com.android.settings.applications.ManageApplications;
@@ -52,6 +48,7 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.deviceinfo.PrivateVolumeSettings;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;

View File

@@ -17,7 +17,6 @@
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
@@ -40,13 +39,14 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.UserManager;
import android.widget.Button;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.TestConfig;
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -98,10 +98,8 @@ public class AppButtonsPreferenceControllerTest {
private Application mApplication;
@Mock
private PackageInfo mPackageInfo;
@Mock
private Button mUninstallButton;
@Mock
private Button mForceStopButton;
private ActionButtonPreference mButtonPrefs;
private Intent mUninstallIntent;
private AppButtonsPreferenceController mController;
@@ -129,8 +127,8 @@ public class AppButtonsPreferenceControllerTest {
mPackageInfo.packageName = PACKAGE_NAME;
mPackageInfo.applicationInfo = mAppInfo;
mController.mUninstallButton = mUninstallButton;
mController.mForceStopButton = mForceStopButton;
mButtonPrefs = ActionButtonPreferenceTest.createMock();
mController.mButtonsPref = mButtonPrefs;
mController.mPackageInfo = mPackageInfo;
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
@@ -155,7 +153,6 @@ public class AppButtonsPreferenceControllerTest {
assertThat(mController.mPackageInfo).isNotNull();
}
@Test
public void testRetrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException {
doReturn(null).when(mState).getEntry(eq(PACKAGE_NAME), anyInt());
@@ -182,13 +179,13 @@ public class AppButtonsPreferenceControllerTest {
@Test
public void testUpdateUninstallButton_isSystemApp_handleAsDisableableButton() {
doReturn(false).when(mController).handleDisableable(any());
doReturn(false).when(mController).handleDisableable();
mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
mController.updateUninstallButton();
verify(mController).handleDisableable(any());
verify(mUninstallButton).setEnabled(false);
verify(mController).handleDisableable();
verify(mButtonPrefs).setButton1Enabled(false);
}
@Test
@@ -219,14 +216,14 @@ public class AppButtonsPreferenceControllerTest {
@Test
public void testUpdateUninstallButton_isDeviceAdminApp_setButtonDisable() {
doReturn(true).when(mController).handleDisableable(any());
doReturn(true).when(mController).handleDisableable();
mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
doReturn(true).when(mDpm).packageHasActiveAdmins(anyString());
mController.updateUninstallButton();
verify(mController).handleDisableable(any());
verify(mUninstallButton).setEnabled(false);
verify(mController).handleDisableable();
verify(mButtonPrefs).setButton1Enabled(false);
}
@Test
@@ -235,7 +232,7 @@ public class AppButtonsPreferenceControllerTest {
mController.updateUninstallButton();
verify(mUninstallButton).setEnabled(false);
verify(mButtonPrefs).setButton1Enabled(false);
}
@Test
@@ -245,7 +242,7 @@ public class AppButtonsPreferenceControllerTest {
mController.updateUninstallButton();
verify(mUninstallButton).setEnabled(false);
verify(mButtonPrefs).setButton1Enabled(false);
}
@Test
@@ -254,7 +251,7 @@ public class AppButtonsPreferenceControllerTest {
mController.updateUninstallButton();
verify(mUninstallButton).setEnabled(false);
verify(mButtonPrefs).setButton1Enabled(false);
}
@Test
@@ -264,7 +261,7 @@ public class AppButtonsPreferenceControllerTest {
mController.updateUninstallButton();
verify(mUninstallButton).setEnabled(false);
verify(mButtonPrefs).setButton1Enabled(false);
}
@Test
@@ -312,11 +309,10 @@ public class AppButtonsPreferenceControllerTest {
public void testHandleDisableable_isHomeApp_notControllable() {
mController.mHomePackages.add(PACKAGE_NAME);
final boolean controllable = mController.handleDisableable(mUninstallButton);
final boolean controllable = mController.handleDisableable();
verify(mUninstallButton).setText(R.string.disable_text);
verify(mButtonPrefs).setButton1Text(R.string.disable_text);
assertThat(controllable).isFalse();
}
@Test
@@ -325,9 +321,9 @@ public class AppButtonsPreferenceControllerTest {
mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
doReturn(false).when(mController).isSystemPackage(any(), any(), any());
final boolean controllable = mController.handleDisableable(mUninstallButton);
final boolean controllable = mController.handleDisableable();
verify(mUninstallButton).setText(R.string.disable_text);
verify(mButtonPrefs).setButton1Text(R.string.disable_text);
assertThat(controllable).isTrue();
}
@@ -338,9 +334,9 @@ public class AppButtonsPreferenceControllerTest {
mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
doReturn(false).when(mController).isSystemPackage(any(), any(), any());
final boolean controllable = mController.handleDisableable(mUninstallButton);
final boolean controllable = mController.handleDisableable();
verify(mUninstallButton).setText(R.string.enable_text);
verify(mButtonPrefs).setButton1Text(R.string.enable_text);
assertThat(controllable).isTrue();
}
@@ -356,7 +352,7 @@ public class AppButtonsPreferenceControllerTest {
* The test fragment which implements
* {@link ButtonActionDialogFragment.AppButtonsDialogListener}
*/
private static class TestFragment extends Fragment implements
public static class TestFragment extends Fragment implements
ButtonActionDialogFragment.AppButtonsDialogListener {
@Override

View File

@@ -0,0 +1,139 @@
/*
* 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.widget;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.v7.preference.PreferenceViewHolder;
import android.view.View;
import android.widget.Button;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ActionButtonPreferenceTest {
private Context mContext;
private View mRootView;
private ActionButtonPreference mPref;
private PreferenceViewHolder mHolder;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mRootView = View.inflate(mContext, R.layout.two_action_buttons, null /* parent */);
mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
mPref = new ActionButtonPreference(mContext);
}
@Test
public void setVisibility_shouldUpdateButtonVisibility() {
mPref.setButton1Visible(false).setButton2Visible(false);
mPref.onBindViewHolder(mHolder);
assertThat(mRootView.findViewById(R.id.button1_positive).getVisibility())
.isEqualTo(View.INVISIBLE);
assertThat(mRootView.findViewById(R.id.button1_negative).getVisibility())
.isEqualTo(View.INVISIBLE);
assertThat(mRootView.findViewById(R.id.button2_positive).getVisibility())
.isEqualTo(View.INVISIBLE);
assertThat(mRootView.findViewById(R.id.button2_negative).getVisibility())
.isEqualTo(View.INVISIBLE);
mPref.setButton1Visible(true).setButton2Visible(true);
mPref.onBindViewHolder(mHolder);
assertThat(mRootView.findViewById(R.id.button1_positive).getVisibility())
.isEqualTo(View.VISIBLE);
assertThat(mRootView.findViewById(R.id.button1_negative).getVisibility())
.isEqualTo(View.INVISIBLE);
assertThat(mRootView.findViewById(R.id.button2_positive).getVisibility())
.isEqualTo(View.VISIBLE);
assertThat(mRootView.findViewById(R.id.button2_negative).getVisibility())
.isEqualTo(View.INVISIBLE);
}
@Test
public void setPositiveNegative_shouldHideOppositeButton() {
mPref.setButton1Positive(true).setButton2Positive(false);
mPref.onBindViewHolder(mHolder);
assertThat(mRootView.findViewById(R.id.button1_positive).getVisibility())
.isEqualTo(View.VISIBLE);
assertThat(mRootView.findViewById(R.id.button1_negative).getVisibility())
.isEqualTo(View.INVISIBLE);
assertThat(mRootView.findViewById(R.id.button2_positive).getVisibility())
.isEqualTo(View.INVISIBLE);
assertThat(mRootView.findViewById(R.id.button2_negative).getVisibility())
.isEqualTo(View.VISIBLE);
}
@Test
public void setEnabled_shouldEnableButton() {
mPref.setButton1Enabled(true).setButton2Enabled(false);
mPref.onBindViewHolder(mHolder);
assertThat(mRootView.findViewById(R.id.button1_positive).isEnabled()).isTrue();
assertThat(mRootView.findViewById(R.id.button1_negative).isEnabled()).isTrue();
assertThat(mRootView.findViewById(R.id.button2_positive).isEnabled()).isFalse();
assertThat(mRootView.findViewById(R.id.button2_negative).isEnabled()).isFalse();
}
@Test
public void setText() {
mPref.setButton1Text(R.string.settings_label);
mPref.onBindViewHolder(mHolder);
assertThat(((Button) mRootView.findViewById(R.id.button1_positive)).getText())
.isEqualTo(mContext.getText(R.string.settings_label));
assertThat(((Button) mRootView.findViewById(R.id.button1_negative)).getText())
.isEqualTo(mContext.getText(R.string.settings_label));
}
public static ActionButtonPreference createMock() {
final ActionButtonPreference pref = mock(ActionButtonPreference.class);
when(pref.setButton1Text(anyInt())).thenReturn(pref);
when(pref.setButton1Positive(anyBoolean())).thenReturn(pref);
when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
when(pref.setButton2Text(anyInt())).thenReturn(pref);
when(pref.setButton2Positive(anyBoolean())).thenReturn(pref);
when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
return pref;
}
}

View File

@@ -16,7 +16,6 @@
package com.android.settings.wifi.details;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
@@ -52,7 +51,6 @@ import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import com.android.internal.logging.nano.MetricsProto;
@@ -63,6 +61,8 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.vpn2.ConnectivityManagerWrapperImpl;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.WifiDetailPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -119,8 +119,7 @@ public class WifiDetailPreferenceControllerTest {
private LayoutPreference mockHeaderLayoutPreference;
@Mock private ImageView mockHeaderIcon;
@Mock private LayoutPreference mockButtonsPref;
@Mock private Button mockSignInButton;
@Mock private ActionButtonPreference mockButtonsPref;
@Mock private WifiDetailPreference mockSignalStrengthPref;
@Mock private WifiDetailPreference mockLinkSpeedPref;
@Mock private WifiDetailPreference mockFrequencyPref;
@@ -130,7 +129,6 @@ public class WifiDetailPreferenceControllerTest {
@Mock private WifiDetailPreference mockGatewayPref;
@Mock private WifiDetailPreference mockSubnetPref;
@Mock private WifiDetailPreference mockDnsPref;
@Mock private Button mockForgetButton;
@Mock private PreferenceCategory mockIpv6Category;
@Mock private WifiDetailPreference mockIpv6AddressesPref;
@@ -211,7 +209,9 @@ public class WifiDetailPreferenceControllerTest {
.thenReturn(mockNetworkInfo);
doNothing().when(mockConnectivityManagerWrapper).registerNetworkCallback(
nullable(NetworkRequest.class), mCallbackCaptor.capture(), nullable(Handler.class));
doNothing().when(mockForgetButton).setOnClickListener(mForgetClickListener.capture());
mockButtonsPref = ActionButtonPreferenceTest.createMock();
when(mockButtonsPref.setButton1OnClickListener(mForgetClickListener.capture()))
.thenReturn(mockButtonsPref);
when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED);
when(mockWifiInfo.getRssi()).thenReturn(RSSI);
@@ -256,10 +256,6 @@ public class WifiDetailPreferenceControllerTest {
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_BUTTONS_PREF))
.thenReturn(mockButtonsPref);
when(mockButtonsPref.findViewById(R.id.forget_button))
.thenReturn(mockForgetButton);
when(mockButtonsPref.findViewById(R.id.signin_button))
.thenReturn(mockSignInButton);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SIGNAL_STRENGTH_PREF))
.thenReturn(mockSignalStrengthPref);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_LINK_SPEED))
@@ -596,7 +592,7 @@ public class WifiDetailPreferenceControllerTest {
mController = newWifiDetailPreferenceController();
displayAndResume();
verify(mockForgetButton).setVisibility(View.INVISIBLE);
verify(mockButtonsPref).setButton1Visible(false);
}
@Test
@@ -606,14 +602,14 @@ public class WifiDetailPreferenceControllerTest {
displayAndResume();
verify(mockForgetButton).setVisibility(View.VISIBLE);
verify(mockButtonsPref).setButton1Visible(true);
}
@Test
public void canForgetNetwork_saved() {
displayAndResume();
verify(mockForgetButton).setVisibility(View.VISIBLE);
verify(mockButtonsPref).setButton1Visible(true);
}
@Test
@@ -716,23 +712,23 @@ public class WifiDetailPreferenceControllerTest {
@Test
public void captivePortal_shouldShowSignInButton() {
InOrder inOrder = inOrder(mockSignInButton);
InOrder inOrder = inOrder(mockButtonsPref);
displayAndResume();
inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
inOrder.verify(mockButtonsPref).setButton2Visible(false);
NetworkCapabilities nc = makeNetworkCapabilities();
updateNetworkCapabilities(nc);
inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
inOrder.verify(mockButtonsPref).setButton2Visible(false);
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
updateNetworkCapabilities(nc);
inOrder.verify(mockSignInButton).setVisibility(View.VISIBLE);
inOrder.verify(mockButtonsPref).setButton2Visible(true);
nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
updateNetworkCapabilities(nc);
inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
inOrder.verify(mockButtonsPref).setButton2Visible(false);
}
@Test
@@ -740,40 +736,10 @@ public class WifiDetailPreferenceControllerTest {
displayAndResume();
ArgumentCaptor<OnClickListener> captor = ArgumentCaptor.forClass(OnClickListener.class);
verify(mockSignInButton).setOnClickListener(captor.capture());
captor.getValue().onClick(mockSignInButton);
verify(mockButtonsPref).setButton2OnClickListener(captor.capture());
captor.getValue().onClick(null);
verify(mockConnectivityManagerWrapper).startCaptivePortalApp(mockNetwork);
verify(mockMetricsFeatureProvider)
.action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_SIGNIN);
}
@Test
public void signInButtonVisible_buttonPanelShouldBeVisible() {
when(mockSignInButton.getVisibility()).thenReturn(View.VISIBLE);
when(mockForgetButton.getVisibility()).thenReturn(View.INVISIBLE);
displayAndResume();
verify(mockButtonsPref).setVisible(true);
}
@Test
public void forgetButtonVisible_buttonPanelShouldBeVisible() {
when(mockSignInButton.getVisibility()).thenReturn(View.INVISIBLE);
when(mockForgetButton.getVisibility()).thenReturn(View.VISIBLE);
displayAndResume();
verify(mockButtonsPref).setVisible(true);
}
@Test
public void neitherButtonVisible_buttonPanelShouldBeInvisible() {
when(mockSignInButton.getVisibility()).thenReturn(View.INVISIBLE);
when(mockForgetButton.getVisibility()).thenReturn(View.INVISIBLE);
displayAndResume();
verify(mockButtonsPref).setVisible(false);
}
}