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 */
16
17package com.android.internal.telephony.uicc;
18
19import android.content.Context;
20import android.content.Intent;
21import android.os.Handler;
22import android.os.Message;
23import android.telephony.TelephonyManager;
24import android.util.Log;
25
26import com.android.internal.R;
27import com.android.internal.telephony.TelephonyIntents;
28import com.android.internal.telephony.uicc.IccCardStatus.CardState;
29
30/**
31 * This class launches its logic on Uicc cards state changes to / from a
32 * {@link #CARDSTATE_RESTRICTED} to notify a device provisioning package {@link
33 * com.android.internal.R.string.config_deviceProvisioningPackage}, which manages user notifications
34 * that inserted SIM is not supported on the device.
35 *
36 * @see #CARDSTATE_RESTRICTED
37 *
38 * {@hide}
39 */
40public class UiccStateChangedLauncher extends Handler {
41    private static final String TAG = UiccStateChangedLauncher.class.getName();
42    private static final int EVENT_ICC_CHANGED = 1;
43
44    private static String sDeviceProvisioningPackage = null;
45    private Context mContext;
46    private UiccController mUiccController;
47    private boolean[] mIsRestricted = null;
48
49    public UiccStateChangedLauncher(Context context, UiccController controller) {
50        sDeviceProvisioningPackage = context.getResources().getString(
51                R.string.config_deviceProvisioningPackage);
52        if (sDeviceProvisioningPackage != null && !sDeviceProvisioningPackage.isEmpty()) {
53            mContext = context;
54            mUiccController = controller;
55            mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
56        }
57    }
58
59    @Override
60    public void handleMessage(Message msg) {
61        switch(msg.what) {
62            case (EVENT_ICC_CHANGED):
63                boolean shouldNotify = false;
64                if (mIsRestricted == null) {
65                    mIsRestricted = new boolean[TelephonyManager.getDefault().getPhoneCount()];
66                    shouldNotify = true;
67                }
68                for (int i = 0; i < mIsRestricted.length; ++i) {
69                    // Update only if restricted state changes.
70
71                    UiccCard uiccCard = mUiccController.getUiccCardForPhone(i);
72                    if ((uiccCard == null
73                            || uiccCard.getCardState() != CardState.CARDSTATE_RESTRICTED)
74                            != mIsRestricted[i]) {
75                        mIsRestricted[i] = !mIsRestricted[i];
76                        shouldNotify = true;
77                    }
78                }
79                if (shouldNotify) {
80                    notifyStateChanged();
81                }
82                break;
83            default:
84                throw new RuntimeException("unexpected event not handled");
85        }
86    }
87
88    /**
89     * Send an explicit intent to device provisioning package.
90     */
91    private void notifyStateChanged() {
92        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
93        intent.setPackage(sDeviceProvisioningPackage);
94        try {
95            mContext.sendBroadcast(intent);
96        } catch (Exception e) {
97            Log.e(TAG, e.toString());
98        }
99    }
100}
101