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.telephony.Rlog;
23import android.util.LocalLog;
24import android.util.Log;
25
26import com.android.internal.util.IndentingPrintWriter;
27
28import java.io.FileDescriptor;
29import java.io.PrintWriter;
30import java.security.InvalidParameterException;
31
32import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATED;
33import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED;
34import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
35import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_RESTRICTED;
36import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_ACTIVATING;
37
38public class SimActivationTracker {
39    /**
40     * SimActivationTracker(SAT) serves as a central place to keep track of all knowledge of
41     * voice & data activation state which is set by custom/default carrier apps.
42     * Each phone object maintains a single activation tracker.
43     */
44    private static final boolean DBG = true;
45    private static final String LOG_TAG = "SAT";
46    private static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
47
48    private Phone mPhone;
49
50    /**
51     * Voice Activation State
52     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
53     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
54     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
55     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
56     */
57    private int mVoiceActivationState;
58
59    /**
60     * Data Activation State
61     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
62     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
63     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
64     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
65     * @see android.telephony.TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
66     */
67    private int mDataActivationState;
68    private final LocalLog mVoiceActivationStateLog = new LocalLog(10);
69    private final LocalLog mDataActivationStateLog = new LocalLog(10);
70    private final BroadcastReceiver mReceiver;
71
72    public SimActivationTracker(Phone phone) {
73        mPhone = phone;
74        mVoiceActivationState = SIM_ACTIVATION_STATE_UNKNOWN;
75        mDataActivationState = SIM_ACTIVATION_STATE_UNKNOWN;
76
77        mReceiver = new  BroadcastReceiver() {
78            @Override
79            public void onReceive(Context context, Intent intent) {
80                String action = intent.getAction();
81                if (VDBG) log("action: " + action);
82                if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)){
83                    if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(
84                            intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))) {
85                        if (DBG) log("onSimAbsent, reset activation state to UNKNOWN");
86                        setVoiceActivationState(SIM_ACTIVATION_STATE_UNKNOWN);
87                        setDataActivationState(SIM_ACTIVATION_STATE_UNKNOWN);
88                    }
89                }
90            }
91        };
92
93        IntentFilter intentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
94        mPhone.getContext().registerReceiver(mReceiver, intentFilter);
95    }
96
97    public void setVoiceActivationState(int state) {
98        if (!isValidActivationState(state) || (SIM_ACTIVATION_STATE_RESTRICTED == state)) {
99            throw new IllegalArgumentException("invalid voice activation state: " + state);
100        }
101        if (DBG) log("setVoiceActivationState=" + state);
102        mVoiceActivationState = state;
103        mVoiceActivationStateLog.log(toString(state));
104        mPhone.notifyVoiceActivationStateChanged(state);
105    }
106
107    public void setDataActivationState(int state) {
108        if (!isValidActivationState(state)) {
109            throw new IllegalArgumentException("invalid data activation state: " + state);
110        }
111        if (DBG) log("setDataActivationState=" + state);
112        mDataActivationState = state;
113        mDataActivationStateLog.log(toString(state));
114        mPhone.notifyDataActivationStateChanged(state);
115    }
116
117    public int getVoiceActivationState() {
118        return mVoiceActivationState;
119    }
120
121    public int getDataActivationState() {
122        return mDataActivationState;
123    }
124
125    private static boolean isValidActivationState(int state) {
126        switch (state) {
127            case SIM_ACTIVATION_STATE_UNKNOWN:
128            case SIM_ACTIVATION_STATE_ACTIVATING:
129            case SIM_ACTIVATION_STATE_ACTIVATED:
130            case SIM_ACTIVATION_STATE_DEACTIVATED:
131            case SIM_ACTIVATION_STATE_RESTRICTED:
132                return true;
133            default:
134                return false;
135        }
136    }
137
138    private static String toString(int state) {
139        switch (state) {
140            case SIM_ACTIVATION_STATE_UNKNOWN:
141                return "unknown";
142            case SIM_ACTIVATION_STATE_ACTIVATING:
143                return "activating";
144            case SIM_ACTIVATION_STATE_ACTIVATED:
145                return "activated";
146            case SIM_ACTIVATION_STATE_DEACTIVATED:
147                return "deactivated";
148            case SIM_ACTIVATION_STATE_RESTRICTED:
149                return "restricted";
150            default:
151                return "invalid";
152        }
153    }
154
155    private void log(String s) {
156        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
157    }
158
159    private void loge(String s) {
160        Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
161    }
162
163    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
164        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
165        pw.println(" mVoiceActivationState Log:");
166        ipw.increaseIndent();
167        mVoiceActivationStateLog.dump(fd, ipw, args);
168        ipw.decreaseIndent();
169
170        pw.println(" mDataActivationState Log:");
171        ipw.increaseIndent();
172        mDataActivationStateLog.dump(fd, ipw, args);
173        ipw.decreaseIndent();
174    }
175
176    public void dispose() {
177        mPhone.getContext().unregisterReceiver(mReceiver);
178    }
179}