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

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

Merge "Disable "Verify apps over usb" according to user restriction." into oc-dev

parents 8e305ee5 f9f980d3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@
            android:title="@string/wait_for_debugger"
            android:summary="@string/wait_for_debugger_summary"/>

        <SwitchPreference
        <com.android.settingslib.RestrictedSwitchPreference
            android:key="verify_apps_over_usb"
            android:title="@string/verify_apps_over_usb_title"
            android:summary="@string/verify_apps_over_usb_summary"/>
+11 −58
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IShortcutService;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbManager;
@@ -140,7 +139,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
    private static final String DEBUG_APP_KEY = "debug_app";
    private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
    private static final String MOCK_LOCATION_APP_KEY = "mock_location_app";
    private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
    private static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes";
    private static final String FORCE_ALLOW_ON_EXTERNAL_KEY = "force_allow_on_external";
    private static final String STRICT_MODE_KEY = "strict_mode";
@@ -226,8 +224,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment

    private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";

    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";

    private static final String TERMINAL_APP_PACKAGE = "com.android.terminal";

    private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
@@ -275,7 +271,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
    private Preference mMockLocationAppPref;

    private SwitchPreference mWaitForDebugger;
    private SwitchPreference mVerifyAppsOverUsb;
    private VerifyAppsOverUsbPreferenceController mVerifyAppsOverUsbController;
    private SwitchPreference mWifiDisplayCertification;
    private SwitchPreference mWifiVerboseLogging;
    private SwitchPreference mWifiAggressiveHandover;
