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