Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad3a7f40 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add switch bar to enable/disable dev settings in new page."

parents e71fa15f d77881f8
Loading
Loading
Loading
Loading
+61 −1
Original line number Diff line number Diff line
@@ -17,12 +17,16 @@
package com.android.settings.development;

import android.content.Context;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
import android.util.Log;
import android.widget.Switch;

import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
@@ -33,21 +37,67 @@ import com.android.settingslib.development.DevelopmentSettingsEnabler;
import java.util.Arrays;
import java.util.List;

public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment {
public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment
        implements SwitchBar.OnSwitchChangeListener {

    private static final String TAG = "DevSettingsDashboard";

    private boolean mIsAvailable = true;
    private SwitchBar mSwitchBar;
    private DevelopmentSwitchBarController mSwitchBarController;

    public DevelopmentSettingsDashboardFragment() {
        super(UserManager.DISALLOW_DEBUGGING_FEATURES);
    }

    @Override
    public void onActivityCreated(Bundle icicle) {
        super.onActivityCreated(icicle);
        // Apply page-level restrictions
        setIfOnlyAvailableForAdmins(true);
        if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) {
            // Block access to developer options if the user is not the owner, if user policy
            // restricts it, or if the device has not been provisioned
            mIsAvailable = false;
            // Show error message
            if (!isUiRestrictedByOnlyAdmin()) {
                getEmptyTextView().setText(R.string.development_settings_not_available);
            }
            getPreferenceScreen().removeAll();
            return;
        }
        // Set up master switch
        mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
        mSwitchBarController = new DevelopmentSwitchBarController(
                this /* DevelopmentSettings */, mSwitchBar, mIsAvailable, getLifecycle());
        mSwitchBar.show();
    }

    @Override
    public int getMetricsCategory() {
        return MetricsProto.MetricsEvent.DEVELOPMENT;
    }

    @Override
    public void onSwitchChanged(Switch switchView, boolean isChecked) {
        if (switchView != mSwitchBar.getSwitch()) {
            return;
        }
        final boolean developmentEnabledState =
                DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext());
        if (isChecked != developmentEnabledState) {
            if (isChecked) {
                EnableDevelopmentSettingWarningDialog.show(this /* host */);
            } else {
                // TODO: Reset dangerous options (move logic from DevelopmentSettings).
                // resetDangerousOptions();
                DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), false);
                // TODO: Refresh all prefs' enabled state (move logic from DevelopmentSettings).
                // setPrefsEnabledState(false);
            }
        }
    }

    @Override
    protected String getLogTag() {
        return TAG;
@@ -69,6 +119,16 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
        return buildPreferenceControllers(context);
    }

    void onEnableDevelopmentOptionsConfirmed() {
        DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(getContext(), true);
        // TODO: Refresh all prefs' enabled state (move logic from DevelopmentSettings).
    }

    void onEnableDevelopmentOptionsRejected() {
        // Reset the toggle
        mSwitchBar.setChecked(false);
    }

    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
        return null;
    }
+36 −2
Original line number Diff line number Diff line
@@ -22,18 +22,39 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.development.DevelopmentSettingsEnabler;

public class DevelopmentSwitchBarController implements LifecycleObserver, OnStart, OnStop {

    private final SwitchBar mSwitchBar;
    private final boolean mIsAvailable;
    private final DevelopmentSettings mSettings;
    private final DevelopmentSettingsDashboardFragment mNewSettings;

    /**
     * @deprecated in favor of the other constructor.
     */
    @Deprecated
    public DevelopmentSwitchBarController(DevelopmentSettings settings, SwitchBar switchBar,
            boolean isAvailable, Lifecycle lifecycle) {
        mSwitchBar = switchBar;
        mIsAvailable = isAvailable && !Utils.isMonkeyRunning();
        mSettings = settings;
        mNewSettings = null;

        if (mIsAvailable) {
            lifecycle.addObserver(this);
        } else {
            mSwitchBar.setEnabled(false);
        }
    }

