1 /* 2 * Copyright (C) 2021 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 17 package com.android.car.settings.qc; 18 19 import android.content.Context; 20 import android.net.Uri; 21 import android.util.ArrayMap; 22 23 import androidx.annotation.NonNull; 24 import androidx.annotation.VisibleForTesting; 25 26 import com.android.car.qc.QCItem; 27 import com.android.car.qc.provider.BaseQCProvider; 28 import com.android.car.settings.R; 29 import com.android.settingslib.utils.ThreadUtils; 30 31 import java.util.Map; 32 import java.util.Set; 33 34 /** 35 * Remote Quick Control provider for CarSettings. 36 */ 37 public class SettingsQCProvider extends BaseQCProvider { 38 private final Map<Uri, SettingsQCItem> mSubscribedItems = new ArrayMap<>(); 39 @VisibleForTesting 40 final Map<Uri, SettingsQCBackgroundWorker> mSubscribedWorkers = new ArrayMap<>(); 41 42 private Set<String> mAllowListedPackages; 43 44 @Override onCreate()45 public boolean onCreate() { 46 boolean returnVal = super.onCreate(); 47 mAllowListedPackages = Set.of(getContext().getResources().getStringArray( 48 R.array.settings_qc_provider_package_allowlist)); 49 return returnVal; 50 } 51 52 @Override onBind(Uri uri)53 public QCItem onBind(Uri uri) { 54 if (SettingsQCRegistry.isValidUri(uri)) { 55 Context context = getContext(); 56 return getQCItemFromUri(context, uri).getQCItem(); 57 } 58 throw new IllegalArgumentException("Unrecognized uri: " + uri); 59 } 60 61 @Override onSubscribed(Uri uri)62 public void onSubscribed(Uri uri) { 63 if (SettingsQCRegistry.isValidUri(uri)) { 64 Context context = getContext(); 65 SettingsQCItem qcItem = getQCItemFromUri(context, uri); 66 ThreadUtils.postOnMainThread(() -> startBackgroundWorker(qcItem, uri)); 67 } 68 } 69 70 @Override onUnsubscribed(Uri uri)71 public void onUnsubscribed(Uri uri) { 72 ThreadUtils.postOnMainThread(() -> stopBackgroundWorker(uri)); 73 } 74 75 @Override onDestroy(Uri uri)76 public void onDestroy(Uri uri) { 77 ThreadUtils.postOnMainThread(() -> SettingsQCBackgroundWorker.shutdown(uri)); 78 } 79 80 @Override shutdown()81 public void shutdown() { 82 ThreadUtils.postOnMainThread(SettingsQCBackgroundWorker::shutdown); 83 } 84 getQCItemFromUri(Context context, Uri uri)85 private SettingsQCItem getQCItemFromUri(Context context, Uri uri) { 86 if (mSubscribedItems.containsKey(uri)) { 87 return mSubscribedItems.get(uri); 88 } 89 Uri newUri = SettingsQCRegistry.removeParameterFromUri(uri); 90 Class clazz = SettingsQCRegistry.getQCClassByUri(newUri); 91 if (clazz == null) { 92 throw new IllegalArgumentException("No QCItem found for uri: " + uri); 93 } 94 95 return SettingsQCItem.createInstance(context, clazz); 96 } 97 startBackgroundWorker(SettingsQCItem qcItem, Uri uri)98 private void startBackgroundWorker(SettingsQCItem qcItem, Uri uri) { 99 Class workerClass = qcItem.getBackgroundWorkerClass(); 100 if (workerClass == null) { 101 return; 102 } 103 104 if (mSubscribedWorkers.containsKey(uri)) { 105 return; 106 } 107 108 SettingsQCBackgroundWorker worker = SettingsQCBackgroundWorker.getInstance( 109 getContext(), qcItem, uri); 110 mSubscribedWorkers.put(uri, worker); 111 worker.subscribe(); 112 mSubscribedItems.put(uri, qcItem); 113 } 114 stopBackgroundWorker(Uri uri)115 private void stopBackgroundWorker(Uri uri) { 116 SettingsQCBackgroundWorker worker = mSubscribedWorkers.get(uri); 117 if (worker != null) { 118 worker.unsubscribe(); 119 mSubscribedWorkers.remove(uri); 120 mSubscribedItems.remove(uri); 121 } 122 } 123 124 @NonNull 125 @Override getAllowlistedPackages()126 protected Set<String> getAllowlistedPackages() { 127 return mAllowListedPackages; 128 } 129 } 130