安卓dialer Phone进程【Telephony框架、TeleService】启动过程

1. 相关源码

phone进程是开机自启的 ,其进程是com.android.phone

packages/services/Telephony
  - src/com/android/phone/PhoneApp.java
  - AndroidManifest.xml
frameworks/base/services/core/java/com/android/server/
  - am/ActivityManagerService.java
frameworks/base/services/java/com/android/server/
  - SystemServer.java
frameworks/base/core/java/android/os/
  - Process.java

 2. Phone进程启动流程

在packages/services/Telephony/AndroidManifest.xml中,/packages/services/Telephony/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
        package="com.android.phone"
        coreApp="true"
        android:sharedUserId="android.uid.phone"
        android:sharedUserLabel="@string/phoneAppLabel"
>
    <!--: to pass lint -->
    <uses-sdk android:minSdkVersion="24"/>
    <!--: @}-->
    <original-package android:name="com.android.phone" />
    <application android:name="PhoneApp"
            android:persistent="true"
            android:label="@string/phoneAppLabel"
            android:icon="@mipmap/ic_launcher_phone"
            android:allowBackup="false"
            android:supportsRtl="true"
            android:usesCleartextTraffic="true"
            android:defaultToDeviceProtectedStorage="true"
            android:directBootAware="true">

 PhoneApp的属性android:persistent="true"

android:persistent=true属性。
系统启动后,会通过ActivityManagerService的systemReady,加载persistent是true的应用。
拥有此属性的app将不能被kill或kill后会自动重启。
不过此apk是想做到不被kill,还是要在system/app下

ActivityManagerService在启动后会去遍历所有android:persistent="true"的应用,而后交由Process通过socket通知zygote fork一个新的进程,phone进程启动具体过程如下:

1)startBootstrapServices 

SystemServer执行main方法,接着执行run,run 方法主要是下列3 种方法

private void run() {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
}

其中的startBootstrapServices方法去调用startService启动ActivityManagerService

    private void startBootstrapServices() {

        // Activity manager runs the show.
        traceBeginAndSlog("StartActivityManager");
        // TODO: Might need to move after migration to WM.
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);

        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();
        traceEnd();

        // Set up the Application instance for the system process and get started.
        traceBeginAndSlog("SetSystemProcess");
        mActivityManagerService.setSystemProcess();
        traceEnd();

 startService会回调Lifecycle.onStart(),这时已经创建好ActivityManagerService对象mActivityManagerService,然后在SystemServer的startBootstrapServices中继续调用ActivityManagerService的setSystemProcess,在ServiceManager中完成注册ActivityManagerService。

至此ActivityManagerService完成了初始化。 

2067      public void setSystemProcess() {
2068          try {
2069              ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
2070                      DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
2071              ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);

2)startOtherServices