@@ -393,6 +389,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
        mBugReportInPowerController = new BugReportInPowerPreferenceController(getActivity());
        mTelephonyMonitorController = new TelephonyMonitorPreferenceController(getActivity());
        mWebViewAppPrefController = new WebViewAppPreferenceController(getActivity());
        mVerifyAppsOverUsbController = new VerifyAppsOverUsbPreferenceController(getActivity());

        setIfOnlyAvailableForAdmins(true);
        if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) {
@@ -453,14 +450,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
        mMockLocationAppPref = findPreference(MOCK_LOCATION_APP_KEY);
        mAllPrefs.add(mMockLocationAppPref);

        mVerifyAppsOverUsb = findAndInitSwitchPref(VERIFY_APPS_OVER_USB_KEY);
        if (!showVerifierSetting()) {
            if (debugDebuggingCategory != null) {
                debugDebuggingCategory.removePreference(mVerifyAppsOverUsb);
            } else {
                mVerifyAppsOverUsb.setEnabled(false);
            }
        }
        mVerifyAppsOverUsbController.displayPreference(getPreferenceScreen());

        mStrictMode = findAndInitSwitchPref(STRICT_MODE_KEY);
        mPointerLocation = findAndInitSwitchPref(POINTER_LOCATION_KEY);
        mShowTouches = findAndInitSwitchPref(SHOW_TOUCHES_KEY);
@@ -795,7 +786,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
        updateImmediatelyDestroyActivitiesOptions();
        updateAppProcessLimitOptions();
        updateShowAllANRsOptions();
        updateVerifyAppsOverUsbOptions();
        mVerifyAppsOverUsbController.updatePreference();
        updateOtaDisableAutomaticUpdateOptions();
        updateBugreportOptions();
        updateForceRtlOptions();
@@ -995,19 +986,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
        }
    }

    private void updateVerifyAppsOverUsbOptions() {
        updateSwitchPreference(mVerifyAppsOverUsb,
                Settings.Global.getInt(getActivity().getContentResolver(),
                        Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0);
        mVerifyAppsOverUsb.setEnabled(enableVerifierSetting());
    }

    private void writeVerifyAppsOverUsbOptions() {
        Settings.Global.putInt(getActivity().getContentResolver(),
                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
                mVerifyAppsOverUsb.isChecked() ? 1 : 0);
    }

    private void updateOtaDisableAutomaticUpdateOptions() {
        // We use the "disabled status" in code, but show the opposite text
        // "Automatic system updates" on screen. So a value 0 indicates the
@@ -1026,31 +1004,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
                mOtaDisableAutomaticUpdate.isChecked() ? 0 : 1);
    }

    private boolean enableVerifierSetting() {
        final ContentResolver cr = getActivity().getContentResolver();
        if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 0) {
            return false;
        }
        if (Settings.Global.getInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 0) {
            return false;
        } else {
            final PackageManager pm = getActivity().getPackageManager();
            final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
            verification.setType(PACKAGE_MIME_TYPE);
            verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
            if (receivers.size() == 0) {
                return false;
            }
        }
        return true;
    }

    private boolean showVerifierSetting() {
        return Settings.Global.getInt(getActivity().getContentResolver(),
                Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
    }

    private static boolean showEnableOemUnlockPreference() {
        return !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
    }
@@ -2417,6 +2370,10 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
            return true;
        }

        if (mVerifyAppsOverUsbController.handlePreferenceTreeClick(preference)) {
            return true;
        }

        if (preference == mEnableAdb) {
            if (mEnableAdb.isChecked()) {
                mDialogClicked = false;
@@ -2431,8 +2388,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
            } else {
                Settings.Global.putInt(getActivity().getContentResolver(),
                        Settings.Global.ADB_ENABLED, 0);
                mVerifyAppsOverUsb.setEnabled(false);
                mVerifyAppsOverUsb.setChecked(false);
                mVerifyAppsOverUsbController.updatePreference();
                updateBugreportOptions();
            }
        } else if (preference == mClearAdbKeys) {
@@ -2482,8 +2438,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
            startActivityForResult(intent, RESULT_DEBUG_APP);
        } else if (preference == mWaitForDebugger) {
            writeDebuggerOptions();
        } else if (preference == mVerifyAppsOverUsb) {
            writeVerifyAppsOverUsbOptions();
        } else if (preference == mOtaDisableAutomaticUpdate) {
            writeOtaDisableAutomaticUpdateOptions();
        } else if (preference == mStrictMode) {
@@ -2631,8 +2585,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
                mDialogClicked = true;
                Settings.Global.putInt(getActivity().getContentResolver(),
                        Settings.Global.ADB_ENABLED, 1);
                mVerifyAppsOverUsb.setEnabled(true);
                updateVerifyAppsOverUsbOptions();
                mVerifyAppsOverUsbController.updatePreference();
                updateBugreportOptions();
            } else {
                // Reset the toggle
+149 −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.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;

import com.android.settings.core.PreferenceController;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;

import java.util.List;

/**
 * Controller to manage the state of "Verify apps over USB" toggle.
 */
public class VerifyAppsOverUsbPreferenceController extends PreferenceController {
    private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";

    private RestrictedSwitchPreference mPreference;

    /**
     * Class for indirection of RestrictedLockUtils for testing purposes. It would be nice to mock
     * the appropriate methods in UserManager instead but they aren't accessible.
     */
    @VisibleForTesting
    class RestrictedLockUtilsDelegate {
        public EnforcedAdmin checkIfRestrictionEnforced(
                Context context, String userRestriction, int userId) {
            return RestrictedLockUtils.checkIfRestrictionEnforced(context, userRestriction, userId);
        }
    }
    // NB: This field is accessed using reflection in the test, please keep name in sync.
    private final RestrictedLockUtilsDelegate mRestrictedLockUtils =
            new RestrictedLockUtilsDelegate();

    VerifyAppsOverUsbPreferenceController(Context context) {
        super(context);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        if (isAvailable()) {
            mPreference = (RestrictedSwitchPreference)
                    screen.findPreference(VERIFY_APPS_OVER_USB_KEY);
        }
    }

    @Override
    public boolean isAvailable() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
    }

    @Override
    public String getPreferenceKey() {
        return VERIFY_APPS_OVER_USB_KEY;
    }

    /** Saves the settings value when it is toggled. */
    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (VERIFY_APPS_OVER_USB_KEY.equals(preference.getKey())) {
            Settings.Global.putInt(mContext.getContentResolver(),
                    Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, mPreference.isChecked() ? 1 : 0);
            return true;
        }
        return false;
    }

    /**
     * Checks whether the toggle should be enabled depending on whether verify apps over USB is
     * possible currently. If ADB is disabled or if package verifier does not exist, the toggle
     * should be disabled.
     */
    private boolean shouldBeEnabled() {
        final ContentResolver cr = mContext.getContentResolver();
        if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 0) {
            return false;
        }
        if (Settings.Global.getInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 0) {
            return false;
        } else {
            final PackageManager pm = mContext.getPackageManager();
            final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
            verification.setType(PACKAGE_MIME_TYPE);
            verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
            if (receivers.size() == 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * Updates position, enabled status and maybe admin message.
     */
    public void updatePreference() {
        if (!isAvailable()) {
            return;
        }

        if (!shouldBeEnabled()) {
            mPreference.setChecked(false);
            mPreference.setDisabledByAdmin(null);
            mPreference.setEnabled(false);
            return;
        }

        final EnforcedAdmin enforcingAdmin = mRestrictedLockUtils.checkIfRestrictionEnforced(
                        mContext, UserManager.ENSURE_VERIFY_APPS, UserHandle.myUserId());
        if (enforcingAdmin != null) {
            mPreference.setChecked(true);
            mPreference.setDisabledByAdmin(enforcingAdmin);
            return;
        }

        mPreference.setEnabled(true);
        final boolean checked = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
        mPreference.setChecked(checked);
    }
}
+179 −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 static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserManager;
import android.provider.Settings.Global;
import android.support.v7.preference.PreferenceScreen;

import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;

import java.util.Collections;
import java.util.List;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class VerifyAppsOverUsbPreferenceControllerTest {

    @Mock
    private PackageManager mPackageManager;
    @Mock
    private PreferenceScreen mScreen;
    @Mock
    private RestrictedSwitchPreference mPreference;

    @Mock
    private VerifyAppsOverUsbPreferenceController.RestrictedLockUtilsDelegate
            mRestrictedLockUtilsDelegate;

    private Context mContext;
    private VerifyAppsOverUsbPreferenceController mController;

    /** Convenience class for setting global int settings. */
    class GlobalSetter {
        public GlobalSetter set(String setting, int value) {
            Global.putInt(mContext.getContentResolver(), setting, value);
            return this;
        }
    }
    private final GlobalSetter mGlobals = new GlobalSetter();

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        final ShadowApplication shadowContext = ShadowApplication.getInstance();
        mContext = spy(shadowContext.getApplicationContext());
        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        mController = new VerifyAppsOverUsbPreferenceController(mContext);
        ReflectionHelpers.setField(
                mController, "mRestrictedLockUtils", mRestrictedLockUtilsDelegate);
    }

    private void setupVerifyBroadcastReceivers(boolean nonEmpty) {
        final List<ResolveInfo> resolveInfos = nonEmpty
                ? Collections.singletonList(mock(ResolveInfo.class))
                : Collections.<ResolveInfo>emptyList();
        when(mPackageManager.queryBroadcastReceivers((Intent) any(), anyInt()))
                .thenReturn(resolveInfos);
    }

    private void setupEnforcedAdmin(EnforcedAdmin result) {
        when(mRestrictedLockUtilsDelegate.checkIfRestrictionEnforced(
                (Context) any(), anyString(), anyInt())).thenReturn(result);
    }

    @Test
    public void updateState_preferenceCheckedWhenSettingIsOn() {
        setupVerifyBroadcastReceivers(true);
        setupEnforcedAdmin(null);
        mGlobals.set(Global.ADB_ENABLED, 1).set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1);
        mController.displayPreference(mScreen);
        mController.updatePreference();
        verify(mPreference).setChecked(true);
    }

    @Test
    public void updateState_preferenceUncheckedWhenSettingIsOff() {
        setupVerifyBroadcastReceivers(true);
        setupEnforcedAdmin(null);
        mGlobals.set(Global.ADB_ENABLED, 1).set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 0);
        mController.displayPreference(mScreen);
        mController.updatePreference();
        verify(mPreference).setChecked(false);
    }

    @Test
    public void updateState_preferenceUncheckedWhenNoAdb() {
        setupVerifyBroadcastReceivers(true);
        setupEnforcedAdmin(null);
        mGlobals.set(Global.ADB_ENABLED, 0).set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1);
        mController.displayPreference(mScreen);
        mController.updatePreference();
        verify(mPreference).setChecked(false);
    }

    @Test
    public void updateState_preferenceUncheckedWhenVerifierIsOff() {
        setupVerifyBroadcastReceivers(true);
        setupEnforcedAdmin(null);
        mGlobals.set(Global.ADB_ENABLED, 1)
                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1)
                .set(Global.PACKAGE_VERIFIER_ENABLE, 0);
        mController.displayPreference(mScreen);
        mController.updatePreference();
        verify(mPreference).setChecked(false);
    }

    @Test
    public void updateState_preferenceUncheckedWhenNoVerifyBroadcastReceivers() {
        setupVerifyBroadcastReceivers(false);
        setupEnforcedAdmin(null);
        mGlobals.set(Global.ADB_ENABLED, 1)
                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1);
        mController.displayPreference(mScreen);
        mController.updatePreference();
        verify(mPreference).setChecked(false);
    }

    @Test
    public void updateState_preferenceDisabledWhenRestrictedByAdmin() {
        setupVerifyBroadcastReceivers(true);
        final EnforcedAdmin admin = new EnforcedAdmin();
        setupEnforcedAdmin(admin);
        mGlobals.set(Global.ADB_ENABLED, 1)
                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1);
        mController.displayPreference(mScreen);
        mController.updatePreference();
        verify(mPreference).setDisabledByAdmin(admin);
    }

    @Test
    public void updateState_preferenceRemovedWhenVerifierSettingsVisibleIsOff() {
        setupVerifyBroadcastReceivers(true);
        mGlobals.set(Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 0);
        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
        when(mScreen.getPreferenceCount()).thenReturn(1);
        when(mScreen.getPreference(anyInt())).thenReturn(mPreference);
        mController.displayPreference(mScreen);
        verify(mScreen).removePreference(mPreference);
    }
}
 No newline at end of file