diff --git a/res/values/strings.xml b/res/values/strings.xml index 2636e6e6573..6b7f04d5643 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2832,6 +2832,10 @@ On / Screen won\u2019t turn off if you\u2019re looking at it Off + + Camera access needed + + Tap to manage permissions for Device Personalization Services Prevents your screen from turning off if you\u2019re looking at it diff --git a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java index 5ce7be5b43e..ab7465cfd3f 100644 --- a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java +++ b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java @@ -21,8 +21,11 @@ import android.content.Context; import androidx.preference.Preference; public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPreferenceController { + private final Context mContext; + public AdaptiveSleepDetailPreferenceController(Context context, String key) { super(context, key); + mContext = context; } @Override @@ -42,6 +45,7 @@ public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPrefer @Override public void updateState(Preference preference) { super.updateState(preference); - preference.setEnabled(super.hasSufficientPermissions); + preference.setEnabled(AdaptiveSleepPreferenceController.hasSufficientPermission( + mContext.getPackageManager())); } -} +} \ No newline at end of file diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java index e83410d3d7a..f9828d77fcd 100644 --- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java +++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java @@ -29,7 +29,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle private static final String SYSTEM_KEY = ADAPTIVE_SLEEP; private static final int DEFAULT_VALUE = 0; - final boolean hasSufficientPermissions; + private final boolean hasSufficientPermissions; public AdaptiveSleepPreferenceController(Context context, String key) { super(context, key); @@ -71,7 +71,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle : UNSUPPORTED_ON_DEVICE; } - private static boolean hasSufficientPermission(PackageManager packageManager) { + static boolean hasSufficientPermission(PackageManager packageManager) { final String attentionPackage = packageManager.getAttentionServicePackageName(); return attentionPackage != null && packageManager.checkPermission( Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED; diff --git a/src/com/android/settings/display/AdaptiveSleepSettings.java b/src/com/android/settings/display/AdaptiveSleepSettings.java index d0f2c9aa0b1..94abe1aba0d 100644 --- a/src/com/android/settings/display/AdaptiveSleepSettings.java +++ b/src/com/android/settings/display/AdaptiveSleepSettings.java @@ -16,16 +16,21 @@ package com.android.settings.display; +import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission; import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF; import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED; import android.app.settings.SettingsEnums; import android.content.Context; -import android.content.SharedPreferences; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; import android.provider.SearchIndexableResource; -import android.util.Log; +import androidx.preference.Preference; + +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; @@ -39,23 +44,45 @@ import java.util.List; public class AdaptiveSleepSettings extends DashboardFragment { private static final String TAG = "AdaptiveSleepSettings"; + private Context mContext; + private String mPackageName; + private PackageManager mPackageManager; + + @VisibleForTesting + Preference mPermissionRequiredPreference; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); final FooterPreference footerPreference = mFooterPreferenceMixin.createFooterPreference(); - final Context context = getContext(); + mContext = getContext(); + mPermissionRequiredPreference = createPermissionMissionPreference(); footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp); footerPreference.setTitle(R.string.adaptive_sleep_privacy); - context.getSharedPreferences(PREF, Context.MODE_PRIVATE) + getPreferenceScreen().addPreference(mPermissionRequiredPreference); + mPermissionRequiredPreference.setVisible(false); + mPackageManager = mContext.getPackageManager(); + mPackageName = mPackageManager.getAttentionServicePackageName(); + mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE) .edit() .putBoolean(PREF_KEY_INTERACTED, true) .apply(); } + @Override + public void onResume() { + super.onResume(); + if (!hasSufficientPermission(mPackageManager)) { + mPermissionRequiredPreference.setVisible(true); + } + else { + mPermissionRequiredPreference.setVisible(false); + } + } + @Override protected int getPreferenceScreenResId() { return R.xml.adaptive_sleep_detail; @@ -86,4 +113,29 @@ public class AdaptiveSleepSettings extends DashboardFragment { return Arrays.asList(sir); } }; + + private Preference createPermissionMissionPreference() { + Preference preference = new Preference(mContext, null); + preference.setIcon(R.drawable.ic_info_outline_24); + // Makes sure it's above the toggle. + preference.setOrder(1); + preference.setPersistent(true); + preference.setTitle(R.string.adaptive_sleep_title_no_permission); + preference.setSummary(R.string.adaptive_sleep_summary_no_permission); + preference.setOnPreferenceClickListener(p -> { + final Intent intent = new Intent( + android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + mPackageName)); + mContext.startActivity(intent); + return true; + }); + return preference; + } + + @VisibleForTesting + void setupForTesting(PackageManager packageManager, Context context) { + mContext = context; + mPackageManager = packageManager; + mPermissionRequiredPreference = createPermissionMissionPreference(); + } } diff --git a/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java b/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java new file mode 100644 index 00000000000..971ebc52d67 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2019 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.display; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; + +import androidx.preference.PreferenceScreen; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class AdaptiveSleepSettingsTest { + private AdaptiveSleepSettings mSettings; + private static final String PACKAGE_NAME = "package_name"; + @Mock + private PackageManager mPackageManager; + @Mock + private PreferenceScreen mScreen; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + Context context = RuntimeEnvironment.application; + mSettings = spy(new AdaptiveSleepSettings()); + + doReturn(PACKAGE_NAME).when(mPackageManager).getAttentionServicePackageName(); + doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + doReturn(mScreen).when(mSettings).getPreferenceScreen(); + + mSettings.setupForTesting(mPackageManager, context); + mSettings.onAttach(context); + + } + + @Test + public void onResume_hasPermission_preferenceInvisible() { + mSettings.onResume(); + + assertThat(mSettings.mPermissionRequiredPreference.isVisible()).isFalse(); + } + + @Test + public void onResume_noPermission_preferenceVisible() { + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + + mSettings.onResume(); + + assertThat(mSettings.mPermissionRequiredPreference.isVisible()).isTrue(); + } +}