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 androidx.window.common;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.provider.Settings;
28 
29 import androidx.window.util.BaseDataProducer;
30 
31 import java.util.Optional;
32 
33 /**
34  * Implementation of {@link androidx.window.util.DataProducer} that provides the device posture
35  * as an {@link Integer} from a value stored in {@link Settings}.
36  */
37 public final class SettingsDevicePostureProducer extends BaseDataProducer<Integer> {
38     private static final String DEVICE_POSTURE = "device_posture";
39 
40     private final Uri mDevicePostureUri =
41             Settings.Global.getUriFor(DEVICE_POSTURE);
42 
43     private final ContentResolver mResolver;
44     private final ContentObserver mObserver;
45     private boolean mRegisteredObservers;
46 
SettingsDevicePostureProducer(@onNull Context context)47     public SettingsDevicePostureProducer(@NonNull Context context) {
48         mResolver = context.getContentResolver();
49         mObserver = new SettingsObserver();
50     }
51 
52     @Override
53     @Nullable
getData()54     public Optional<Integer> getData() {
55         int posture = Settings.Global.getInt(mResolver, DEVICE_POSTURE, -1);
56         return posture == -1 ? Optional.empty() : Optional.of(posture);
57     }
58 
59     /**
60      * Registers settings observers, if needed. When settings observers are registered for this
61      * producer callbacks for changes in data will be triggered.
62      */
registerObserversIfNeeded()63     public void registerObserversIfNeeded() {
64         if (mRegisteredObservers) {
65             return;
66         }
67         mRegisteredObservers = true;
68         mResolver.registerContentObserver(mDevicePostureUri, false /* notifyForDescendants */,
69                 mObserver /* ContentObserver */);
70     }
71 
72     /**
73      * Unregisters settings observers, if needed. When settings observers are unregistered for this
74      * producer callbacks for changes in data will not be triggered.
75      */
unregisterObserversIfNeeded()76     public void unregisterObserversIfNeeded() {
77         if (!mRegisteredObservers) {
78             return;
79         }
80         mRegisteredObservers = false;
81         mResolver.unregisterContentObserver(mObserver);
82     }
83 
84     private final class SettingsObserver extends ContentObserver {
SettingsObserver()85         SettingsObserver() {
86             super(new Handler(Looper.getMainLooper()));
87         }
88 
89         @Override
onChange(boolean selfChange, Uri uri)90         public void onChange(boolean selfChange, Uri uri) {
91             if (mDevicePostureUri.equals(uri)) {
92                 notifyDataChanged();
93             }
94         }
95     }
96 }
97