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