1 /*
2  * Copyright (C) 2020 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 com.android.settings.network;
18 
19 import android.content.Context;
20 import android.net.TetheringManager;
21 
22 import androidx.lifecycle.Lifecycle;
23 import androidx.lifecycle.LifecycleObserver;
24 import androidx.lifecycle.OnLifecycleEvent;
25 import androidx.preference.Preference;
26 import androidx.preference.PreferenceScreen;
27 
28 import com.android.settings.R;
29 import com.android.settings.core.TogglePreferenceController;
30 import com.android.settings.datausage.DataSaverBackend;
31 
32 public abstract class TetherBasePreferenceController extends TogglePreferenceController
33         implements LifecycleObserver,  DataSaverBackend.Listener,
34         TetherEnabler.OnTetherStateUpdateListener {
35 
36     private static final String TAG = "TetherBasePreferenceController";
37     final TetheringManager mTm;
38     private final DataSaverBackend mDataSaverBackend;
39 
40     private TetherEnabler mTetherEnabler;
41     Preference mPreference;
42     private boolean mDataSaverEnabled;
43     int mTetheringState;
44 
TetherBasePreferenceController(Context context, String preferenceKey)45     TetherBasePreferenceController(Context context, String preferenceKey) {
46         super(context, preferenceKey);
47         mTm = context.getSystemService(TetheringManager.class);
48         mDataSaverBackend = new DataSaverBackend(context);
49         mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
50     }
51 
52     /**
53      * Set TetherEnabler for the controller. Call this method to initialize the controller.
54      * @param tetherEnabler The tetherEnabler to set for the controller.
55      */
setTetherEnabler(TetherEnabler tetherEnabler)56     public void setTetherEnabler(TetherEnabler tetherEnabler) {
57         mTetherEnabler = tetherEnabler;
58     }
59 
60     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
onResume()61     public void onResume() {
62         // Must call setEnabler() before
63         if (mTetherEnabler != null) {
64             mTetherEnabler.addListener(this);
65         }
66         mDataSaverBackend.addListener(this);
67     }
68 
69     @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
onPause()70     public void onPause() {
71         if (mTetherEnabler != null) {
72             mTetherEnabler.removeListener(this);
73         }
74         mDataSaverBackend.remListener(this);
75     }
76 
77     @Override
isChecked()78     public boolean isChecked() {
79         return TetherEnabler.isTethering(mTetheringState, getTetherType());
80     }
81 
82     @Override
setChecked(boolean isChecked)83     public boolean setChecked(boolean isChecked) {
84         if (mTetherEnabler == null) {
85             return false;
86         }
87         if (isChecked) {
88             mTetherEnabler.startTethering(getTetherType());
89         } else {
90             mTetherEnabler.stopTethering(getTetherType());
91         }
92         return true;
93     }
94 
95     @Override
displayPreference(PreferenceScreen screen)96     public void displayPreference(PreferenceScreen screen) {
97         super.displayPreference(screen);
98         mPreference = screen.findPreference(mPreferenceKey);
99     }
100 
101     @Override
updateState(Preference preference)102     public void updateState(Preference preference) {
103         super.updateState(preference);
104         if (isAvailable()) {
105             preference.setEnabled(getAvailabilityStatus() != DISABLED_DEPENDENT_SETTING);
106         }
107     }
108 
109     @Override
getAvailabilityStatus()110     public int getAvailabilityStatus() {
111         if (!shouldShow()) {
112             return CONDITIONALLY_UNAVAILABLE;
113         }
114 
115         if (mDataSaverEnabled || !shouldEnable()) {
116             return DISABLED_DEPENDENT_SETTING;
117         }
118         return AVAILABLE;
119     }
120 
121     @Override
getSliceHighlightMenuRes()122     public int getSliceHighlightMenuRes() {
123         return R.string.menu_key_network;
124     }
125 
126     @Override
onTetherStateUpdated(@etherEnabler.TetheringState int state)127     public void onTetherStateUpdated(@TetherEnabler.TetheringState int state) {
128         mTetheringState = state;
129         updateState(mPreference);
130     }
131 
132     @Override
onDataSaverChanged(boolean isDataSaving)133     public void onDataSaverChanged(boolean isDataSaving) {
134         mDataSaverEnabled = isDataSaving;
135     }
136 
137     @Override
onAllowlistStatusChanged(int uid, boolean isAllowlisted)138     public void onAllowlistStatusChanged(int uid, boolean isAllowlisted) {
139     }
140 
141     @Override
onDenylistStatusChanged(int uid, boolean isDenylisted)142     public void onDenylistStatusChanged(int uid, boolean isDenylisted) {
143     }
144 
145     /**
146      * Used to enable or disable the preference.
147      * @return true if the preference should be enabled; false otherwise.
148      */
shouldEnable()149     public abstract boolean shouldEnable();
150 
151     /**
152      * Used to determine visibility of the preference.
153      * @return true if the preference should be visible; false otherwise.
154      */
shouldShow()155     public abstract boolean shouldShow();
156 
157     /**
158      * Get the type of tether interface that is controlled by the preference.
159      * @return the tether interface, like {@link ConnectivityManager#TETHERING_WIFI}
160      */
getTetherType()161     public abstract int getTetherType();
162 }
163