private void startOtherServices() {
     mActivityManagerService.systemReady(new Runnable() ...
}
9176      public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
9177          traceLog.traceBegin("PhaseActivityManagerReady");
9279  
9280          synchronized (this) {
9281              // Only start up encryption-aware persistent apps; once user is
9282              // unlocked we'll come back around and start unaware apps
// 核心方法:遍历所有android:persistent属性为true的进程
9283              startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
9284  
9285              // Start up initial activity.
9286              mBooting = true;

------------
7747      void startPersistentApps(int matchFlags) {
7748          if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
7749  
7750          synchronized (this) {
7751              try {
7752                  final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
7753                          .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
7754                  for (ApplicationInfo app : apps) {
7755                      if (!"android".equals(app.packageName)) {

// 接着进入addAppLocked,启动persistent进程
7756                          addAppLocked(app, null, false, null /* ABI override */);
7757                      }
7758                  }
7759              } catch (RemoteException ex) {
7760              }
7761          }
7762      }

---------------

最终: Zygote fork phone进程

Phone实体是Telephony框架对象,可以向该对象发起各种通讯相关的请求,Phone对象是Telephony整个框架的核心,他负责与RIL层的交互。

Phone对象是在PhoneApp这个application初始化过程中被创建的

public class PhoneApp extends Application {
    PhoneGlobals mPhoneGlobals;
    TelephonyGlobals mTelephonyGlobals;

    public PhoneApp() {
    }

    @Override
    public void onCreate() {
        if (UserHandle.myUserId() == 0) {
            // We are running as the primary user, so should bring up the
            // global phone state.
            // 创建PhoneGlobals,即Phone的全局状态
            mPhoneGlobals = new PhoneGlobals(this);
            mPhoneGlobals.onCreate();
public void onCreate() {
    if (VDBG) Log.v(LOG_TAG, "onCreate()...");

    ContentResolver resolver = getContentResolver();

    // 缓存 "voice capable" 标志,来自资源文件的配置
    sVoiceCapable = getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);

    if (mCM == null) {
        // 初始化 telephony framework
        PhoneFactory.makeDefaultPhones(this);
        // 实例化通话管理类CallManager,并把phone注册进去
        mCM = CallManager.getInstance();
        for (Phone phone : PhoneFactory.getPhones()) {
            mCM.registerPhone(phone);
        }

        // 创建NotificationMgr单例,用于显示状态栏图标和控制其他状态栏行为。
        notificationMgr = NotificationMgr.init(this);

        // 发送EVENT_RESTART_SIP信号,如果PhoneGlobals已崩溃并正在重新启动,则重新启动。
        // 走到这里已经存在phone进程,mHandler在处理EVENT_RESTART_SIP消息时,会从UserManager
        // 中查找当前用户的状态,如果处于unlocked状态,才调用startSipService
        mHandler.sendEmptyMessage(EVENT_RESTART_SIP);

        // 创建一个CdmaPhoneCallState实例并将其初始化为IDLE
        // 通话状态包括IDLE/SINGLE_ACTIVE/THRWAY_ACTIVE/CONF_CALL
        cdmaPhoneCallState = new CdmaPhoneCallState();
        cdmaPhoneCallState.CdmaPhoneCallStateInit();

        // 获取电源管理器mPowerManager、唤醒锁mWakeLock、锁屏管理器mKeyguardManager
        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
        // 当我们不关心显示器时,用于保持处理器唤醒的锁定
        mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
                | PowerManager.ON_AFTER_RELEASE, LOG_TAG);

        mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

        // 为了屏蔽在通话过程中提示系统更新相关事件,创建UpdateLock对象
        mUpdateLock = new UpdateLock("phone");

        // 实例化通话路由管理器
        callGatewayManager = CallGatewayManager.getInstance();

        // 实例化通话信息缓存类,它会记住自定义铃声发送到语音邮件设置。 异步缓存将在此调用之后立即启动。
        callerInfoCache = CallerInfoCache.init(this);
        // 实例化phone接口管理类,这个类可用于访问/修改phone的状态,比如通话状态/数据连接/网络状态等等
        phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
        // 实例化运营商配置加载类
        configLoader = CarrierConfigLoader.init(this);

        // 实例化CallNotifier,它处理来自电话层的异步事件(比如在有来电时启动来电呼叫UI)
        notifier = CallNotifier.init(this);

        // 注册ICC的EVENT_SIM_NETWORK_LOCKED状态监听处理
        PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);

        // 注册MMI/USSD事件的监听处理
        mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);

        // 注册连接事件的监听处理,ConnectionHandler处理PHONE_STATE_CHANGED事件
        PhoneUtils.initializeConnectionHandler(mCM);

        // 注册一些广播事件处理
        IntentFilter intentFilter =
                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
        intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
        intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
        intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
        intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
        intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        registerReceiver(mReceiver, intentFilter);

        IntentFilter sipIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
        sipIntentFilter.addAction(SipManager.ACTION_SIP_SERVICE_UP);
        sipIntentFilter.addAction(SipManager.ACTION_SIP_CALL_OPTION_CHANGED);
        sipIntentFilter.addAction(SipManager.ACTION_SIP_REMOVE_PHONE);
        registerReceiver(mSipReceiver, sipIntentFilter);

        mCarrierVvmPackageInstalledReceiver.register(this);

        // 设置手机中偏好设置的默认值
        PreferenceManager.setDefaultValues(this, R.xml.network_setting_fragment, false);

        PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);

        // 在给定手机的当前状态的情况下,确保正确初始化音频模式(以及我们自己的一些音频模式相关状态)。
        PhoneUtils.setAudioMode(mCM);
    }

    // 尝试加载SimProvider以使其准备就绪
    resolver.getType(Uri.parse("content://icc/adn"));

    // TODO: 注册Cdma信息记录
    // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);

    // 读取HAC设置并配置音频硬件
    if (getResources().getBoolean(R.bool.hac_enabled)) {
        int hac = android.provider.Settings.System.getInt(
                getContentResolver(),
                android.provider.Settings.System.HEARING_AID,
                0);
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.setParameter(SettingsConstants.HAC_KEY,
                hac == SettingsConstants.HAC_ENABLED
                        ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF);
    }
}

