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 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 /**
32  * Observes changes for dark night settings*/
33 public class DarkModeObserver {
34     private static final String TAG = "DarkModeObserver";
35     private ContentObserver mContentObserver;
36     private final BroadcastReceiver mBatterySaverReceiver = new BroadcastReceiver() {
37         @Override
38         public void onReceive(Context context, Intent intent) {
39             mCallback.run();
40         }
41     };
42     private Runnable mCallback;
43     private Context mContext;
44 
DarkModeObserver(Context context)45     public DarkModeObserver(Context context) {
46         mContext = context;
47         mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
48             @Override
49             public void onChange(boolean selfChange, Uri uri) {
50                 super.onChange(selfChange, uri);
51                 final String setting = uri == null ? null : uri.getLastPathSegment();
52                 if (setting != null && mCallback != null) {
53                     mCallback.run();
54                 }
55             }
56         };
57     }
58 
59     /**
60      * subscribe callback when night mode changed in the database
61      *
62      * @param callback the callback that gets triggered when subscribed
63      */
subscribe(Runnable callback)64     public void subscribe(Runnable callback) {
65         callback.run();
66         mCallback = callback;
67         final Uri uri = Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE);
68         final Uri customType =
69                 Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE_CUSTOM_TYPE);
70         final Uri customStart =
71                 Settings.Secure.getUriFor(Settings.Secure.DARK_THEME_CUSTOM_START_TIME);
72         final Uri customEnd =
73                 Settings.Secure.getUriFor(Settings.Secure.DARK_THEME_CUSTOM_END_TIME);
74         mContext.getContentResolver()
75                 .registerContentObserver(uri, false, mContentObserver);
76         mContext.getContentResolver()
77                 .registerContentObserver(customType, false, mContentObserver);
78         mContext.getContentResolver()
79                 .registerContentObserver(customStart, false, mContentObserver);
80         mContext.getContentResolver()
81                 .registerContentObserver(customEnd, false, mContentObserver);
82         final IntentFilter batteryFilter = new IntentFilter();
83         batteryFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
84         mContext.registerReceiver(
85                 mBatterySaverReceiver, batteryFilter);
86     }
87 
88     /**
89      * unsubscribe from dark ui database changes
90      */
unsubscribe()91     public void unsubscribe() {
92         mContext.getContentResolver().unregisterContentObserver(mContentObserver);
93         try {
94             mContext.unregisterReceiver(mBatterySaverReceiver);
95         } catch (IllegalArgumentException e) {
96             /* Ignore: unregistering an unregistered receiver */
97             Log.w(TAG, e.getMessage());
98         }
99         // NO-OP
100         mCallback = null;
101     }
102 
103     @VisibleForTesting
setContentObserver(ContentObserver co)104     protected void setContentObserver(ContentObserver co) {
105         mContentObserver = co;
106     }
107 
108     @VisibleForTesting
getContentObserver()109     protected ContentObserver getContentObserver() {
110         return mContentObserver;
111     }
112 }
113