电话中工厂模式和源码分析

来源:互联网 发布:小米 查看网络制式 *# 编辑:程序博客网 时间:2024/05/01 09:09

工厂模式应该是应用非常广泛的模式了,具体描述和过程网上应该有非常多的描述了,这里不再做更多的介绍。

http://blog.csdn.net/jason0539/article/details/23020989

在telephony中,其实使用了大量的工厂模式,但是大多是都是简单工厂模式,我觉得简单工厂模式,它们的用处就是构建相应的实例。

PhoneFactory

/frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneFactory.java

phone

/frameworks/opt/telephony/src/java/com/android/internal/telephony/Phone.java

PhoneFactory,就是只在phone的工厂,phone是什么呢?
首先phone继承了PhoneInternalInterface这个接口,通过这个接口,就大致能了解phone的作用。

/frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneInternalInterface.java

这个接口有非常多的方法:

    /**     * Get the current ServiceState. Use     * <code>registerForServiceStateChanged</code> to be informed of     * updates.     */    ServiceState getServiceState();    /**     * Get the current CellLocation.     */    CellLocation getCellLocation();    /**     * Answers a ringing or waiting call. Active calls, if any, go on hold.     * Answering occurs asynchronously, and final notification occurs via     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,     * java.lang.Object) registerForPreciseCallStateChanged()}.     *     * @param videoState The video state in which to answer the call.     * @exception CallStateException when no call is ringing or waiting     */    void acceptCall(int videoState) throws CallStateException;    /**     * Reject (ignore) a ringing call. In GSM, this means UDUB     * (User Determined User Busy). Reject occurs asynchronously,     * and final notification occurs via     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,     * java.lang.Object) registerForPreciseCallStateChanged()}.     *     * @exception CallStateException when no call is ringing or waiting     */    void rejectCall() throws CallStateException;    /**     * Places any active calls on hold, and makes any held calls     *  active. Switch occurs asynchronously and may fail.     * Final notification occurs via     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,     * java.lang.Object) registerForPreciseCallStateChanged()}.     *     * @exception CallStateException if a call is ringing, waiting, or     * dialing/alerting. In these cases, this operation may not be performed.     */    void switchHoldingAndActive() throws CallStateException;

有数据相关的,有电话相关。总的来说telephony相关的所有业务有依靠这个类,通过这个接口可以拿到电话的服务状态,网络状态,拨打接听电话。
PhoneFactory就是来制造phone的。

PhoneFactory

通过源码可以看到PhoneFactory其实非常简单,总共只有不到500行。
具体只有四个构建实例的方法

public static void makeDefaultPhones(Context context)public static void makeDefaultPhone(Context context)public static SipPhone makeSipPhone(String sipUri)public static Phone makeImsPhone(PhoneNotifier phoneNotifier, Phone defaultPhone)

所有PhoneFactory是一个简单工厂模式,并且它类似与一个单例模式。在phone进程启动时makeDefaultPhones,之后通过getPhone来使用之前构造的phone。