PhoneGlobals.onCreate()主要做了以下工作:

1.初始化 telephony framework

2.实例化各种管理类CallManager,NotificationMgr,PowerManager,KeyguardManager,CallGatewayManager,PhoneInterfaceManager

3.设置Phone的一些初始化配置,注册相关广播,初始化SimProvider,配置音频硬件等

其中,各大管理类和各种配置可根据注释以及源码自己查看,这里继续解析Phone,即Telephony framework (PhoneFactory.makeDefaultPhones(this));

初始化 telephony 框架

Telephony应用框架层启动流程

// Initialize the telephony framework
297              PhoneFactory.makeDefaultPhones(this);

 1. 创建了 RIL 对象;2. 初始化了 SubscriptionController; 3. 检查是否是多 SIM 卡

public static void makeDefaultPhone(Context context) {
        synchronized (sLockProxyPhones) {
            if (!sMadeDefaults) {
                sContext = context;
                // 实例化telephony硬件资源控制接口,这里的硬件资源包括SIM/MODEM/RIL
                TelephonyDevController.create();

                int retryCount = 0;
                // 通过尝试创建地址为"com.android.internal.telephony"的LocalServerSocket来中断循环
                for(;;) {
                    boolean hasException = false;
                    retryCount ++;

                    try {
                        // 使用UNIX域套接字来防止后续初始化
                        new LocalServerSocket("com.android.internal.telephony");
                    } catch (java.io.IOException ex) {
                        hasException = true;
                    }

                    if ( !hasException ) {
                        break;
                    } else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
                        throw new RuntimeException("PhoneFactory probably already running");
                    } else {
                        try {
                            Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
                        } catch (InterruptedException er) {
                        }
                    }
                }

                // Phone的状态通知器,对外发出通知,包括通话状态/网络服务状态/信号强度/SS(运营商补充服务--呼叫转移等)/网络小区信息/数据连接等等,
                // DefaultPhoneNotifier其实就是个中转站,本质上各接口都是通过ITelephonyRegistry代理来访问"telephony.registry"服务
                sPhoneNotifier = new DefaultPhoneNotifier();

                // CDMA subscription状态管理
                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);

                // 在多SIM模式的情况下,创建两个Phone,RIL实例,isMultiSimEnabled()函数检查它是单SIM还是多SIM模式
                int numPhones = TelephonyManager.getDefault().getPhoneCount();
                // 返回设备是否应使用动态绑定或静态实现(不建议使用)
                boolean isDynamicBinding = sContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_dynamic_bind_ims);
                // 获取默认IMS实现的包名称
                String defaultImsPackage = sContext.getResources().getString(
                        com.android.internal.R.string.config_ims_package);
                // 启动ImsResolver并绑定到ImsServices
                sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones,
                        isDynamicBinding);
                sImsResolver.initPopulateCacheAndStartBind();

                int[] networkModes = new int[numPhones];
                // 创建Phones数组,用来存储Phone实例
                sPhones = new Phone[numPhones];
                // 创建RIL数组,用来存储RIL实例
                sCommandsInterfaces = new RIL[numPhones];
                // TelephonyNetworkFactory是创建网络代理的工厂,默认网络代理的评判根据分数和能力来进行,也可以通过重载来实现更复杂的计算来评判
                sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];

                for (int i = 0; i < numPhones; i++) {
                    // 读取系统属性并生成命令接口获取首选网络类型。
                    // 初始化网络模式和RIL,支持几张卡就初始化几个RIL
                    networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;
                    sCommandsInterfaces[i] = new RIL(context, networkModes[i],
                            cdmaSubscription, i);
                }
                // SubscriptionController提供访问SubscriptionInfo的IPC接口,SubscriptionInfo是framework层对sim卡信息的抽象表示,
                // 数据都存储在数据库中,比如设置SIM卡的icon/名称/号码,读取plmn/mccmnc等等
                SubscriptionController.init(context, sCommandsInterfaces);

                // 实例化UiccController/assets/images/android/tele/用于访问UICC卡的相关信息,通过在RIL中注册事件监听来实现
                sUiccController = UiccController.make(context, sCommandsInterfaces);

                if (context.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_TELEPHONY_EUICC)) {
                    sEuiccController = EuiccController.init(context);
                    sEuiccCardController = EuiccCardController.init(context);
                }

                // 根据SIM卡数量创建Phone实例,Phone实例分为两种类型GSM和CDMA
                // 7.0开始没有CDMAPhone类,把之前的GSMPhone和CDMAPhone合并成了GsmCdmaPhone
                // 同样的就有了GsmCdmaCallTracker/GsmCdmaConnection
                for (int i = 0; i < numPhones; i++) {
                    Phone phone = null;
                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                        phone = new GsmCdmaPhone(context,
                                sCommandsInterfaces[i], sPhoneNotifier, i,
                                PhoneConstants.PHONE_TYPE_GSM,
                                TelephonyComponentFactory.getInstance());
                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                        phone = new GsmCdmaPhone(context,
                                sCommandsInterfaces[i], sPhoneNotifier, i,
                                PhoneConstants.PHONE_TYPE_CDMA_LTE,
                                TelephonyComponentFactory.getInstance());
                    }

                    sPhones[i] = phone;
                }

                // 在基类中设置默认Phone
                sPhone = sPhones[0];
                sCommandsInterface = sCommandsInterfaces[0];

                // 确保我们有一个默认的短信应用程序。 请求将updateIfNeeded设置为true的应用程序足以配置默认的SMS应用程序。
                ComponentName componentName =
                        SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */);
                String packageName = "NONE";
                if (componentName != null) {
                    packageName = componentName.getPackageName();
                }

                // 设置监视器以监视SMS程序包的更改
                SmsApplication.initSmsPackageMonitor(context);

                sMadeDefaults = true;
                // SubscriptionInfoUpdater主要监听sim卡的插入/拔出/上锁/加载等情况
                sSubInfoRecordUpdater = new SubscriptionInfoUpdater(
                        BackgroundThread.get().getLooper(), context, sPhones, sCommandsInterfaces);
                SubscriptionController.getInstance().updatePhonesAvailability(sPhones);

                // 在默认设置完成后开始监控。 在创建ImsPhone之前,必须准备好默认Phone,因为ImsService在打开时可能需要它
                // 这应该为ImsService的ImsResolver实现初始化多个ImsPhones。
                for (int i = 0; i < numPhones; i++) {
                    sPhones[i].startMonitoringImsService();
                }

                // ITelephonyRegistry提供了访问通话状态/网络服务状态/信号强度/SS(运营商补充服务--呼叫转移等)/网络小区信息/数据连接等等的接口
                ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(
                        ServiceManager.getService("telephony.registry"));
                SubscriptionController sc = SubscriptionController.getInstance();

                sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);
                //PhoneSwitcher监听subscription的变化和网络请求来决定启用哪个phone
                sPhoneSwitcher = new PhoneSwitcher(MAX_ACTIVE_PHONES, numPhones,
                        sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,
                        sPhones);

                // ProxyController类用于get/set radio相关的操作
                sProxyController = ProxyController.getInstance(context, sPhones,
                        sUiccController, sCommandsInterfaces, sPhoneSwitcher);

                sIntentBroadcaster = IntentBroadcaster.getInstance(context);

                sNotificationChannelController = new NotificationChannelController(context);

                // 网络数据连接辅助类
                sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];
                for (int i = 0; i < numPhones; i++) {
                    sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
                            sPhoneSwitcher, sc, sSubscriptionMonitor, Looper.myLooper(),
                            sContext, i, sPhones[i].mDcTracker);
                }
            }
        }
    }