    public DevelopmentSwitchBarController(DevelopmentSettingsDashboardFragment settings,
            SwitchBar switchBar, boolean isAvailable, Lifecycle lifecycle) {
        mSwitchBar = switchBar;
        mIsAvailable = isAvailable && !Utils.isMonkeyRunning();
        mSettings = null;
        mNewSettings = settings;

        if (mIsAvailable) {
            lifecycle.addObserver(this);
@@ -44,11 +65,24 @@ public class DevelopmentSwitchBarController implements LifecycleObserver, OnStar

    @Override
    public void onStart() {
        if (mSettings != null) {
            mSwitchBar.addOnSwitchChangeListener(mSettings);
        }
        if (mNewSettings != null) {
            final boolean developmentEnabledState = DevelopmentSettingsEnabler
                    .isDevelopmentSettingsEnabled(mNewSettings.getContext());
            mSwitchBar.setChecked(developmentEnabledState);
            mSwitchBar.addOnSwitchChangeListener(mNewSettings);
        }
    }

    @Override
    public void onStop() {
        if (mSettings != null) {
            mSwitchBar.removeOnSwitchChangeListener(mSettings);
        }
        if (mNewSettings != null) {
            mSwitchBar.removeOnSwitchChangeListener(mNewSettings);
        }
    }
}
+70 −0
Original line number Diff line number Diff line
/*
 * 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.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.os.Bundle;

import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

public class EnableDevelopmentSettingWarningDialog extends InstrumentedDialogFragment
        implements DialogInterface.OnClickListener {

    public static final String TAG = "EnableDevSettingDlg";

    public static void show(
            DevelopmentSettingsDashboardFragment host) {
        final EnableDevelopmentSettingWarningDialog dialog =
                new EnableDevelopmentSettingWarningDialog();
        dialog.setTargetFragment(host, 0 /* requestCode */);
        final FragmentManager manager = host.getActivity().getFragmentManager();
        if (manager.findFragmentByTag(TAG) == null) {
            dialog.show(manager, TAG);
        }
    }

    @Override
    public int getMetricsCategory() {
        return MetricsProto.MetricsEvent.DIALOG_ENABLE_DEVELOPMENT_OPTIONS;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setMessage(R.string.dev_settings_warning_message)
                .setTitle(R.string.dev_settings_warning_title)
                .setPositiveButton(android.R.string.yes, this)
                .setNegativeButton(android.R.string.no, this)
                .create();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        final DevelopmentSettingsDashboardFragment host =
                (DevelopmentSettingsDashboardFragment) getTargetFragment();
        if (which == DialogInterface.BUTTON_POSITIVE) {
            host.onEnableDevelopmentOptionsConfirmed();
        } else {
            host.onEnableDevelopmentOptionsRejected();
        }
    }
}
+82 −1
Original line number Diff line number Diff line
@@ -17,22 +17,32 @@
package com.android.settings.development;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.provider.SearchIndexableResource;
import android.provider.Settings;

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.settings.widget.SwitchBar;
import com.android.settings.widget.ToggleSwitch;
import com.android.settingslib.development.DevelopmentSettingsEnabler;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;

import java.util.List;

@@ -44,11 +54,24 @@ import java.util.List;
        })
public class DevelopmentSettingsDashboardFragmentTest {

    private SwitchBar mSwitchBar;
    private ToggleSwitch mSwitch;
    private Context mContext;
    private DevelopmentSettingsDashboardFragment mDashboard;

    @Before
    public void setUp() {
        mDashboard = new DevelopmentSettingsDashboardFragment();
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;
        mSwitchBar = new SwitchBar(mContext);
        mSwitch = mSwitchBar.getSwitch();
        mDashboard = spy(new DevelopmentSettingsDashboardFragment());
        ReflectionHelpers.setField(mDashboard, "mSwitchBar", mSwitchBar);
    }

    @After
    public void tearDown() {
        ShadowEnableDevelopmentSettingWarningDialog.reset();
    }

