10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2011 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.BroadcastReceiver;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.IntentFilter;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.PowerManager;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.provider.Telephony.Sms.Intents;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Monitors the device and ICC storage, and sends the appropriate events.
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This code was formerly part of {@link SMSDispatcher}, and has been moved
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * into a separate class to support instantiation of multiple SMSDispatchers on
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * dual-mode devices that require support for both 3GPP and 3GPP2 format messages.
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic final class SmsStorageMonitor extends Handler {
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final String TAG = "SmsStorageMonitor";
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** SIM/RUIM storage is full */
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_ICC_FULL = 1;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Memory status reporting is acknowledged by RIL */
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_REPORT_MEMORY_STATUS_DONE = 2;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Radio is ON */
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int EVENT_RADIO_ON = 3;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Context from phone object passed to constructor. */
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final Context mContext;
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Wake lock to ensure device stays awake while dispatching the SMS intent. */
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private PowerManager.WakeLock mWakeLock;
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mReportMemoryStatusPending;
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    final CommandsInterface mCm;                            // accessed from inner class
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean mStorageAvailable = true;                       // accessed from inner class
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Hold the wake lock for 5 seconds, which should be enough time for
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * any receiver(s) to grab its own wake lock.
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int WAKE_LOCK_TIMEOUT = 5000;
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Creates an SmsStorageMonitor and registers for events.
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param phone the Phone to use
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public SmsStorageMonitor(PhoneBase phone) {
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext = phone.getContext();
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCm = phone.mCM;
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        createWakelock();
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCm.setOnIccSmsFull(this, EVENT_ICC_FULL, null);
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCm.registerForOn(this, EVENT_RADIO_ON, null);
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Register for device storage intents.  Use these to notify the RIL
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // that storage for SMS is or is not available.
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        IntentFilter filter = new IntentFilter();
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        filter.addAction(Intent.ACTION_DEVICE_STORAGE_FULL);
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        filter.addAction(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext.registerReceiver(mResultReceiver, filter);
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dispose() {
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCm.unSetOnIccSmsFull(this);
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCm.unregisterForOn(this);
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext.unregisterReceiver(mResultReceiver);
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Handles events coming from the phone stack. Overridden from handler.
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param msg the message to handle
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void handleMessage(Message msg) {
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        AsyncResult ar;
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (msg.what) {
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_ICC_FULL:
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                handleIccFull();
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_REPORT_MEMORY_STATUS_DONE:
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult) msg.obj;
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.exception != null) {
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mReportMemoryStatusPending = true;
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Log.v(TAG, "Memory status report to modem pending : mStorageAvailable = "
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + mStorageAvailable);
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mReportMemoryStatusPending = false;
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RADIO_ON:
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (mReportMemoryStatusPending) {
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Log.v(TAG, "Sending pending memory status report : mStorageAvailable = "
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + mStorageAvailable);
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mCm.reportSmsMemoryStatus(mStorageAvailable,
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void createWakelock() {
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SmsStorageMonitor");
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mWakeLock.setReferenceCounted(true);
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Called when SIM_FULL message is received from the RIL.  Notifies interested
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * parties that SIM storage for SMS messages is full.
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void handleIccFull() {
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // broadcast SIM_FULL intent
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(Intents.SIM_FULL_ACTION);
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext.sendBroadcast(intent, SMSDispatcher.RECEIVE_SMS_PERMISSION);
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Returns whether or not there is storage available for an incoming SMS. */
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isStorageAvailable() {
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mStorageAvailable;
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private final BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        @Override
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        public void onReceive(Context context, Intent intent) {
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_FULL)) {
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mStorageAvailable = false;
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCm.reportSmsMemoryStatus(false, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_NOT_FULL)) {
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mStorageAvailable = true;
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCm.reportSmsMemoryStatus(true, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    };
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
163