CarrierActionAgent.java revision afffe1b3e671ba002a5bf79a2f59ec8e6c8bd6a3
1/* 2 * Copyright (C) 2016 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 */ 16package com.android.internal.telephony; 17 18import android.content.BroadcastReceiver; 19import android.content.Context; 20import android.content.Intent; 21import android.content.IntentFilter; 22import android.database.ContentObserver; 23import android.os.AsyncResult; 24import android.os.Handler; 25import android.os.Message; 26import android.os.Registrant; 27import android.os.RegistrantList; 28import android.provider.Settings; 29import android.telephony.Rlog; 30import android.util.LocalLog; 31import android.util.Log; 32 33import com.android.internal.annotations.VisibleForTesting; 34import com.android.internal.util.IndentingPrintWriter; 35import java.io.FileDescriptor; 36import java.io.PrintWriter; 37 38/** 39 * Carrier Action Agent(CAA) paired with 40 * {@link com.android.internal.telephony.CarrierSignalAgent CarrierSignalAgent}, 41 * serves as an agent to dispatch carrier actions from carrier apps to different telephony modules, 42 * {@link android.telephony.TelephonyManager#carrierActionSetRadioEnabled(int, boolean) 43 * carrierActionSetRadioEnabled} for example. 44 * 45 * CAA supports dynamic registration where different telephony modules could listen for a specific 46 * carrier action event and implement their own handler. CCA will dispatch the event to all 47 * interested parties and maintain the received action states internally for future inspection. 48 * Each CarrierActionAgent is associated with a phone object. 49 */ 50public class CarrierActionAgent extends Handler { 51 private static final String LOG_TAG = "CarrierActionAgent"; 52 private static final boolean DBG = true; 53 private static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE); 54 55 /** A list of carrier actions */ 56 public static final int CARRIER_ACTION_SET_METERED_APNS_ENABLED = 0; 57 public static final int CARRIER_ACTION_SET_RADIO_ENABLED = 1; 58 public static final int CARRIER_ACTION_RESET = 2; 59 60 /** Member variables */ 61 private final Phone mPhone; 62 /** registrant list per carrier action */ 63 private RegistrantList mMeteredApnEnableRegistrants = new RegistrantList(); 64 private RegistrantList mRadioEnableRegistrants = new RegistrantList(); 65 /** local log for carrier actions */ 66 private LocalLog mMeteredApnEnabledLog = new LocalLog(10); 67 private LocalLog mRadioEnabledLog = new LocalLog(10); 68 /** carrier actions, true by default */ 69 private Boolean mCarrierActionOnMeteredApnEnabled = true; 70 private Boolean mCarrierActionOnRadioEnabled = true; 71 /** content observer for APM change */ 72 private final SettingsObserver mSettingsObserver; 73 74 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 75 @Override 76 public void onReceive(Context context, Intent intent) { 77 final String action = intent.getAction(); 78 final String iccState = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 79 if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)){ 80 if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(iccState) || 81 IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(iccState)) { 82 sendEmptyMessage(CARRIER_ACTION_RESET); 83 } 84 } 85 } 86 }; 87 88 private class SettingsObserver extends ContentObserver { 89 SettingsObserver() { 90 super(null); 91 } 92 93 @Override 94 public void onChange(boolean selfChange) { 95 if (Settings.Global.getInt(mPhone.getContext().getContentResolver(), 96 Settings.Global.AIRPLANE_MODE_ON, 0) != 0) { 97 sendEmptyMessage(CARRIER_ACTION_RESET); 98 } 99 } 100 } 101 102 /** Constructor */ 103 public CarrierActionAgent(Phone phone) { 104 mPhone = phone; 105 mPhone.getContext().registerReceiver(mReceiver, 106 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 107 mSettingsObserver = new SettingsObserver(); 108 mPhone.getContext().getContentResolver().registerContentObserver( 109 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), 110 false, mSettingsObserver); 111 if (DBG) log("Creating CarrierActionAgent"); 112 } 113 114 @Override 115 public void handleMessage(Message msg) { 116 switch (msg.what) { 117 case CARRIER_ACTION_SET_METERED_APNS_ENABLED: 118 mCarrierActionOnMeteredApnEnabled = (boolean) msg.obj; 119 log("SET_METERED_APNS_ENABLED: " + mCarrierActionOnMeteredApnEnabled); 120 mMeteredApnEnabledLog.log("SET_METERED_APNS_ENABLED: " 121 + mCarrierActionOnMeteredApnEnabled); 122 mMeteredApnEnableRegistrants.notifyRegistrants( 123 new AsyncResult(null, mCarrierActionOnMeteredApnEnabled, null)); 124 break; 125 case CARRIER_ACTION_SET_RADIO_ENABLED: 126 mCarrierActionOnRadioEnabled = (boolean) msg.obj; 127 log("SET_RADIO_ENABLED: " + mCarrierActionOnRadioEnabled); 128 mRadioEnabledLog.log("SET_RADIO_ENABLED: " + mCarrierActionOnRadioEnabled); 129 mRadioEnableRegistrants.notifyRegistrants( 130 new AsyncResult(null, mCarrierActionOnRadioEnabled, null)); 131 break; 132 case CARRIER_ACTION_RESET: 133 log("CARRIER_ACTION_RESET"); 134 carrierActionSetMeteredApnsEnabled(true); 135 carrierActionSetRadioEnabled(true); 136 // notify configured carrier apps for reset 137 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers( 138 new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET)); 139 break; 140 default: 141 loge("Unknown carrier action: " + msg.what); 142 } 143 } 144 145 /** 146 * Return current carrier action values 147 */ 148 public Object getCarrierActionValue(int action) { 149 Object val = getCarrierAction(action); 150 if (val == null) { 151 throw new IllegalArgumentException("invalid carrier action: " + action); 152 } 153 return val; 154 } 155 156 /** 157 * Action set from carrier app to enable/disable radio 158 */ 159 public void carrierActionSetRadioEnabled(boolean enabled) { 160 sendMessage(obtainMessage(CARRIER_ACTION_SET_RADIO_ENABLED, enabled)); 161 } 162 163 /** 164 * Action set from carrier app to enable/disable metered APNs 165 */ 166 public void carrierActionSetMeteredApnsEnabled(boolean enabled) { 167 sendMessage(obtainMessage(CARRIER_ACTION_SET_METERED_APNS_ENABLED, enabled)); 168 } 169 170 private RegistrantList getRegistrantsFromAction(int action) { 171 switch (action) { 172 case CARRIER_ACTION_SET_METERED_APNS_ENABLED: 173 return mMeteredApnEnableRegistrants; 174 case CARRIER_ACTION_SET_RADIO_ENABLED: 175 return mRadioEnableRegistrants; 176 default: 177 loge("Unsupported action: " + action); 178 return null; 179 } 180 } 181 182 private Object getCarrierAction(int action) { 183 switch (action) { 184 case CARRIER_ACTION_SET_METERED_APNS_ENABLED: 185 return mCarrierActionOnMeteredApnEnabled; 186 case CARRIER_ACTION_SET_RADIO_ENABLED: 187 return mCarrierActionOnRadioEnabled; 188 default: 189 loge("Unsupported action: " + action); 190 return null; 191 } 192 } 193 194 /** 195 * Register with CAA for a specific event. 196 * @param action which carrier action registrant is interested in 197 * @param notifyNow if carrier action has once set, notify registrant right after 198 * registering, so that registrants will get the latest carrier action. 199 */ 200 public void registerForCarrierAction(int action, Handler h, int what, Object obj, 201 boolean notifyNow) { 202 Object carrierAction = getCarrierAction(action); 203 if (carrierAction == null) { 204 throw new IllegalArgumentException("invalid carrier action: " + action); 205 } 206 RegistrantList list = getRegistrantsFromAction(action); 207 Registrant r = new Registrant(h, what, obj); 208 list.add(r); 209 if (notifyNow) { 210 r.notifyRegistrant(new AsyncResult(null, carrierAction, null)); 211 } 212 } 213 214 /** 215 * Unregister with CAA for a specific event. Callers will no longer be notified upon such event. 216 * @param action which carrier action caller is no longer interested in 217 */ 218 public void unregisterForCarrierAction(Handler h, int action) { 219 RegistrantList list = getRegistrantsFromAction(action); 220 if (list == null) { 221 throw new IllegalArgumentException("invalid carrier action: " + action); 222 } 223 list.remove(h); 224 } 225 226 @VisibleForTesting 227 public ContentObserver getContentObserver() { 228 return mSettingsObserver; 229 } 230 231 private void log(String s) { 232 Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); 233 } 234 235 private void loge(String s) { 236 Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); 237 } 238 239 private void logv(String s) { 240 Rlog.v(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); 241 } 242 243 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 244 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 245 pw.println(" mCarrierActionOnMeteredApnsEnabled Log:"); 246 ipw.increaseIndent(); 247 mMeteredApnEnabledLog.dump(fd, ipw, args); 248 ipw.decreaseIndent(); 249 250 pw.println(" mCarrierActionOnRadioEnabled Log:"); 251 ipw.increaseIndent(); 252 mRadioEnabledLog.dump(fd, ipw, args); 253 ipw.decreaseIndent(); 254 } 255} 256