电话中工厂模式和源码分析
来源:互联网 发布:小米 查看网络制式 *# 编辑:程序博客网 时间: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。
- 电话中工厂模式和源码分析
- Android 系统电话管理机制一--工厂模式和代理模式
- Android源码分析之简单工厂模式
- Android源码分析之工厂方法模式
- Android源码分析之抽象工厂模式
- 从Phone源码中分析来电话流程(部分)
- 装饰者模式-JDK中InputStream和HttpServletRequsetWrapper源码分析
- 简单工厂、工厂方法模式和抽象工厂模式的分析
- 设计模式之工厂模式 c++实现和详细分析
- javaScript工厂模式分析
- 创建型模式之 工厂、简单工厂、抽象工厂 简单图析和代码分析 笔记
- 工厂模式(head first中简单工厂和工厂模式的迷惑)
- Spring Bean工厂继承关系和源码分析
- 简单工厂和工厂模式
- 简单工厂和工厂模式
- 工厂模式 和工厂方法
- 简单工厂和工厂模式
- Android 最常用的设计模式八 安卓源码分析—工厂方法模式factory
- gRPC 源码编译安装
- web前端入门积累
- 《thinking in JAVA》读书笔记
- PHP基础教程-14 字符串变量简介
- 贴之道-我不想陪伴你太久
- 电话中工厂模式和源码分析
- Codeforces 838 A Binary Blocks(前缀和)
- 在线画流程图的工具
- Java中的运算符
- 菜鸟之歌
- MySQL创建用户及赋予权限
- python 与命令
- 《thinking in JAVA》读书笔记 (二)
- 2017暑训入门摸底(hdu4500,hdu2190,hdu2111,hud3787,hdu2108)