From fcf98251f2b407b61fffa7f86673e98021b6bd04 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Wed, 20 Mar 2019 08:54:56 -0700 Subject: [PATCH] Updated privacy settings to launch custom content capture settings when available. Test: manual verification Test: atest EnableContentCapturePreferenceControllerTest \ CtsContentTestCases:android.content.cts.AvailableIntentsTest#testRequestEnableContentCaptureIntent Test: adb shell am start-activity -a android.settings.REQUEST_ENABLE_CONTENT_CAPTURE Fixes: 119264902 Change-Id: I2a030c31d966d40feb6ba449e4bbc9ef8cf0565b --- res/xml/privacy_dashboard_settings.xml | 13 ++++ ...bleContentCapturePreferenceController.java | 29 +++----- ...thServiceSettingsPreferenceController.java | 72 +++++++++++++++++++ .../settings/utils/ContentCaptureUtils.java | 66 +++++++++++++++++ ...ontentCapturePreferenceControllerTest.java | 2 +- 5 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java create mode 100644 src/com/android/settings/utils/ContentCaptureUtils.java diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml index d2d9e35a1dd..f39880c2bd7 100644 --- a/res/xml/privacy_dashboard_settings.xml +++ b/res/xml/privacy_dashboard_settings.xml @@ -63,12 +63,25 @@ settings:searchable="false"/> + + + + + + diff --git a/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java b/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java index b3ea9a7e395..47610aa18b5 100644 --- a/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java +++ b/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java @@ -16,43 +16,34 @@ package com.android.settings.privacy; +import android.annotation.NonNull; import android.content.Context; -import android.os.IBinder; -import android.os.ServiceManager; -import android.os.UserHandle; import android.provider.Settings; -import android.view.contentcapture.ContentCaptureManager; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.utils.ContentCaptureUtils; -public class EnableContentCapturePreferenceController extends TogglePreferenceController { +public final class EnableContentCapturePreferenceController extends TogglePreferenceController { - private static final String KEY_SHOW_PASSWORD = "content_capture"; - private static final int MY_USER_ID = UserHandle.myUserId(); - - public EnableContentCapturePreferenceController(Context context) { - super(context, KEY_SHOW_PASSWORD); + public EnableContentCapturePreferenceController(@NonNull Context context, @NonNull String key) { + super(context, key); } @Override public boolean isChecked() { - boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, MY_USER_ID) == 1; - return enabled; + return ContentCaptureUtils.isEnabledForUser(mContext); } @Override public boolean setChecked(boolean isChecked) { - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.CONTENT_CAPTURE_ENABLED, isChecked ? 1 : 0, MY_USER_ID); + ContentCaptureUtils.setEnabledForUser(mContext, isChecked); return true; } @Override public int getAvailabilityStatus() { - // We cannot look for ContentCaptureManager, because it's not available if the service - // didn't whitelist Settings - IBinder service = ServiceManager.checkService(Context.CONTENT_CAPTURE_MANAGER_SERVICE); - return service != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + boolean available = ContentCaptureUtils.isFeatureAvailable() + && ContentCaptureUtils.getServiceSettingsComponentName() == null; + return available ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } } diff --git a/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java new file mode 100644 index 00000000000..1456c2dc367 --- /dev/null +++ b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java @@ -0,0 +1,72 @@ +/* + * 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.privacy; + +import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import androidx.preference.Preference; + +import com.android.settings.core.TogglePreferenceController; +import com.android.settings.utils.ContentCaptureUtils; +import com.android.settings.widget.MasterSwitchPreference; + +public final class EnableContentCaptureWithServiceSettingsPreferenceController + extends TogglePreferenceController { + + private static final String TAG = "ContentCaptureController"; + + public EnableContentCaptureWithServiceSettingsPreferenceController(@NonNull Context context, + @NonNull String key) { + super(context, key); + } + + @Override + public boolean isChecked() { + return ContentCaptureUtils.isEnabledForUser(mContext); + } + + @Override + public boolean setChecked(boolean isChecked) { + ContentCaptureUtils.setEnabledForUser(mContext, isChecked); + return true; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + + ComponentName componentName = ContentCaptureUtils.getServiceSettingsComponentName(); + if (componentName != null) { + preference.setIntent(new Intent(Intent.ACTION_MAIN).setComponent(componentName)); + } else { + // Should not happen - preference should be disabled by controller + Log.w(TAG, "No component name for custom service settings"); + preference.setSelectable(false); + } + } + + @Override + public int getAvailabilityStatus() { + boolean available = ContentCaptureUtils.isFeatureAvailable() + && ContentCaptureUtils.getServiceSettingsComponentName() != null; + return available ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } +} diff --git a/src/com/android/settings/utils/ContentCaptureUtils.java b/src/com/android/settings/utils/ContentCaptureUtils.java new file mode 100644 index 00000000000..a92651fbb48 --- /dev/null +++ b/src/com/android/settings/utils/ContentCaptureUtils.java @@ -0,0 +1,66 @@ +/* + * 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.utils; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.os.IBinder; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Log; +import android.view.contentcapture.ContentCaptureManager; + +public final class ContentCaptureUtils { + + private static final String TAG = ContentCaptureUtils.class.getSimpleName(); + private static final int MY_USER_ID = UserHandle.myUserId(); + + public static boolean isEnabledForUser(@NonNull Context context) { + boolean enabled = Settings.Secure.getIntForUser(context.getContentResolver(), + Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, MY_USER_ID) == 1; + return enabled; + } + + public static void setEnabledForUser(@NonNull Context context, boolean enabled) { + Settings.Secure.putIntForUser(context.getContentResolver(), + Settings.Secure.CONTENT_CAPTURE_ENABLED, enabled ? 1 : 0, MY_USER_ID); + } + + public static boolean isFeatureAvailable() { + // We cannot look for ContentCaptureManager, because it's not available if the service + // didn't whitelist Settings + IBinder service = ServiceManager.checkService(Context.CONTENT_CAPTURE_MANAGER_SERVICE); + return service != null; + } + + @Nullable + public static ComponentName getServiceSettingsComponentName() { + try { + return ContentCaptureManager.getServiceSettingsComponentName(); + } catch (RuntimeException e) { + Log.w(TAG, "Could not get service settings: " + e); + return null; + } + } + + private ContentCaptureUtils() { + throw new UnsupportedOperationException("contains only static methods"); + } +} diff --git a/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java index a3798582033..179063d744a 100644 --- a/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java @@ -51,7 +51,7 @@ public class EnableContentCapturePreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - mController = new EnableContentCapturePreferenceController(mContext); + mController = new EnableContentCapturePreferenceController(mContext, "THE_KEY_TO_SUCCESS"); mPreference = new Preference(mContext); mPreference.setKey(mController.getPreferenceKey()); }