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