总结一下上面对makeDefaultPhone()方法的分析:

1.初始化各种控制接口SubscriptionController,UiccController,主要负责SIM卡状态信息的控制监听

2.根据SIM卡数量创建Phone和RIL实例,并且设置默认Phone和RIL,Phone分为GSM和CDMA两大种类

3.启动ImsResolver并绑定到ImsServices

Android中有三种PhoneFactory

1.PhoneFactory.java ——–>用于创建GsmCdmaPhone对象
2.ImsPhoneFactory.java ——–>用于创建ImsPhone对象
3.SipPhoneFactory.java ——–>用于创建SipPhone对象

链接

3. Telephony phone 

其中:

其中在 GsmCdmaPhone 构造方法会 makeXXXTreacker () 方法

3. 1 GsmCdmaPhone 

GsmCdmaPhone 对象作为Telephony 业务模型中的关键对象、中心对象,其Java 类的定义和继承关系

public abstract class Phone extends Handler implements PhoneInternalInterface {

------- 1 ------
public class GsmCdmaPhone extends Phone {

------- 2 -------
abstract class ImsPhoneBase extends Phone {
public class ImsPhone extends ImsPhoneBase {

Phone 抽象类的三个子类

Sip Phone 负责Sip 网络电话业务
GsmCdmaPhone 承载CS ( Circuit Switch ,电路交换)域的电信业务
Ims Phone 承载高清语音通话业务

关键属性对象
mCi 是RILJ 对象引用, mDcTracker 是DcTracker 对象引用, mCT 是GsmCdmaCallTracker 对象引用, mSST 是ServiceStateTracker 对象引用

GsmCdmaPhone 关键属性

GsmCdmaPhone 关键方法

3. 2 GsmCdmaPhone 的Handler 消息处理机制

GsmCdmaPhone 类中的Handler 消息处理机制可分成以下三个大类:

• 基本Handler 消息注册和响应机制。
• Registrantlist 封装的Handler 消息运行机制。
• 创建的Message 对象作为RILJ 对象回调入口。

1. 基本Handler 消息注册和响应机制

GsmCdmaPhone 类中基本的Handler 消息注册和响应机制包括两方面的内容:
调用mCi.registerForxxx 方法,向RILJ 对象注册单个的Handler消息【在 GsmCdmaPhone 的构造方法会初始化】


• Handler 对象handleMessage 接收并响应Message 消息


在GsmCdmaPhone 类的构造方法的调用过程中,即加载Telephony 业务模型的过程中,以调用mCi.registerForxxx(this, what, null) 的方式向RILJ 对象发起消息注册。在GsmCdmaPhone 和Phone类中均重写了父类的handleMessage 方法,从而响应RILJ 对象发出的Handler 消息回调通知。

2. Registrantlist 封装的Handler 消息运行机制

在Phone 抽象类中,一共定义了14 个Registrantlist 对象。针对这14 个Registrantlist 对象,分别实现了 RegisterFor×××和unregisterForXXX 方法来完成多个Handler 消息的注册和取消注册

3. 创建的Message 对象作为RILJ 对象回调入口

GsmCdmaPhone 对象在与RILJ 对象的交互过程中创建Message 对象,作为R ILJ 对象的回调入口。使用这种方式不需要向R ILJ 注册HanIder 消息,其生命周期很短,仅在一次交互过程中有效,决定了这种交互方式的灵活性。GsmCdmaPhone 对象提供的方法中有一些处理逻辑。首先,创建基于GsmCdmaPhone 对象的Message 对象,然后将此对象作为参数调用mCi 对象的方法;其次, RILJ 对象处理完成后,通过Message 对象进行回调;最后,在GsmCdmaPhone 对象的handleMessage 方法中接收和响应Message 对象发出的Handler 消息。这种Handler 消息处理方式的代码逻辑详情如下

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值