1 /*
2  * Copyright (C) 2019 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 static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
20 import static androidx.lifecycle.Lifecycle.Event.ON_START;
21 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
22 
23 import android.content.Context;
24 import android.os.Looper;
25 import android.provider.Settings;
26 import android.telephony.SubscriptionInfo;
27 import android.telephony.SubscriptionManager;
28 
29 import androidx.lifecycle.Lifecycle;
30 import androidx.lifecycle.LifecycleObserver;
31 import androidx.lifecycle.OnLifecycleEvent;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * A proxy to the subscription manager
38  */
39 public class ProxySubscriptionManager implements LifecycleObserver {
40 
41     /**
42      * Interface for monitor active subscriptions list changing
43      */
44     public interface OnActiveSubscriptionChangedListener {
45         /**
46          * When active subscriptions list get changed
47          */
onChanged()48         void onChanged();
49         /**
50          * get Lifecycle of listener
51          *
52          * @return Returns Lifecycle.
53          */
getLifecycle()54         default Lifecycle getLifecycle() {
55             return null;
56         }
57     }
58 
59     /**
60      * Get proxy instance to subscription manager
61      *
62      * @return proxy to subscription manager
63      */
getInstance(Context context)64     public static ProxySubscriptionManager getInstance(Context context) {
65         if (sSingleton != null) {
66             return sSingleton;
67         }
68         sSingleton = new ProxySubscriptionManager(context.getApplicationContext());
69         return sSingleton;
70     }
71 
72     private static ProxySubscriptionManager sSingleton;
73 
ProxySubscriptionManager(Context context)74     private ProxySubscriptionManager(Context context) {
75         final Looper looper = Looper.getMainLooper();
76 
77         mActiveSubscriptionsListeners =
78                 new ArrayList<OnActiveSubscriptionChangedListener>();
79 
80         mSubscriptionMonitor = new ActiveSubsciptionsListener(looper, context) {
81             public void onChanged() {
82                 notifyAllListeners();
83             }
84         };
85         mAirplaneModeMonitor = new GlobalSettingsChangeListener(looper,
86                 context, Settings.Global.AIRPLANE_MODE_ON) {
87             public void onChanged(String field) {
88                 mSubscriptionMonitor.clearCache();
89                 notifyAllListeners();
90             }
91         };
92 
93         mSubscriptionMonitor.start();
94     }
95 
96     private Lifecycle mLifecycle;
97     private ActiveSubsciptionsListener mSubscriptionMonitor;
98     private GlobalSettingsChangeListener mAirplaneModeMonitor;
99 
100     private List<OnActiveSubscriptionChangedListener> mActiveSubscriptionsListeners;
101 
notifyAllListeners()102     private void notifyAllListeners() {
103         for (OnActiveSubscriptionChangedListener listener : mActiveSubscriptionsListeners) {
104             final Lifecycle lifecycle = listener.getLifecycle();
105             if ((lifecycle == null)
106                     || (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED))) {
107                 listener.onChanged();
108             }
109         }
110     }
111 
112     /**
113      * Lifecycle for data within proxy
114      *
115      * @param lifecycle life cycle to reference
116      */
setLifecycle(Lifecycle lifecycle)117     public void setLifecycle(Lifecycle lifecycle) {
118         if (mLifecycle == lifecycle) {
119             return;
120         }
121         if (mLifecycle != null) {
122             mLifecycle.removeObserver(this);
123         }
124         if (lifecycle != null) {
125             lifecycle.addObserver(this);
126         }
127         mLifecycle = lifecycle;
128         mAirplaneModeMonitor.notifyChangeBasedOn(lifecycle);
129     }
130 
131     @OnLifecycleEvent(ON_START)
onStart()132     void onStart() {
133         mSubscriptionMonitor.start();
134     }
135 
136     @OnLifecycleEvent(ON_STOP)
onStop()137     void onStop() {
138         mSubscriptionMonitor.stop();
139     }
140 
141     @OnLifecycleEvent(ON_DESTROY)
onDestroy()142     void onDestroy() {
143         mSubscriptionMonitor.close();
144         mAirplaneModeMonitor.close();
145 
146         if (mLifecycle != null) {
147             mLifecycle.removeObserver(this);
148             mLifecycle = null;
149 
150             sSingleton = null;
151         }
152     }
153 
154     /**
155      * Get SubscriptionManager
156      *
157      * @return a SubscriptionManager
158      */
get()159     public SubscriptionManager get() {
160         return mSubscriptionMonitor.getSubscriptionManager();
161     }
162 
163     /**
164      * Get current max. number active subscription info(s) been setup within device
165      *
166      * @return max. number of active subscription info(s)
167      */
getActiveSubscriptionInfoCountMax()168     public int getActiveSubscriptionInfoCountMax() {
169         return mSubscriptionMonitor.getActiveSubscriptionInfoCountMax();
170     }
171 
172     /**
173      * Get a list of active subscription info
174      *
175      * @return A list of active subscription info
176      */
getActiveSubscriptionsInfo()177     public List<SubscriptionInfo> getActiveSubscriptionsInfo() {
178         return mSubscriptionMonitor.getActiveSubscriptionsInfo();
179     }
180 
181     /**
182      * Get an active subscription info with given subscription ID
183      *
184      * @param subId target subscription ID
185      * @return A subscription info which is active list
186      */
getActiveSubscriptionInfo(int subId)187     public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
188         return mSubscriptionMonitor.getActiveSubscriptionInfo(subId);
189     }
190 
191     /**
192      * Get a list of accessible subscription info
193      *
194      * @return A list of accessible subscription info
195      */
getAccessibleSubscriptionsInfo()196     public List<SubscriptionInfo> getAccessibleSubscriptionsInfo() {
197         return mSubscriptionMonitor.getAccessibleSubscriptionsInfo();
198     }
199 
200     /**
201      * Get an accessible subscription info with given subscription ID
202      *
203      * @param subId target subscription ID
204      * @return A subscription info which is accessible list
205      */
getAccessibleSubscriptionInfo(int subId)206     public SubscriptionInfo getAccessibleSubscriptionInfo(int subId) {
207         return mSubscriptionMonitor.getAccessibleSubscriptionInfo(subId);
208     }
209 
210     /**
211      * Clear data cached within proxy
212      */
clearCache()213     public void clearCache() {
214         mSubscriptionMonitor.clearCache();
215     }
216 
217     /**
218      * Add listener to active subscriptions monitor list
219      *
220      * @param listener listener to active subscriptions change
221      */
addActiveSubscriptionsListener(OnActiveSubscriptionChangedListener listener)222     public void addActiveSubscriptionsListener(OnActiveSubscriptionChangedListener listener) {
223         if (mActiveSubscriptionsListeners.contains(listener)) {
224             return;
225         }
226         mActiveSubscriptionsListeners.add(listener);
227     }
228 
229     /**
230      * Remove listener from active subscriptions monitor list
231      *
232      * @param listener listener to active subscriptions change
233      */
removeActiveSubscriptionsListener(OnActiveSubscriptionChangedListener listener)234     public void removeActiveSubscriptionsListener(OnActiveSubscriptionChangedListener listener) {
235         mActiveSubscriptionsListeners.remove(listener);
236     }
237 }
238