makeDefaultPhone

    /**     * FIXME replace this with some other way of making these     * instances     */    public static void makeDefaultPhone(Context context) {        synchronized (sLockProxyPhones) { //通过锁来保证只执行一次            if (!sMadeDefaults) {                sContext = context;                // create the telephony device controller.                TelephonyDevController.create();                int retryCount = 0;                for(;;) {                    boolean hasException = false;                    retryCount ++;                    try {                        // use UNIX domain socket to                        // prevent subsequent initialization                        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) {                        }                    }                }                sPhoneNotifier = new DefaultPhoneNotifier();                TelephonyComponentFactory telephonyComponentFactory                    = TelephonyComponentFactory.getInstance();  //又是一个工厂                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);                Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);                /* In case of multi SIM mode two instances of Phone, RIL are created,                   where as in single SIM mode only instance. isMultiSimEnabled() function checks                   whether it is single SIM or multi SIM mode */                int numPhones = TelephonyManager.getDefault().getPhoneCount();                int[] networkModes = new int[numPhones];                sPhones = new Phone[numPhones];                sCommandsInterfaces = new RIL[numPhones];                sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];                // 更具phone的个数new出对应的数组                for (int i = 0; i < numPhones; i++) {                    // reads the system properties and makes commandsinterface                    // Get preferred network type.                    networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;                    Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));                    sCommandsInterfaces[i] = new RIL(context, networkModes[i],                            cdmaSubscription, i);                }                Rlog.i(LOG_TAG, "Creating SubscriptionController");                telephonyComponentFactory.initSubscriptionController(                        context, sCommandsInterfaces);                // Instantiate UiccController so that all other classes can just                // call getInstance()                sUiccController = UiccController.make(context, sCommandsInterfaces);                for (int i = 0; i < numPhones; i++) {                    Phone phone = null;                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {                        phone = telephonyComponentFactory.makePhone(context,                                sCommandsInterfaces[i], sPhoneNotifier, i,                                PhoneConstants.PHONE_TYPE_GSM,                                telephonyComponentFactory);                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {                        phone = telephonyComponentFactory.makePhone(context,                                sCommandsInterfaces[i], sPhoneNotifier, i,                                PhoneConstants.PHONE_TYPE_CDMA_LTE,                                telephonyComponentFactory);                    }                    // 使用telephonyComponentFactory制造不同类型的phone                    Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);                    sPhones[i] = phone;                }                // Set the default phone in base class.                // FIXME: This is a first best guess at what the defaults will be. It                // FIXME: needs to be done in a more controlled manner in the future.                sPhone = sPhones[0];                sCommandsInterface = sCommandsInterfaces[0];                // Ensure that we have a default SMS app. Requesting the app with                // updateIfNeeded set to true is enough to configure a default SMS app.                ComponentName componentName =                        SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */);                String packageName = "NONE";                if (componentName != null) {                    packageName = componentName.getPackageName();                }                Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);                // Set up monitor to watch for changes to SMS packages                SmsApplication.initSmsPackageMonitor(context);                sMadeDefaults = true;                Rlog.i(LOG_TAG, "Creating SubInfoRecordUpdater ");                sSubInfoRecordUpdater = telephonyComponentFactory.makeSubscriptionInfoUpdater(                        context, sPhones, sCommandsInterfaces);                SubscriptionController.getInstance().updatePhonesAvailability(sPhones);                // Start monitoring after defaults have been made.                // Default phone must be ready before ImsPhone is created                // because ImsService might need it when it is being opened.                for (int i = 0; i < numPhones; i++) {                    sPhones[i].startMonitoringImsService();                }                ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(                        ServiceManager.getService("telephony.registry"));                SubscriptionController sc = SubscriptionController.getInstance();                sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);                sPhoneSwitcher = telephonyComponentFactory.                        makePhoneSwitcher (MAX_ACTIVE_PHONES, numPhones,                        sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,                        sPhones);                sProxyController = ProxyController.getInstance(context, sPhones,                        sUiccController, sCommandsInterfaces, sPhoneSwitcher);                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);                }                telephonyComponentFactory.makeExtTelephonyClasses(                        context, sPhones, sCommandsInterfaces);            }        }    }

可以看到,又有一个工厂TelephonyComponentFactory,通过TelephonyComponentFactory构造了不同类型的phone并且保存在了PhoneFactory当中。而TelephonyComponentFactory更像是一个纯粹的工厂,其中makePhone。

    public Phone makePhone(Context context, CommandsInterface ci, PhoneNotifier notifier,            int phoneId, int precisePhoneType,            TelephonyComponentFactory telephonyComponentFactory) {        Rlog.d(LOG_TAG, "makePhone");        Phone phone = null;        if (precisePhoneType == PhoneConstants.PHONE_TYPE_GSM) {            phone = new GsmCdmaPhone(context,                ci, notifier, phoneId,                PhoneConstants.PHONE_TYPE_GSM,                telephonyComponentFactory);        } else if (precisePhoneType == PhoneConstants.PHONE_TYPE_CDMA) {                phone = new GsmCdmaPhone(context,                ci, notifier, phoneId,                PhoneConstants.PHONE_TYPE_CDMA_LTE,                telephonyComponentFactory);        }        return phone;    }

可以看到这里会根据类型new出不同的phone。

getPhone

而我们真正使用这些phone对象的时候都是通过get方法来使用,所以这个PhoneFactory又类似于一个单例模式,

    public static Phone getDefaultPhone() {        synchronized (sLockProxyPhones) {            if (!sMadeDefaults) {                throw new IllegalStateException("Default phones haven't been made yet!");            }            return sPhone;        }    }    public static Phone getPhone(int phoneId) {        Phone phone;        String dbgInfo = "";        synchronized (sLockProxyPhones) {            if (!sMadeDefaults) {                throw new IllegalStateException("Default phones haven't been made yet!");                // CAF_MSIM FIXME need to introduce default phone id ?            } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {                if (DBG) dbgInfo = "phoneId == DEFAULT_PHONE_ID return sPhone";                phone = sPhone;            } else {                if (DBG) dbgInfo = "phoneId != DEFAULT_PHONE_ID return sPhones[phoneId]";                phone = (((phoneId >= 0)                                && (phoneId < TelephonyManager.getDefault().getPhoneCount()))                        ? sPhones[phoneId] : null);            }            if (DBG) {                Rlog.d(LOG_TAG, "getPhone:- " + dbgInfo + " phoneId=" + phoneId +                        " phone=" + phone);            }            return phone;        }    }

总结:这个phoneFactory的构建方法只能使用一次,即在phone进程启动时就会make出相应的phone,之后会根据不同的情况来使用不同phone,这里使用工厂模式,也就是能够屏蔽一下phone的构造方法。

TelecomSystem

google会在非常多的地方用Factory这个东西,有时候我觉得更像一种标准,和代码的规范,比如在构建TelecomSystem时

    /**     * This method is to be called by components (Activitys, Services, ...) to initialize the     * Telecom singleton. It should only be called on the main thread. As such, it is atomic     * and needs no synchronization -- it will either perform its initialization, after which     * the {@link TelecomSystem#getInstance()} will be initialized, or some other invocation of     * this method on the main thread will have happened strictly prior to it, and this method     * will be a benign no-op.     *     * @param context     */    static void initializeTelecomSystem(Context context) {        if (TelecomSystem.getInstance() == null) {            final NotificationManager notificationManager =                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);            TelecomSystem.setInstance(                    new TelecomSystem(                            context,                            new MissedCallNotifierImpl.MissedCallNotifierImplFactory() {                                @Override                                // MIUI MOD:                                // public MissedCallNotifierImpl makeMissedCallNotifierImpl(                                public com.android.server.telecom.MissedCallNotifier makeMissedCallNotifierImpl(                                        Context context,                                        PhoneAccountRegistrar phoneAccountRegistrar,                                        PhoneNumberUtilsAdapter phoneNumberUtilsAdapter) {                                    // MIUI MOD:                                    // return new MissedCallNotifierImpl(context,                                    //         phoneAccountRegistrar, phoneNumberUtilsAdapter);                                    return new com.android.server.telecom.MiuiMissedCallNotifierImpl(context,                                            phoneAccountRegistrar, phoneNumberUtilsAdapter);                                }                            },                            new CallerInfoAsyncQueryFactory() {                                @Override                                public CallerInfoAsyncQuery startQuery(int token, Context context,                                        String number,                                        CallerInfoAsyncQuery.OnQueryCompleteListener listener,                                        Object cookie) {                                    Log.i(TelecomSystem.getInstance(),                                            "CallerInfoAsyncQuery.startQuery number=%s cookie=%s",                                            Log.pii(number), cookie);                                    return CallerInfoAsyncQuery.startQuery(                                            token, context, number, listener, cookie);                                }                            },                            new HeadsetMediaButtonFactory() {                                @Override                                public HeadsetMediaButton create(                                        Context context,                                        CallsManager callsManager,                                        TelecomSystem.SyncRoot lock) {                                    return new HeadsetMediaButton(context, callsManager, lock);                                }                            },                            new ProximitySensorManagerFactory() {                                @Override                                public ProximitySensorManager create(                                        Context context,                                        CallsManager callsManager) {                                    return new ProximitySensorManager(                                            new TelecomWakeLock(                                                    context,                                                    PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,                                                    ProximitySensorManager.class.getSimpleName()),                                            callsManager);                                }                            },                            new InCallWakeLockControllerFactory() {                                @Override                                public InCallWakeLockController create(Context context,                                        CallsManager callsManager) {                                    return new InCallWakeLockController(                                            new TelecomWakeLock(context,                                                    PowerManager.FULL_WAKE_LOCK,                                                    InCallWakeLockController.class.getSimpleName()),                                            callsManager);                                }                            },                            new CallAudioManager.AudioServiceFactory() {                                @Override                                public IAudioService getAudioService() {                                    return IAudioService.Stub.asInterface(                                            ServiceManager.getService(Context.AUDIO_SERVICE));                                }                            },                            new BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory() {                                @Override                                public BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl(                                        Context context, TelecomSystem.SyncRoot lock,                                        CallsManager callsManager,                                        PhoneAccountRegistrar phoneAccountRegistrar) {                                    return new BluetoothPhoneServiceImpl(context, lock,                                            callsManager, new BluetoothAdapterProxy(),                                            phoneAccountRegistrar);                                }                            },                            new Timeouts.Adapter(),                            // MIUI MOD:                            // new AsyncRingtonePlayer(),                            new MiuiAsyncRingtonePlayer(context),                            new ViceNotifier() {                                @Override                                public ViceNotificationImpl create(Context context,                                        CallsManager callsManager) {                                    return new ViceNotificationImpl(                                            context.getApplicationContext(), callsManager);                                }                            },                            new PhoneNumberUtilsAdapterImpl(),                            new InterruptionFilterProxy() {                                @Override                                public void setInterruptionFilter(int interruptionFilter) {                                    notificationManager.setInterruptionFilter(interruptionFilter);                                }                                @Override                                public int getCurrentInterruptionFilter() {                                    return notificationManager.getCurrentInterruptionFilter();                                }                                @Override                                public String getInterruptionModeInitiator() {                                    ZenModeConfig config = notificationManager.getZenModeConfig();                                    if (config.manualRule != null) {                                        return config.manualRule.enabler;                                    }                                    return null;                                }                            }                    ));        }        if (BluetoothAdapter.getDefaultAdapter() != null) {            context.startService(new Intent(context, BluetoothPhoneService.class));        }    }

在Android N之后,在TelecomSystem的构造函数传入的都是Factory,而不再是直接new出对应的对象,我觉得这么做的目的,就是这些要构建的对象依赖于一些之前的对象,比如这个:

/** * This is a TEMPORARY fix to make the {@link HeadsetMediaButton} object injectable for testing. * Class {@link HeadsetMediaButton} itself is not testable because it grabs lots of special stuff * from its {@code Context} that cannot be conveniently mocked. * * TODO: Replace with a better design. */public interface HeadsetMediaButtonFactory {    HeadsetMediaButton create(            Context context,            CallsManager callsManager,            TelecomSystem.SyncRoot lock);}

这些对象有一些先后的顺序,在构建HeadsetMediaButton时需要CallsManager。同时我也发现TODO: Replace with a better design.,希望可以在下个版本看到更好的design。

原创粉丝点击