• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.settingslib.deviceinfo;
18 
19 import android.bluetooth.BluetoothAdapter;
20 import android.content.Context;
21 import android.net.ConnectivityManager;
22 import android.net.wifi.WifiManager;
23 import android.os.PersistableBundle;
24 import android.telephony.CarrierConfigManager;
25 import android.telephony.SubscriptionManager;
26 import android.telephony.ims.ImsMmTelManager;
27 import android.telephony.ims.RegistrationManager;
28 import android.util.Log;
29 
30 import androidx.annotation.VisibleForTesting;
31 import androidx.preference.Preference;
32 import androidx.preference.PreferenceScreen;
33 
34 import com.android.settingslib.R;
35 import com.android.settingslib.core.lifecycle.Lifecycle;
36 
37 import java.util.concurrent.ExecutorService;
38 import java.util.concurrent.Executors;
39 import java.util.concurrent.Semaphore;
40 import java.util.concurrent.TimeUnit;
41 import java.util.concurrent.atomic.AtomicBoolean;
42 import java.util.function.Consumer;
43 
44 /**
45  * Preference controller for IMS status
46  */
47 public abstract class AbstractImsStatusPreferenceController
48         extends AbstractConnectivityPreferenceController {
49 
50     private static final String LOG_TAG = "AbstractImsPrefController";
51 
52     @VisibleForTesting
53     static final String KEY_IMS_REGISTRATION_STATE = "ims_reg_state";
54 
55     private static final long MAX_THREAD_BLOCKING_TIME_MS = 2000;
56 
57     private static final String[] CONNECTIVITY_INTENTS = {
58             BluetoothAdapter.ACTION_STATE_CHANGED,
59             ConnectivityManager.CONNECTIVITY_ACTION,
60             WifiManager.ACTION_LINK_CONFIGURATION_CHANGED,
61             WifiManager.NETWORK_STATE_CHANGED_ACTION,
62     };
63 
64     private Preference mImsStatus;
65 
AbstractImsStatusPreferenceController(Context context, Lifecycle lifecycle)66     public AbstractImsStatusPreferenceController(Context context,
67             Lifecycle lifecycle) {
68         super(context, lifecycle);
69     }
70 
71     @Override
isAvailable()72     public boolean isAvailable() {
73         final CarrierConfigManager configManager =
74                 mContext.getSystemService(CarrierConfigManager.class);
75         final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
76         PersistableBundle config = null;
77         if (configManager != null) {
78             config = configManager.getConfigForSubId(subId);
79         }
80         return config != null && config.getBoolean(
81                 CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL);
82     }
83 
84     @Override
getPreferenceKey()85     public String getPreferenceKey() {
86         return KEY_IMS_REGISTRATION_STATE;
87     }
88 
89     @Override
displayPreference(PreferenceScreen screen)90     public void displayPreference(PreferenceScreen screen) {
91         super.displayPreference(screen);
92         mImsStatus = screen.findPreference(KEY_IMS_REGISTRATION_STATE);
93         updateConnectivity();
94     }
95 
96     @Override
getConnectivityIntents()97     protected String[] getConnectivityIntents() {
98         return CONNECTIVITY_INTENTS;
99     }
100 
101     @Override
updateConnectivity()102     protected void updateConnectivity() {
103         if (mImsStatus == null) {
104             return;
105         }
106         final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
107         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
108             mImsStatus.setSummary(R.string.ims_reg_status_not_registered);
109             return;
110         }
111         final ExecutorService executors = Executors.newSingleThreadExecutor();
112         final StateCallback stateCallback = new StateCallback();
113 
114         final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId);
115         try {
116             imsMmTelManager.getRegistrationState(executors, stateCallback);
117         } catch (Exception ex) {
118         }
119 
120         mImsStatus.setSummary(stateCallback.waitUntilResult()
121                 ? R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered);
122 
123         try {
124             executors.shutdownNow();
125         } catch (Exception exception) {
126         }
127     }
128 
129     private final class StateCallback extends AtomicBoolean implements Consumer<Integer> {
StateCallback()130         private StateCallback() {
131             super(false);
132             mSemaphore = new Semaphore(0);
133         }
134 
135         private final Semaphore mSemaphore;
136 
accept(Integer state)137         public void accept(Integer state) {
138             set(state == RegistrationManager.REGISTRATION_STATE_REGISTERED);
139             try {
140                 mSemaphore.release();
141             } catch (Exception ex) {
142             }
143         }
144 
waitUntilResult()145         public boolean waitUntilResult() {
146             try {
147                 if (!mSemaphore.tryAcquire(MAX_THREAD_BLOCKING_TIME_MS, TimeUnit.MILLISECONDS)) {
148                     Log.w(LOG_TAG, "IMS registration state query timeout");
149                     return false;
150                 }
151             } catch (Exception ex) {
152             }
153             return get();
154         }
155     }
156 }
157