    @Test
@@ -95,4 +118,62 @@ public class DevelopmentSettingsDashboardFragmentTest {

        assertThat(nonIndexableKeys).doesNotContain("development_prefs_screen");
    }

    @Test
    @Config(shadows = {
            ShadowEnableDevelopmentSettingWarningDialog.class
    })
    public void onSwitchChanged_sameState_shouldDoNothing() {
        when(mDashboard.getContext()).thenReturn(mContext);
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);

        mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
        assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isFalse();
    }

    @Test
    @Config(shadows = {
            ShadowEnableDevelopmentSettingWarningDialog.class
    })
    public void onSwitchChanged_turnOn_shouldShowWarningDialog() {
        when(mDashboard.getContext()).thenReturn(mContext);
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);

        mDashboard.onSwitchChanged(mSwitch, true /* isChecked */);
        assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isTrue();
    }

    @Test
    @Config(shadows = {
            ShadowEnableDevelopmentSettingWarningDialog.class
    })
    public void onSwitchChanged_turnOff_shouldTurnOff() {
        when(mDashboard.getContext()).thenReturn(mContext);
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);

        mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);

        assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isFalse();
        assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext))
                .isFalse();
    }

    @Implements(EnableDevelopmentSettingWarningDialog.class)
    public static class ShadowEnableDevelopmentSettingWarningDialog {

        static boolean mShown;

        public static void reset() {
            mShown = false;
        }

        @Implementation
        public static void show(
                DevelopmentSettingsDashboardFragment host) {
            mShown = true;
        }
    }
}
+34 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settings.development;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;

import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -45,6 +46,8 @@ public class DevelopmentSwitchBarControllerTest {

    @Mock
    private DevelopmentSettings mSettings;
    @Mock
    private DevelopmentSettingsDashboardFragment mNewSettings;
    private Lifecycle mLifecycle;
    private SwitchBar mSwitchBar;
    private DevelopmentSwitchBarController mController;
@@ -76,6 +79,21 @@ public class DevelopmentSwitchBarControllerTest {
        assertThat(listeners).doesNotContain(mSettings);
    }

    @Test
    public void runThroughLifecycle_v2_isMonkeyRun_shouldNotRegisterListener() {
        ShadowUtils.setIsUserAMonkey(true);
        mController = new DevelopmentSwitchBarController(mNewSettings, mSwitchBar,
                true /* isAvailable */, mLifecycle);
        final ArrayList<SwitchBar.OnSwitchChangeListener> listeners =
                ReflectionHelpers.getField(mSwitchBar, "mSwitchChangeListeners");

        mLifecycle.onStart();
        assertThat(listeners).doesNotContain(mNewSettings);

        mLifecycle.onStop();
        assertThat(listeners).doesNotContain(mNewSettings);
    }

    @Test
    public void runThroughLifecycle_isNotMonkeyRun_shouldRegisterAndRemoveListener() {
        ShadowUtils.setIsUserAMonkey(false);
@@ -91,6 +109,22 @@ public class DevelopmentSwitchBarControllerTest {
        assertThat(listeners).doesNotContain(mSettings);
    }

    @Test
    public void runThroughLifecycle_v2_isNotMonkeyRun_shouldRegisterAndRemoveListener() {
        when(mNewSettings.getContext()).thenReturn(RuntimeEnvironment.application);
        ShadowUtils.setIsUserAMonkey(false);
        mController = new DevelopmentSwitchBarController(mNewSettings, mSwitchBar,
                true /* isAvailable */, mLifecycle);
        final ArrayList<SwitchBar.OnSwitchChangeListener> listeners =
                ReflectionHelpers.getField(mSwitchBar, "mSwitchChangeListeners");

        mLifecycle.onStart();
        assertThat(listeners).contains(mNewSettings);

        mLifecycle.onStop();
        assertThat(listeners).doesNotContain(mNewSettings);
    }

    @Test
    public void buildController_unavailable_shouldDisableSwitchBar() {
        ShadowUtils.setIsUserAMonkey(false);