1e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk/** 2e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Copyright (C) 2016 The Android Open Source Project 3e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 4e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * you may not use this file except in compliance with the License. 6e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * You may obtain a copy of the License at 7e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 8e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 10e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * See the License for the specific language governing permissions and 14e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * limitations under the License. 15e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 16e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpackage com.android.server.vr; 17e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 18e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull; 19e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.BroadcastReceiver; 20e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ContentResolver; 21e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.Context; 22e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.Intent; 23e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.database.ContentObserver; 24e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.net.Uri; 25e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler; 26e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.UserHandle; 27e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings; 28e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.util.ArraySet; 29e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 30e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport java.util.Objects; 31e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport java.util.Set; 32e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 33e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk/** 34e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Detects changes in a given setting. 35e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 36e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide 37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 38e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class SettingsObserver { 39e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 40e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final String mSecureSettingName; 4149506e089103e8fe38d10e0589688e51cceacaf2Ruben Brunk private final BroadcastReceiver mSettingRestoreReceiver; 42e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final ContentObserver mContentObserver; 43e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final Set<SettingChangeListener> mSettingsListeners = new ArraySet<>(); 44e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 45e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 46e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Implement this to receive callbacks when the setting tracked by this observer changes. 47e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 48e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public interface SettingChangeListener { 49e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 50e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 51e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Called when the tracked setting has changed. 52e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 53e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk void onSettingChanged(); 54e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 55e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 56e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 57e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Called when the tracked setting has been restored for a particular user. 58e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 59e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param prevValue the previous value of the setting. 60e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param newValue the new value of the setting. 61e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param userId the user ID for which this setting has been restored. 62e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 63e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk void onSettingRestored(String prevValue, String newValue, int userId); 64e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 65e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 66e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private SettingsObserver(@NonNull final Context context, @NonNull final Handler handler, 67e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @NonNull final Uri settingUri, @NonNull final String secureSettingName) { 68e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 69e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mSecureSettingName = secureSettingName; 7049506e089103e8fe38d10e0589688e51cceacaf2Ruben Brunk mSettingRestoreReceiver = new BroadcastReceiver() { 71e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 72e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onReceive(Context context, Intent intent) { 73e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) { 74e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk String element = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); 75e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (Objects.equals(element, secureSettingName)) { 76e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk String prevValue = intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE); 77e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); 78e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk sendSettingRestored(prevValue, newValue, getSendingUserId()); 79e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 80e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 81e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 82e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk }; 83e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 84e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContentObserver = new ContentObserver(handler) { 85e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 86e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onChange(boolean selfChange, Uri uri) { 87e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (uri == null || settingUri.equals(uri)) { 88e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk sendSettingChanged(); 89e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 90e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 91e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk }; 92e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 93e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk ContentResolver resolver = context.getContentResolver(); 94e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk resolver.registerContentObserver(settingUri, false, mContentObserver, 95e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk UserHandle.USER_ALL); 96e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 97e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 98e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 99e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Create a SettingsObserver instance. 100e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 101e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param context the context to query for settings changes. 102e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param handler the handler to use for a settings ContentObserver. 103e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param settingName the setting to track. 104e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return a SettingsObserver instance. 105e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 106e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public static SettingsObserver build(@NonNull Context context, @NonNull Handler handler, 107e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @NonNull String settingName) { 108e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Uri settingUri = Settings.Secure.getUriFor(settingName); 109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 110e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return new SettingsObserver(context, handler, settingUri, settingName); 111e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 112e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 113e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 114e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Add a listener for setting changes. 115e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 116e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param listener a {@link SettingChangeListener} instance. 117e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 118e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void addListener(@NonNull SettingChangeListener listener) { 119e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mSettingsListeners.add(listener); 120e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 121e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 122e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 123e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Remove a listener for setting changes. 124e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 125e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param listener a {@link SettingChangeListener} instance. 126e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 127e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void removeListener(@NonNull SettingChangeListener listener) { 128e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mSettingsListeners.remove(listener); 129e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 130e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 131e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 132e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private void sendSettingChanged() { 133e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk for (SettingChangeListener l : mSettingsListeners) { 134e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk l.onSettingChanged(); 135e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 136e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 137e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 138e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private void sendSettingRestored(final String prevValue, final String newValue, final int userId) { 139e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk for (SettingChangeListener l : mSettingsListeners) { 140e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk l.onSettingRestored(prevValue, newValue, userId); 141e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 142e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 143e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 144e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk} 145