Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4036e712 authored by Koushik Dutta's avatar Koushik Dutta
Browse files

Add SMS Middleware layer.

Change-Id: If5621d0c5126d6917ab00143af645692f3c4a384
parent bf522945
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -90,6 +90,12 @@ public class SmsMessage {
     */
    public static final String FORMAT_3GPP2 = "3gpp2";

    /**
     * Indicates a synthetic SMS message.
     * @hide
     */
    public static final String FORMAT_SYNTHETIC = "synthetic";

    /** Contains actual SmsMessage. Only public for debugging and for framework layer.
     *
     * @hide
@@ -143,6 +149,9 @@ public class SmsMessage {
        int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
        String format = (PHONE_TYPE_CDMA == activePhone) ?
                SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
        if (com.android.internal.telephony.SyntheticSmsMessage.isSyntheticPdu(pdu)) {
            format = FORMAT_SYNTHETIC;
        }
        message = createFromPdu(pdu, format);

        if (null == message || null == message.mWrappedSmsMessage) {
@@ -171,6 +180,8 @@ public class SmsMessage {
            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
        } else if (SmsConstants.FORMAT_3GPP.equals(format)) {
            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
        } else if (FORMAT_SYNTHETIC.equals(format)) {
            wrappedMessage = com.android.internal.telephony.SyntheticSmsMessage.createFromPdu(pdu);
        } else {
            Rlog.e(LOG_TAG, "createFromPdu(): unsupported message format " + format);
            return null;
+40 −19
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source Project
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * Not a Contribution.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -21,11 +23,15 @@ import android.Manifest;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncResult;
import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.telephony.Rlog;
import android.util.Log;

@@ -122,9 +128,6 @@ public class IccSmsInterfaceManager extends ISms.Stub {
        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        mDispatcher = new ImsSMSDispatcher(phone,
                phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
        if (ServiceManager.getService("isms") == null) {
            ServiceManager.addService("isms", this);
        }
    }

    protected void markMessagesAsRead(ArrayList<byte[]> messages) {
@@ -275,6 +278,9 @@ public class IccSmsInterfaceManager extends ISms.Stub {
        return mSuccess;
    }

    public void synthesizeMessages(String originatingAddress, String scAddress, List<String> messages, long timestampMillis) throws RemoteException {
    }

    /**
     * Retrieves all messages currently stored on Icc.
     *
@@ -287,10 +293,6 @@ public class IccSmsInterfaceManager extends ISms.Stub {
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.RECEIVE_SMS,
                "Reading messages from Icc");
        if (mAppOps.noteOp(AppOpsManager.OP_READ_ICC_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return new ArrayList<SmsRawData>();
        }
        synchronized(mLock) {

            IccFileHandler fh = mPhone.getIccFileHandler();
@@ -384,16 +386,26 @@ public class IccSmsInterfaceManager extends ISms.Stub {
    @Override
    public void sendText(String callingPackage, String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
        int callingUid = Binder.getCallingUid();

        String[] callingParts = callingPackage.split("\\\\");
        if (callingUid == android.os.Process.PHONE_UID &&
                                         callingParts.length > 1) {
            callingUid = Integer.parseInt(callingParts[1]);
        }

        if (Binder.getCallingPid() != android.os.Process.myPid()) {
            mPhone.getContext().enforceCallingPermission(
                    Manifest.permission.SEND_SMS,
                    "Sending SMS message");
        }
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
                " text='"+ text + "' sentIntent=" +
                sentIntent + " deliveryIntent=" + deliveryIntent);
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, callingUid,
                callingParts[0]) != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
@@ -428,9 +440,19 @@ public class IccSmsInterfaceManager extends ISms.Stub {
    public void sendMultipartText(String callingPackage, String destAddr, String scAddr,
            List<String> parts, List<PendingIntent> sentIntents,
            List<PendingIntent> deliveryIntents) {
        int callingUid = Binder.getCallingUid();

        String[] callingParts = callingPackage.split("\\\\");
        if (callingUid == android.os.Process.PHONE_UID &&
                                         callingParts.length > 1) {
            callingUid = Integer.parseInt(callingParts[1]);
        }

        if (Binder.getCallingPid() != android.os.Process.myPid()) {
            mPhone.getContext().enforceCallingPermission(
                    Manifest.permission.SEND_SMS,
                    "Sending SMS message");
        }
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            int i = 0;
            for (String part : parts) {
@@ -438,8 +460,8 @@ public class IccSmsInterfaceManager extends ISms.Stub {
                        ", part[" + (i++) + "]=" + part);
            }
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, callingUid,
                callingParts[0]) != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
@@ -527,7 +549,6 @@ public class IccSmsInterfaceManager extends ISms.Stub {
            return disableCdmaBroadcastRange(startMessageId, endMessageId);
        }
    }

    synchronized public boolean enableGsmBroadcastRange(int startMessageId, int endMessageId) {
        if (DBG) log("enableGsmBroadcastRange");

+252 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import java.util.ArrayList;
import java.util.List;

import android.Manifest;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Telephony.Sms.Intents;
import android.telephony.SmsMessage;

public class IccSmsInterfaceManagerProxy extends ISms.Stub {
    private IccSmsInterfaceManager mIccSmsInterfaceManager;

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            // check if the message was aborted
            if (getResultCode() != Activity.RESULT_OK) {
                return;
            }
            String destAddr = getResultData();
            String scAddr = intent.getStringExtra("scAddr");
            String callingPackage = intent.getStringExtra("callingPackage");
            ArrayList<String> parts = intent.getStringArrayListExtra("parts");
            ArrayList<PendingIntent> sentIntents = intent.getParcelableArrayListExtra("sentIntents");
            ArrayList<PendingIntent> deliveryIntents = intent.getParcelableArrayListExtra("deliveryIntents");

            if (intent.getIntExtra("callingUid", 0) != 0) {
                callingPackage = callingPackage + "\\" + intent.getIntExtra("callingUid", 0);
            }

            if (intent.getBooleanExtra("multipart", false)) {
                mIccSmsInterfaceManager.sendMultipartText(callingPackage, destAddr, scAddr,
                        parts, sentIntents, deliveryIntents);
                return;
            }

            PendingIntent sentIntent = null;
            if (sentIntents != null && sentIntents.size() > 0) {
                sentIntent = sentIntents.get(0);
            }
            PendingIntent deliveryIntent = null;
            if (deliveryIntents != null && deliveryIntents.size() > 0) {
                deliveryIntent = deliveryIntents.get(0);
            }
            String text = null;
            if (parts != null && parts.size() > 0) {
                text = parts.get(0);
            }
            mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
                    sentIntent, deliveryIntent);
        }
    };

    public IccSmsInterfaceManagerProxy(Context context,
            IccSmsInterfaceManager iccSmsInterfaceManager) {
        this.mContext = context;
        mIccSmsInterfaceManager = iccSmsInterfaceManager;
        if(ServiceManager.getService("isms") == null) {
            ServiceManager.addService("isms", this);
        }

        createWakelock();
    }

    public void setmIccSmsInterfaceManager(IccSmsInterfaceManager iccSmsInterfaceManager) {
        mIccSmsInterfaceManager = iccSmsInterfaceManager;
    }

    private void createWakelock() {
        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "IccSmsInterfaceManager");
        mWakeLock.setReferenceCounted(true);
    }

    private Context mContext;
    private PowerManager.WakeLock mWakeLock;
    private static final int WAKE_LOCK_TIMEOUT = 5000;
    private final Handler mHandler = new Handler();
    private void dispatchPdus(byte[][] pdus) {
        Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
        // Direct the intent to only the default SMS app. If we can't find a default SMS app
        // then sent it to all broadcast receivers.
        ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
        if (componentName == null)
            return;
        // Deliver SMS message only to this receiver
        intent.setComponent(componentName);
        intent.putExtra("pdus", pdus);
        intent.putExtra("format", SmsMessage.FORMAT_SYNTHETIC);
        dispatch(intent, Manifest.permission.RECEIVE_SMS);
    }

    private void dispatch(Intent intent, String permission) {
        // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
        // receivers time to take their own wake locks.
        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
        intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
        mContext.sendOrderedBroadcast(intent, permission, AppOpsManager.OP_RECEIVE_SMS, null,
                mHandler, Activity.RESULT_OK, null, null);
    }

    public void synthesizeMessages(String originatingAddress, String scAddress, List<String> messages, long timestampMillis) throws RemoteException {
        mContext.enforceCallingPermission(
                android.Manifest.permission.BROADCAST_SMS, "");
        byte[][] pdus = new byte[messages.size()][];
        for (int i = 0; i < messages.size(); i++) {
            SyntheticSmsMessage message = new SyntheticSmsMessage(originatingAddress, scAddress, messages.get(i), timestampMillis);
            pdus[i] = message.getPdu();
        }
        dispatchPdus(pdus);
    }

    @Override
    public boolean
    updateMessageOnIccEf(String callingPackage, int index, int status, byte[] pdu) {
         return mIccSmsInterfaceManager.updateMessageOnIccEf(callingPackage, index, status, pdu);
    }

    @Override
    public boolean copyMessageToIccEf(String callingPackage, int status, byte[] pdu,
            byte[] smsc) {
        return mIccSmsInterfaceManager.copyMessageToIccEf(callingPackage, status, pdu, smsc);
    }

    @Override
    public List<SmsRawData> getAllMessagesFromIccEf(String callingPackage) {
        return mIccSmsInterfaceManager.getAllMessagesFromIccEf(callingPackage);
    }

    @Override
    public void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
        mIccSmsInterfaceManager.sendData(callingPackage, destAddr, scAddr, destPort, data,
                sentIntent, deliveryIntent);
    }

    private void broadcastOutgoingSms(String callingPackage, String destAddr, String scAddr,
            boolean multipart, ArrayList<String> parts,
            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
            int priority) {
        Intent broadcast = new Intent(Intent.ACTION_NEW_OUTGOING_SMS);
        broadcast.putExtra("destAddr", destAddr);
        broadcast.putExtra("scAddr", scAddr);
        broadcast.putExtra("multipart", multipart);
        broadcast.putExtra("callingPackage", callingPackage);
        broadcast.putExtra("callingUid", android.os.Binder.getCallingUid());
        broadcast.putStringArrayListExtra("parts", parts);
        broadcast.putParcelableArrayListExtra("sentIntents", sentIntents);
        broadcast.putParcelableArrayListExtra("deliveryIntents", deliveryIntents);
        broadcast.putExtra("priority", priority);
        mContext.sendOrderedBroadcastAsUser(broadcast, UserHandle.OWNER,
                android.Manifest.permission.INTERCEPT_SMS,
                mReceiver, null, Activity.RESULT_OK, destAddr, null);
    }

    @Override
    public void sendText(String callingPackage, String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.SEND_SMS,
                "Sending SMS message");
        ArrayList<String> parts = new ArrayList<String>();
        parts.add(text);
        ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();
        sentIntents.add(sentIntent);
        ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
        deliveryIntents.add(deliveryIntent);
        broadcastOutgoingSms(callingPackage, destAddr, scAddr, false, parts, sentIntents,
                deliveryIntents, -1);
    }

    @Override
    public void sendMultipartText(String callingPackage, String destAddr, String scAddr,
            List<String> parts, List<PendingIntent> sentIntents,
            List<PendingIntent> deliveryIntents) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.SEND_SMS,
                "Sending SMS message");
        broadcastOutgoingSms(callingPackage, destAddr, scAddr, true, new ArrayList<String>(parts),
                new ArrayList<PendingIntent>(sentIntents), new ArrayList<PendingIntent>(deliveryIntents),
                -1);
    }

    @Override
    public boolean enableCellBroadcast(int messageIdentifier) throws android.os.RemoteException {
        return mIccSmsInterfaceManager.enableCellBroadcast(messageIdentifier);
    }

    @Override
    public boolean disableCellBroadcast(int messageIdentifier) throws android.os.RemoteException {
        return mIccSmsInterfaceManager.disableCellBroadcast(messageIdentifier);
    }

    @Override
    public boolean enableCellBroadcastRange(int startMessageId, int endMessageId)
            throws android.os.RemoteException {
        return mIccSmsInterfaceManager.enableCellBroadcastRange(startMessageId, endMessageId);
    }

    @Override
    public boolean disableCellBroadcastRange(int startMessageId, int endMessageId)
            throws android.os.RemoteException {
        return mIccSmsInterfaceManager.disableCellBroadcastRange(startMessageId, endMessageId);
    }

    @Override
    public int getPremiumSmsPermission(String packageName) {
        return mIccSmsInterfaceManager.getPremiumSmsPermission(packageName);
    }

    @Override
    public void setPremiumSmsPermission(String packageName, int permission) {
        mIccSmsInterfaceManager.setPremiumSmsPermission(packageName, permission);
    }

    @Override
    public boolean isImsSmsSupported() throws RemoteException {
        return mIccSmsInterfaceManager.isImsSmsSupported();
    }

    @Override
    public String getImsSmsFormat() throws RemoteException {
        return mIccSmsInterfaceManager.getImsSmsFormat();
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ public class PhoneProxy extends Handler implements Phone {
    private IccPhoneBookInterfaceManagerProxy mIccPhoneBookInterfaceManagerProxy;
    private PhoneSubInfoProxy mPhoneSubInfoProxy;
    private IccCardProxy mIccCardProxy;
    private IccSmsInterfaceManagerProxy mIccSmsInterfaceManagerProxy;

    private boolean mResetModemOnRadioTechnologyChange = false;

@@ -78,6 +79,9 @@ public class PhoneProxy extends Handler implements Phone {
        mPhoneSubInfoProxy = new PhoneSubInfoProxy(phone.getPhoneSubInfo());
        mCommandsInterface = ((PhoneBase)mActivePhone).mCi;

        mIccSmsInterfaceManagerProxy =
            new IccSmsInterfaceManagerProxy(mActivePhone.getContext(), mIccSmsInterfaceManager);

        mCommandsInterface.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
        mCommandsInterface.registerForOn(this, EVENT_RADIO_ON, null);
        mCommandsInterface.registerForVoiceRadioTechChanged(