1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.permissioncontroller.privacysources 17 18 import android.content.ComponentName 19 import android.content.Context 20 import android.provider.Settings 21 import android.text.TextUtils 22 import android.util.Log 23 import kotlinx.coroutines.sync.Mutex 24 import kotlinx.coroutines.sync.withLock 25 26 /** 27 * Code reference from https://source.corp.google.com/android/frameworks/base/packages/SettingsLib/ 28 * src/com/android/settingslib/accessibility/AccessibilityUtils.java 29 */ 30 object AccessibilitySettingsUtil { 31 private const val ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':' 32 private val LOG_TAG = AccessibilitySettingsUtil::class.java.simpleName 33 private val lock = Mutex() 34 35 /** Changes an accessibility component's state. */ disableAccessibilityServicenull36 suspend fun disableAccessibilityService(context: Context, serviceToBeDisabled: ComponentName) { 37 lock.withLock { 38 val settingsEnabledA11yServices = getEnabledServicesFromSettings(context) 39 if ( 40 settingsEnabledA11yServices.isEmpty() || 41 !settingsEnabledA11yServices.contains(serviceToBeDisabled) 42 ) { 43 Log.w( 44 LOG_TAG, 45 "${serviceToBeDisabled.toShortString()} is already disabled " + 46 "or not installed." 47 ) 48 return 49 } 50 51 settingsEnabledA11yServices.remove(serviceToBeDisabled) 52 53 val updatedEnabledServices = 54 settingsEnabledA11yServices 55 .map { it.flattenToString() } 56 .joinToString(separator = ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR.toString()) 57 58 Settings.Secure.putString( 59 context.contentResolver, 60 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 61 updatedEnabledServices 62 ) 63 } 64 } 65 66 /** @return the mutable set of enabled accessibility services. */ getEnabledServicesFromSettingsnull67 fun getEnabledServicesFromSettings(context: Context): MutableSet<ComponentName> { 68 val enabledServicesSetting = 69 Settings.Secure.getString( 70 context.contentResolver, 71 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES 72 ) 73 val enabledServices = mutableSetOf<ComponentName>() 74 if (TextUtils.isEmpty(enabledServicesSetting)) { 75 return enabledServices 76 } 77 78 val colonSplitter: TextUtils.StringSplitter = 79 TextUtils.SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR) 80 colonSplitter.setString(enabledServicesSetting) 81 82 for (componentNameString in colonSplitter) { 83 val enabledService = ComponentName.unflattenFromString(componentNameString) 84 if (enabledService != null) { 85 enabledServices.add(enabledService) 86 } else { 87 Log.e(LOG_TAG, "unable to parse accessibility service $componentNameString") 88 } 89 } 90 91 return enabledServices 92 } 93 } 94