`

TelephonyProvider的源代码分析

阅读更多

TelephonyProvider.java
package com.android.providers.telephony;

import android.content.*;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Environment;
import android.provider.Telephony;
import android.util.Config;
import android.util.Log;
import android.util.Xml;
import com.android.internal.util.XmlUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TelephonyProvider extends ContentProvider
{
    private static final String DATABASE_NAME = "telephony.db";
    // DATABASE_VERSION needs to be in-sync with version in apns.xml.
    private static final int DATABASE_VERSION = 4 << 16;
    private static final int URL_TELEPHONY = 1;
    private static final int URL_CURRENT = 2;
    private static final int URL_ID = 3;

    private static final String TAG = "TelephonyProvider";
    private static final String CARRIERS_TABLE = "carriers";
    private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";

    private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    private static final ContentValues s_currentNullMap;
    private static final ContentValues s_currentSetMap;

    static {
        s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY);
        s_urlMatcher.addURI("telephony", "carriers/current", URL_CURRENT);
        s_urlMatcher.addURI("telephony", "carriers/#", URL_ID);

        s_currentNullMap = new ContentValues(1);
        s_currentNullMap.put("current", (Long) null);

        s_currentSetMap = new ContentValues(1);
        s_currentSetMap.put("current", "1");
    }

    private static class DatabaseHelper extends SQLiteOpenHelper {
        // Context to access resources with
        private Context mContext;

        /**
         * DatabaseHelper helper class for loading apns into a database.
         *
         * @param parser the system-default parser for apns.xml
         * @param confidential an optional parser for confidential APNS (stored separately)
         */
        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, getVersion(context));
            mContext = context;
        }

        private static int getVersion(Context context) {
            // Get the database version, combining a static schema version and the XML version
            Resources r = context.getResources();
            XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
            try {
                XmlUtils.beginDocument(parser, "apns");
                int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
                return DATABASE_VERSION | publicversion;
            } catch (Exception e) {
                Log.e(TAG, "Can't get version of APN database", e);
                return DATABASE_VERSION;
            } finally {
                parser.close();
            }
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            // Set up the database schema
            db.execSQL("CREATE TABLE " + CARRIERS_TABLE +
                "(_id INTEGER PRIMARY KEY," +
                    "name TEXT," +
                    "numeric TEXT," +
                    "mcc TEXT," +
                    "mnc TEXT," +
                    "apn TEXT," +
                    "user TEXT," +
                    "server TEXT," +
                    "password TEXT," +
                    "proxy TEXT," +
                    "port TEXT," +
                    "mmsproxy TEXT," +
                    "mmsport TEXT," +
                    "mmsc TEXT," +
                    "type TEXT," +
                    "current INTEGER);");

            // Read internal APNS data
            Resources r = mContext.getResources();
            XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
            int publicversion = -1;
            try {
                XmlUtils.beginDocument(parser, "apns");
                publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
                loadApns(db, parser);
            } catch (Exception e) {
                Log.e(TAG, "Got execption while loading APN database.", e);
            } finally {
                parser.close();
            }

            // Read external APNS data (partner-provided)
            XmlPullParser confparser = null;
            // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
            File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);
            FileReader confreader = null;
            try {
                confreader = new FileReader(confFile);
                confparser = Xml.newPullParser();
                confparser.setInput(confreader);
                XmlUtils.beginDocument(confparser, "apns");

                // Sanity check. Force internal version and confidential versions to agree
                int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version"));
                if (publicversion != confversion) {
                    throw new IllegalStateException("Internal APNS file version doesn't match "
                            + confFile.getAbsolutePath());
                }

                loadApns(db, confparser);
            } catch (FileNotFoundException e) {
                // It's ok if the file isn't found. It means there isn't a confidential file
                // Log.e(TAG, "File not found: '" + confFile.getAbsolutePath() + "'");
            } catch (Exception e) {
                Log.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
            } finally {
                try { if (confreader != null) confreader.close(); } catch (IOException e) { }
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE + ";");
            onCreate(db);
        }

        /**
         * Gets the next row of apn values.
         *
         * @param parser the parser
         * @return the row or null if it's not an apn
         */
        private ContentValues getRow(XmlPullParser parser) {
            if (!"apn".equals(parser.getName())) {
                return null;
            }

            ContentValues map = new ContentValues();

            String mcc = parser.getAttributeValue(null, "mcc");
            String mnc = parser.getAttributeValue(null, "mnc");
            String numeric = mcc + mnc;

            map.put(Telephony.Carriers.NUMERIC,numeric);
            map.put(Telephony.Carriers.MCC, mcc);
            map.put(Telephony.Carriers.MNC, mnc);
            map.put(Telephony.Carriers.NAME, parser.getAttributeValue(null, "carrier"));
            map.put(Telephony.Carriers.APN, parser.getAttributeValue(null, "apn"));
            map.put(Telephony.Carriers.USER, parser.getAttributeValue(null, "user"));
            map.put(Telephony.Carriers.SERVER, parser.getAttributeValue(null, "server"));
            map.put(Telephony.Carriers.PASSWORD, parser.getAttributeValue(null, "password"));

            // do not add NULL to the map so that insert() will set the default value
            String proxy = parser.getAttributeValue(null, "proxy");
            if (proxy != null) {
                map.put(Telephony.Carriers.PROXY, proxy);
            }
            String port = parser.getAttributeValue(null, "port");
            if (port != null) {
                map.put(Telephony.Carriers.PORT, port);
            }
            String mmsproxy = parser.getAttributeValue(null, "mmsproxy");
            if (mmsproxy != null) {
                map.put(Telephony.Carriers.MMSPROXY, mmsproxy);
            }
            String mmsport = parser.getAttributeValue(null, "mmsport");
            if (mmsport != null) {
                map.put(Telephony.Carriers.MMSPORT, mmsport);
            }
            map.put(Telephony.Carriers.MMSC, parser.getAttributeValue(null, "mmsc"));
            String type = parser.getAttributeValue(null, "type");
            if (type != null) {
                map.put(Telephony.Carriers.TYPE, type);
            }

            return map;
        }

        /*
         * Loads apns from xml file into the database
         *
         * @param db the sqlite database to write to
         * @param parser the xml parser
         *
         */
        private void loadApns(SQLiteDatabase db, XmlPullParser parser) {
            if (parser != null) {
                try {
                    while (true) {
                        XmlUtils.nextElement(parser);
                        ContentValues row = getRow(parser);
                        if (row != null) {
                            db.insert(CARRIERS_TABLE, null, row);
                        } else {
                            break;  // do we really want to skip the rest of the file?
                        }
                    }
                } catch (XmlPullParserException e)  {
                    Log.e(TAG, "Got execption while getting perferred time zone.", e);
                } catch (IOException e) {
                    Log.e(TAG, "Got execption while getting perferred time zone.", e);
                }
            }
        }
    }

    @Override
    public boolean onCreate() {
        mOpenHelper = new DatabaseHelper(getContext());
        return true;
    }

    @Override
    public Cursor query(Uri url, String[] projectionIn, String selection,
            String[] selectionArgs, String sort) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables("carriers");

        int match = s_urlMatcher.match(url);
        switch (match) {
            // do nothing
            case URL_TELEPHONY: {
                break;
            }


            case URL_CURRENT: {
                qb.appendWhere("current IS NOT NULL");
                // ignore the selection
                selection = null;
                break;
            }

            case URL_ID: {
                qb.appendWhere("_id = " + url.getPathSegments().get(1));
                break;
            }

            default: {
                return null;
            }
        }

        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        Cursor ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort);
        ret.setNotificationUri(getContext().getContentResolver(), url);
        return ret;
    }

    @Override
    public String getType(Uri url)
    {
        switch (s_urlMatcher.match(url)) {
        case URL_TELEPHONY:
            return "vnd.android.cursor.dir/telephony-carrier";

        case URL_ID:
            return "vnd.android.cursor.item/telephony-carrier";

        default:
            throw new IllegalArgumentException("Unknown URL " + url);
        }
    }

    @Override
    public Uri insert(Uri url, ContentValues initialValues)
    {
        Uri result = null;

        checkPermission();

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        int match = s_urlMatcher.match(url);
        boolean notify = false;
        switch (match)
        {
            case URL_TELEPHONY:
            {
                ContentValues values;
                if (initialValues != null) {
                    values = new ContentValues(initialValues);
                } else {
                    values = new ContentValues();
                }

                // TODO Review this. This code should probably not bet here.
                // It is valid for the database to return a null string.
                if (values.containsKey(Telephony.Carriers.NAME) == false) {
                    values.put(Telephony.Carriers.NAME, "");
                }
                if (values.containsKey(Telephony.Carriers.APN) == false) {
                    values.put(Telephony.Carriers.APN, "");
                }
                if (values.containsKey(Telephony.Carriers.PORT) == false) {
                    values.put(Telephony.Carriers.PORT, "");
                }
                if (values.containsKey(Telephony.Carriers.PROXY) == false) {
                    values.put(Telephony.Carriers.PROXY, "");
                }
                if (values.containsKey(Telephony.Carriers.USER) == false) {
                    values.put(Telephony.Carriers.USER, "");
                }
                if (values.containsKey(Telephony.Carriers.SERVER) == false) {
                    values.put(Telephony.Carriers.SERVER, "");
                }
                if (values.containsKey(Telephony.Carriers.PASSWORD) == false) {
                    values.put(Telephony.Carriers.PASSWORD, "");
                }
                if (values.containsKey(Telephony.Carriers.MMSPORT) == false) {
                    values.put(Telephony.Carriers.MMSPORT, "");
                }
                if (values.containsKey(Telephony.Carriers.MMSPROXY) == false) {
                    values.put(Telephony.Carriers.MMSPROXY, "");
                }

                long rowID = db.insert(CARRIERS_TABLE, null, values);
                if (rowID > 0)
                {
                    result = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, rowID);
                    notify = true;
                }

                if (Config.LOGD) Log.d(TAG, "inserted " + values.toString() + " rowID = " + rowID);
                break;
            }

            case URL_CURRENT:
            {
                // null out the previous operator
                db.update("carriers", s_currentNullMap, "current IS NOT NULL", null);

                String numeric = initialValues.getAsString("numeric");
                int updated = db.update("carriers", s_currentSetMap,
                        "numeric = '" + numeric + "'", null);

                if (updated > 0)
                {
                    if (Config.LOGD) {
                        Log.d(TAG, "Setting numeric '" + numeric + "' to be the current operator");
                    }
                }
                else
                {
                    Log.e(TAG, "Failed setting numeric '" + numeric + "' to the current operator");
                }
                break;
            }
        }

        if (notify) {
            getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null);
        }

        return result;
    }

    @Override
    public int delete(Uri url, String where, String[] whereArgs)
    {
        int count;

        checkPermission();
        
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        int match = s_urlMatcher.match(url);
        switch (match)
        {
            case URL_TELEPHONY:
            {
                count = db.delete(CARRIERS_TABLE, where, whereArgs);
                break;
            }

            case URL_CURRENT:
            {
                count = db.delete(CARRIERS_TABLE, where, whereArgs);
                break;
            }
            
            case URL_ID:
            {
                count = db.delete(CARRIERS_TABLE, Telephony.Carriers._ID + "=?",
                        new String[] { url.getLastPathSegment() });
                break;
            }

            default: {
                throw new UnsupportedOperationException("Cannot delete that URL: " + url);
            }
        }

        if (count > 0) {
            getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null);
        }

        return count;
    }

    @Override
    public int update(Uri url, ContentValues values, String where, String[] whereArgs)
    {
        int count;

        checkPermission();

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        int match = s_urlMatcher.match(url);
        switch (match)
        {
            case URL_TELEPHONY:
            {
                count = db.update(CARRIERS_TABLE, values, where, whereArgs);
                break;
            }

            case URL_CURRENT:
            {
                count = db.update(CARRIERS_TABLE, values, where, whereArgs);
                break;
            }

            case URL_ID:
            {
                if (where != null || whereArgs != null) {
                    throw new UnsupportedOperationException(
                            "Cannot update URL " + url + " with a where clause");
                }
                count = db.update(CARRIERS_TABLE, values, Telephony.Carriers._ID + "=?",
                        new String[] { url.getLastPathSegment() });
                break;
            }
            
            default: {
                throw new UnsupportedOperationException("Cannot update that URL: " + url);
            }
        }

        if (count > 0) {
            getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null);
        }

        return count;
    }

    private void checkPermission() {
        // Check the permissions
        getContext().enforceCallingOrSelfPermission("android.permission.WRITE_APN_SETTINGS",
                "No permission to write APN settings");
    }

    private SQLiteOpenHelper mOpenHelper;
}


以上是TelephonyProvider的源代码

其实TelephonyProvider是一个工具类,封装了对数据库的操作,负责添加删除查询carriers 的信息。

com.android.providers.telephony.TelephonyProvider
com.android.providers.telephony.TelephonyProvider.delete(Uri, String, String[])
com.android.providers.telephony.TelephonyProvider.getType(Uri)
com.android.providers.telephony.TelephonyProvider.insert(Uri, ContentValues)
com.android.providers.telephony.TelephonyProvider.onCreate()
com.android.providers.telephony.TelephonyProvider.query(Uri, String[], String, String[], String)
com.android.providers.telephony.TelephonyProvider.update(Uri, ContentValues, String, String[])

现在就要找到调用情况,clone一个TelephonyProvider出来完成对phone2 相同的操作。
分享到:
评论

相关推荐

    apk文件 TelephonyProvider(电视直播视频)

    apk文件 TelephonyProvider(电视直播视频)apk文件 TelephonyProvider(电视直播视频)apk文件 TelephonyProvider(电视直播视频)apk文件 TelephonyProvider(电视直播视频)apk文件 TelephonyProvider(电视直播...

    TelephonyProvider:安卓上层应用原始码,电话短信内容提供者原始码

    本文将深入探讨TelephonyProvider的源代码,揭示其在系统开源环境下的工作原理,帮助开发者理解和掌握Android上层应用的开发。 一、TelephonyProvider概述 TelephonyProvider是Android系统中负责处理电话和短信...

    android phone 电话源码

    - TelephonyProvider:电话数据库管理,如SIM卡信息、联系人、通话记录等。 - ServiceStateTracker:跟踪网络状态和服务提供商信息。 - IccCardProxy:与SIM卡交互,处理SIM卡事件。 - PhoneBase:电话基类,...

    android 短信源码

    通过深入理解和分析Android短信源码,开发者不仅可以了解其工作原理,还能对Android系统有更深入的认识,从而更好地进行系统级的开发和优化。对于想要开发自己的通信应用或者增强现有短信功能的开发者而言,研究这...

    Android可精简项目.pdf

    - TelephonyProvider.apk:提供电话服务相关数据的系统服务。 精简Android项目,关键是要分析每个组件或服务的具体作用,确定哪些是核心功能,哪些是可以删除的。由于Android系统是基于Linux内核开发的,因此在精简...

    Android获取通话时间实例分析

    `ContactProvider`主要负责管理联系人数据,包括姓名、电话号码等,而`TelephonyProvider`通常涉及到更深入的电话功能,如通话状态监听。在获取通话时间的场景中,我们通常会查询`Calls.CONTENT_URI`,这是`...

    Android Mms专题之:PDU介绍.doc

    在Android系统中,PDU的存储方式是放在标准的SQLiteDatabase中,通过TelephonyProvider。由于PDU的存储方式需要将PDU拆解成为可读的字段,因此PduPersister类将PDU的存储和加载过程封装起来,以便于使用。 PDU是...

    APN配置指北1

    4. 通过TelephonyProvider服务,系统可以对APN配置信息进行增删改查。 在Android系统中,有两个主要的APN配置文件: 1. Android自带的APN配置文件位于frameworks/base/core/res/res/xml/apns.xml,通常为空,不建议...

    MOTO XT882一键ROOT

    TelephonyProvider.apk=拨号记录存储服务(绝不能删除) Term.apk=超级终端(可删,不过不建议,可以用来刷Recovery) UserDictionaryProvider.apk =用户数据字典服务(可删) TtsService.apk=Text-to-speech服务...

    安卓APK程序中英文对照表.docx

    7. **拨号记录存储服务** (TelephonyProvider.apk): 管理通话记录,包括拨入、拨出和未接电话。 8. **CellConnService.apk**: 与网络连接相关的服务,可能涉及网络信号的管理和切换。 9. **Bluetooth.apk**: 蓝牙...

    如何删除系统中的垃圾文件

    15. TelephonyProvider.apk - 拨号记录存储,保存通话记录。 另外,有些文件虽然不是系统必备,但删除可能影响某些功能,但根据个人需求可以选择保留或删除: 1. AcwfDialog.APK 2. apkCompassCH.apk - 超级指南针...

    安卓2.3系统软件的各种删除。。。释放内存啦!!!!.pdf

    53. TelephonyProvider.apk:拨号器存储,删除影响拨号功能,不可删。 54. ThemeChooser.apk:主题选择,删除后影响主题切换。 55. ThemeManager.apk:主题管理,删除后影响主题管理,建议保留。 56. TtsService....

    安卓2.3系统软件的各种删除。。。释放内存啦!!!!实用.pdf

    53. TelephonyProvider.apk:拨号器储存。删除可能影响拨号功能。 54. ThemeChooser.apk:主题选择。删除后无法更改主题。 55. ThemeManager.apk:主题管理。不使用主题功能时可删除。 56. TtsService.apk:语音...

    Android安卓系统自带软件详解(免费)

    5. **TelephonyProvider.apk**:拨号记录存储服务,对于电话功能至关重要。 6. **MediaProvider.apk**:媒体数据存储服务,负责管理音频、视频等媒体文件。 7. **PackageInstaller.apk**:程序安装服务,用于安装和...

    U880可精简软件详表,所有文件及功能列表[参考].pdf

    【正文】 在Android系统中,用户可以通过获取ROOT权限来对手机进行深度定制,包括删除预装应用以优化系统性能和释放存储空间。...72. 短信(TelephonyProvider.apk) - 不可删,短信数据库管理。 73.

Global site tag (gtag.js) - Google Analytics