• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import android.text.TextUtils;
29 import android.util.Log;
30 
31 import androidx.window.util.BaseDataProducer;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Optional;
36 
37 /**
38  * Implementation of {@link androidx.window.util.DataProducer} that produces
39  * {@link CommonDisplayFeature} parsed from a string stored in {@link Settings}.
40  */
41 public final class SettingsDisplayFeatureProducer
42         extends BaseDataProducer<List<DisplayFeature>> {
43     private static final boolean DEBUG = false;
44     private static final String TAG = "SettingsDisplayFeatureProducer";
45     private static final String DISPLAY_FEATURES = "display_features";
46 
47     private final Uri mDisplayFeaturesUri =
48             Settings.Global.getUriFor(DISPLAY_FEATURES);
49 
50     private final ContentResolver mResolver;
51     private final ContentObserver mObserver;
52     private boolean mRegisteredObservers;
53 
SettingsDisplayFeatureProducer(@onNull Context context)54     public SettingsDisplayFeatureProducer(@NonNull Context context) {
55         mResolver = context.getContentResolver();
56         mObserver = new SettingsObserver();
57     }
58 
59     @Override
60     @Nullable
getData()61     public Optional<List<DisplayFeature>> getData() {
62         String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES);
63         if (displayFeaturesString == null) {
64             return Optional.empty();
65         }
66 
67         List<DisplayFeature> features = new ArrayList<>();
68         if (TextUtils.isEmpty(displayFeaturesString)) {
69             return Optional.of(features);
70         }
71         String[] featureStrings =  displayFeaturesString.split(";");
72 
73         for (String featureString : featureStrings) {
74             CommonDisplayFeature feature;
75             try {
76                 feature = CommonDisplayFeature.parseFromString(featureString);
77             } catch (IllegalArgumentException e) {
78                 if (DEBUG) {
79                     Log.w(TAG, "Failed to parse display feature: " + featureString, e);
80                 }
81                 continue;
82             }
83             features.add(feature);
84         }
85         return Optional.of(features);
86     }
87 
88     /**
89      * Registers settings observers, if needed. When settings observers are registered for this
90      * producer callbacks for changes in data will be triggered.
91      */
registerObserversIfNeeded()92     public void registerObserversIfNeeded() {
93         if (mRegisteredObservers) {
94             return;
95         }
96         mRegisteredObservers = true;
97         mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */,
98                 mObserver /* ContentObserver */);
99     }
100 
101     /**
102      * Unregisters settings observers, if needed. When settings observers are unregistered for this
103      * producer callbacks for changes in data will not be triggered.
104      */
unregisterObserversIfNeeded()105     public void unregisterObserversIfNeeded() {
106         if (!mRegisteredObservers) {
107             return;
108         }
109         mRegisteredObservers = false;
110         mResolver.unregisterContentObserver(mObserver);
111     }
112 
113     private final class SettingsObserver extends ContentObserver {
SettingsObserver()114         SettingsObserver() {
115             super(new Handler(Looper.getMainLooper()));
116         }
117 
118         @Override
onChange(boolean selfChange, Uri uri)119         public void onChange(boolean selfChange, Uri uri) {
120             if (mDisplayFeaturesUri.equals(uri)) {
121                 notifyDataChanged();
122             }
123         }
124     }
125 }
126