diff --git a/res/values/config.xml b/res/values/config.xml index f5105232035..b9a69f105e8 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -106,6 +106,9 @@ --> + + + true diff --git a/src/com/android/settings/display/BrightnessLevelPreferenceController.java b/src/com/android/settings/display/BrightnessLevelPreferenceController.java index 05f43f650ac..dc24ed0188f 100644 --- a/src/com/android/settings/display/BrightnessLevelPreferenceController.java +++ b/src/com/android/settings/display/BrightnessLevelPreferenceController.java @@ -151,13 +151,21 @@ public class BrightnessLevelPreferenceController extends AbstractPreferenceContr return (value - min) / (max - min); } + @VisibleForTesting + IVrManager safeGetVrManager() { + return IVrManager.Stub.asInterface(ServiceManager.getService( + Context.VR_SERVICE)); + } + @VisibleForTesting boolean isInVrMode() { - try { - return IVrManager.Stub.asInterface(ServiceManager.getService(Context.VR_SERVICE)) - .getVrModeState(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to check vr mode!", e); + IVrManager vrManager = safeGetVrManager(); + if (vrManager != null) { + try { + return vrManager.getVrModeState(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to check vr mode!", e); + } } return false; } diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index 21d14905213..6edacda5522 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -63,6 +63,7 @@ import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import com.android.settings.search.SearchFeatureProvider; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedPreference; @@ -132,10 +133,14 @@ public class ChooseLockGeneric extends SettingsActivity { @VisibleForTesting static final int CONFIRM_EXISTING_REQUEST = 100; - private static final int ENABLE_ENCRYPTION_REQUEST = 101; - private static final int CHOOSE_LOCK_REQUEST = 102; - private static final int CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST = 103; - private static final int SKIP_FINGERPRINT_REQUEST = 104; + @VisibleForTesting + static final int ENABLE_ENCRYPTION_REQUEST = 101; + @VisibleForTesting + static final int CHOOSE_LOCK_REQUEST = 102; + @VisibleForTesting + static final int CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST = 103; + @VisibleForTesting + static final int SKIP_FINGERPRINT_REQUEST = 104; private ChooseLockSettingsHelper mChooseLockSettingsHelper; private DevicePolicyManager mDPM; @@ -401,6 +406,8 @@ public class ChooseLockGeneric extends SettingsActivity { resultCode == RESULT_FINISHED ? RESULT_OK : resultCode, data); finish(); } + } else if (requestCode == SearchFeatureProvider.REQUEST_CODE) { + return; } else { getActivity().setResult(Activity.RESULT_CANCELED); finish(); diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java index bce6911ca50..6744a7b72ff 100644 --- a/src/com/android/settings/search/SearchFeatureProvider.java +++ b/src/com/android/settings/search/SearchFeatureProvider.java @@ -32,6 +32,7 @@ import com.android.settingslib.search.SearchIndexableResources; public interface SearchFeatureProvider { Intent SEARCH_UI_INTENT = new Intent("com.android.settings.action.SETTINGS_SEARCH"); + int REQUEST_CODE = 0; /** * Ensures the caller has necessary privilege to launch search result page. @@ -65,7 +66,7 @@ public interface SearchFeatureProvider { FeatureFactory.getFactory( activity.getApplicationContext()).getSlicesFeatureProvider() .indexSliceDataAsync(activity.getApplicationContext()); - activity.startActivityForResult(intent, 0 /* requestCode */); + activity.startActivityForResult(intent, REQUEST_CODE); }); } } diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index f0439a893f2..e3594779356 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.READ_SEARCH_INDEXABLES; import android.app.slice.SliceManager; import android.content.ContentResolver; +import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; @@ -36,6 +37,7 @@ import androidx.annotation.VisibleForTesting; import androidx.slice.Slice; import androidx.slice.SliceProvider; +import com.android.settings.R; import com.android.settings.bluetooth.BluetoothSliceBuilder; import com.android.settings.core.BasePreferenceController; import com.android.settings.flashlight.FlashlightSliceBuilder; @@ -113,6 +115,8 @@ public class SettingsSliceProvider extends SliceProvider { public static final String EXTRA_SLICE_PLATFORM_DEFINED = "com.android.settings.slice.extra.platform"; + private static final KeyValueListParser KEY_VALUE_LIST_PARSER = new KeyValueListParser(','); + @VisibleForTesting CustomSliceManager mCustomSliceManager; @@ -125,13 +129,10 @@ public class SettingsSliceProvider extends SliceProvider { @VisibleForTesting Map mSliceDataCache; - private final KeyValueListParser mParser; - final Set mRegisteredUris = new ArraySet<>(); public SettingsSliceProvider() { super(READ_SEARCH_INDEXABLES); - mParser = new KeyValueListParser(','); } @Override @@ -151,6 +152,7 @@ public class SettingsSliceProvider extends SliceProvider { SliceDeepLinkSpringBoard.parse( intent.getData(), getContext().getPackageName())); } catch (URISyntaxException e) { + Log.e(TAG, "Uri syntax error, can't map intent to uri.", e); return null; } } @@ -319,9 +321,33 @@ public class SettingsSliceProvider extends SliceProvider { final List keys = mSlicesDatabaseAccessor.getSliceKeys(isPlatformUri); descendants.addAll(buildUrisFromKeys(keys, authority)); descendants.addAll(getSpecialCaseUris(isPlatformUri)); + grantWhitelistedPackagePermissions(getContext(), descendants); return descendants; } + @VisibleForTesting + static void grantWhitelistedPackagePermissions(Context context, List descendants) { + if (descendants == null) { + Log.d(TAG, "No descendants to grant permission with, skipping."); + } + final String[] whitelistPackages = + context.getResources().getStringArray(R.array.slice_whitelist_package_names); + if (whitelistPackages == null || whitelistPackages.length == 0) { + Log.d(TAG, "No packages to whitelist, skipping."); + return; + } else { + Log.d(TAG, String.format( + "Whitelisting %d uris to %d pkgs.", + descendants.size(), whitelistPackages.length)); + } + final SliceManager sliceManager = context.getSystemService(SliceManager.class); + for (Uri descendant : descendants) { + for (String toPackage : whitelistPackages) { + sliceManager.grantSlicePermission(toPackage, descendant); + } + } + } + private List buildUrisFromKeys(List keys, String authority) { final List descendants = new ArrayList<>(); @@ -428,7 +454,7 @@ public class SettingsSliceProvider extends SliceProvider { final Set set = new ArraySet<>(); try { - mParser.setString(value); + KEY_VALUE_LIST_PARSER.setString(value); } catch (IllegalArgumentException e) { Log.e(TAG, "Bad Settings Slices Whitelist flags", e); return set; diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml index bbbdcc2e849..2488882f2b5 100644 --- a/tests/robotests/res/values-mcc999/config.xml +++ b/tests/robotests/res/values-mcc999/config.xml @@ -67,4 +67,10 @@ fake_package/fake_service + + + + com.android.settings.slice_whitelist_package + + diff --git a/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java index 4122b14b734..a22a1591053 100644 --- a/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java @@ -84,6 +84,12 @@ public class BrightnessLevelPreferenceControllerTest { assertThat(mController.isAvailable()).isTrue(); } + @Test + public void isInVrMode_noVrManager_shouldAlwaysReturnFalse() { + doReturn(null).when(mController).safeGetVrManager(); + assertThat(mController.isInVrMode()).isFalse(); + } + @Test public void onStart_shouldRegisterObserver() { BrightnessLevelPreferenceController controller = diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java index b8aaeb80382..9eaf217a4f7 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java @@ -16,25 +16,32 @@ package com.android.settings.password; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; +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 android.app.Activity; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.provider.Settings.Global; import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment; +import com.android.settings.search.SearchFeatureProvider; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.SettingsShadowResources; import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; @@ -43,37 +50,88 @@ import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) public class ChooseLockGenericTest { + private Context mContext; + private ChooseLockGenericFragment mFragment; + private FragmentActivity mActivity; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mFragment = spy(new ChooseLockGenericFragment()); + mActivity = mock(FragmentActivity.class); + when(mFragment.getActivity()).thenReturn(mActivity); + when(mFragment.getFragmentManager()).thenReturn(mock(FragmentManager.class)); + doNothing().when(mFragment).startActivity(any(Intent.class)); + } + @After public void tearDown() { Global.putInt(RuntimeEnvironment.application.getContentResolver(), - Global.DEVICE_PROVISIONED, 1); + Global.DEVICE_PROVISIONED, 1); } @Test @Config(shadows = SettingsShadowResources.SettingsShadowTheme.class) public void onCreate_deviceNotProvisioned_shouldFinishActivity() { - final Context context = RuntimeEnvironment.application; - Global.putInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0); - final FragmentActivity activity = mock(FragmentActivity.class); - when(activity.getContentResolver()).thenReturn(context.getContentResolver()); - when(activity.getTheme()).thenReturn(context.getTheme()); + Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0); + when(mActivity.getContentResolver()).thenReturn(mContext.getContentResolver()); + when(mActivity.getTheme()).thenReturn(mContext.getTheme()); + when(mFragment.getArguments()).thenReturn(Bundle.EMPTY); - final ChooseLockGenericFragment fragment = spy(new ChooseLockGenericFragment()); - when(fragment.getActivity()).thenReturn(activity); - when(fragment.getArguments()).thenReturn(Bundle.EMPTY); - - fragment.onCreate(Bundle.EMPTY); - verify(activity).finish(); + mFragment.onCreate(Bundle.EMPTY); + verify(mActivity).finish(); } @Test public void onActivityResult_nullIntentData_shouldNotCrash() { - ChooseLockGenericFragment fragment = spy(new ChooseLockGenericFragment()); - doNothing().when(fragment).updatePreferencesOrFinish(anyBoolean()); + doNothing().when(mFragment).updatePreferencesOrFinish(anyBoolean()); - fragment.onActivityResult( - fragment.CONFIRM_EXISTING_REQUEST, Activity.RESULT_OK, null /* data */); + mFragment.onActivityResult( + ChooseLockGenericFragment.CONFIRM_EXISTING_REQUEST, Activity.RESULT_OK, + null /* data */); // no crash } + @Test + public void onActivityResult_requestcode0_shouldNotFinish() { + mFragment.onActivityResult( + SearchFeatureProvider.REQUEST_CODE, Activity.RESULT_OK, null /* data */); + + verify(mFragment, never()).finish(); + } + + @Test + public void onActivityResult_requestcode101_shouldFinish() { + mFragment.onActivityResult( + ChooseLockGenericFragment.ENABLE_ENCRYPTION_REQUEST, Activity.RESULT_OK, + null /* data */); + + verify(mFragment).finish(); + } + + @Test + public void onActivityResult_requestcode102_shouldFinish() { + mFragment.onActivityResult( + ChooseLockGenericFragment.CHOOSE_LOCK_REQUEST, Activity.RESULT_OK, null /* data */); + + verify(mFragment).finish(); + } + + @Test + public void onActivityResult_requestcode103_shouldFinish() { + mFragment.onActivityResult( + ChooseLockGenericFragment.CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST, + BiometricEnrollBase.RESULT_FINISHED, null /* data */); + + verify(mFragment).finish(); + } + + @Test + public void onActivityResult_requestcode104_shouldFinish() { + mFragment.onActivityResult( + ChooseLockGenericFragment.SKIP_FINGERPRINT_REQUEST, Activity.RESULT_OK, + null /* data */); + + verify(mFragment).finish(); + } } diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java index 1ee9230b50e..f7c6bba76e2 100644 --- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java +++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java @@ -21,9 +21,12 @@ import static android.content.ContentResolver.SCHEME_CONTENT; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -64,6 +67,7 @@ import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.annotation.Resetter; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -477,6 +481,28 @@ public class SettingsSliceProviderTest { mProvider.onSlicePinned(uri); } + @Test + public void grantWhitelistedPackagePermissions_noWhitelist_shouldNotGrant() { + final List uris = new ArrayList<>(); + uris.add(Uri.parse("content://settings/slice")); + + mProvider.grantWhitelistedPackagePermissions(mContext, uris); + + verify(mManager, never()).grantSlicePermission(anyString(), any(Uri.class)); + } + + @Test + @Config(qualifiers = "mcc999") + public void grantWhitelistedPackagePermissions_hasPackageWhitelist_shouldGrant() { + final List uris = new ArrayList<>(); + uris.add(Uri.parse("content://settings/slice")); + + mProvider.grantWhitelistedPackagePermissions(mContext, uris); + + verify(mManager) + .grantSlicePermission("com.android.settings.slice_whitelist_package", uris.get(0)); + } + private void insertSpecialCase(String key) { insertSpecialCase(key, true); }