1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.settings.display.darkmode;
16 
17 import android.content.BroadcastReceiver;
18 import android.content.Context;
19 import android.content.Intent;
20 import android.content.IntentFilter;
21 import android.database.ContentObserver;
22 import android.net.Uri;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.os.PowerManager;
26 import android.provider.Settings;
27 import android.util.Log;
28 import com.android.internal.annotations.VisibleForTesting;
29 
30 /**
31  * Observes changes for dark night settings*/
32 public class DarkModeObserver {
33     private static final String TAG = "DarkModeObserver";
34     private ContentObserver mContentObserver;
35     private final BroadcastReceiver mBatterySaverReceiver = new BroadcastReceiver() {
36         @Override
37         public void onReceive(Context context, Intent intent) {
38             mCallback.run();
39         }
40     };
41     private Runnable mCallback;
42     private Context mContext;
43 
DarkModeObserver(Context context)44     public DarkModeObserver(Context context) {
45         mContext = context;
46         mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
47             @Override
48             public void onChange(boolean selfChange, Uri uri) {
49                 super.onChange(selfChange, uri);
50                 final String setting = uri == null ? null : uri.getLastPathSegment();
51                 if (setting != null && mCallback != null) {
52                     mCallback.run();
53                 }
54             }
55         };
56     }
57 
58     /**
59      * subscribe callback when night mode changed in the database
60      *
61      * @param callback the callback that gets triggered when subscribed
62      */
subscribe(Runnable callback)63     public void subscribe(Runnable callback) {
64         callback.run();
65         mCallback = callback;
66         final Uri uri = Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE);
67         final Uri customStart =
68                 Settings.Secure.getUriFor(Settings.Secure.DARK_THEME_CUSTOM_START_TIME);
69         final Uri customEnd =
70                 Settings.Secure.getUriFor(Settings.Secure.DARK_THEME_CUSTOM_END_TIME);
71         mContext.getContentResolver()
72                 .registerContentObserver(uri, false, mContentObserver);
73         mContext.getContentResolver()
74                 .registerContentObserver(customStart, false, mContentObserver);
75         mContext.getContentResolver()
76                 .registerContentObserver(customEnd, false, mContentObserver);
77         final IntentFilter batteryFilter = new IntentFilter();
78         batteryFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
79         mContext.registerReceiver(
80                 mBatterySaverReceiver, batteryFilter);
81     }
82 
83     /**
84      * unsubscribe from dark ui database changes
85      */
unsubscribe()86     public void unsubscribe() {
87         mContext.getContentResolver().unregisterContentObserver(mContentObserver);
88         try {
89             mContext.unregisterReceiver(mBatterySaverReceiver);
90         } catch (IllegalArgumentException e) {
91             /* Ignore: unregistering an unregistered receiver */
92             Log.w(TAG, e.getMessage());
93         }
94         // NO-OP
95         mCallback = null;
96     }
97 
98     @VisibleForTesting
setContentObserver(ContentObserver co)99     protected void setContentObserver(ContentObserver co) {
100         mContentObserver = co;
101     }
102 
103     @VisibleForTesting
getContentObserver()104     protected ContentObserver getContentObserver() {
105         return mContentObserver;
106     }
107 }
108