Android 网络bind流程

        在国内无法使用谷歌GMS包,我们选择NLP(network location provider)有提供商有: 百度、高德、腾讯等可以选择,那这一块初始化流程是怎样的呢?我们代码梳理下:

我们知道,LocationManagerService 是由 SystemServer 启动的,然后在 SystemServer 里面执行:locationF.systemRunning(),locationF 就是 LocationManagerService,那看下具体代码:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/LocationManagerService.java#systemRunning

276    public void systemRunning() {
277        synchronized (mLock) {
278            if (D) Log.d(TAG, "systemRunning()");

…………

345            // prepare providers
346            loadProvidersLocked();  ---> 主要看下这个

在 loadProvidersLocked 方法中,我们仅看和网络相关的,重点是下面的这个bind

636        // bind to network provider
637        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
638                mContext,
639                LocationManager.NETWORK_PROVIDER,
640                NETWORK_LOCATION_SERVICE_ACTION,
641                com.android.internal.R.bool.config_enableNetworkLocationOverlay,   ---> 这几个都是在这里配置:/frameworks/base/core/res/res/values/config.xml
642                com.android.internal.R.string.config_networkLocationProviderPackageName,  ---> 三方包名,比如百度Nlp:com.baidu.map.location
643                com.android.internal.R.array.config_locationProviderPackageNames, ---> 添加三方包名,比如百度Nlp:com.baidu.map.location
644                mLocationHandler);
645        if (networkProvider != null) {
646            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
647            mProxyProviders.add(networkProvider);
648            addProviderLocked(networkProvider);
649        } else {
650            Slog.w(TAG, "no network location provider found");
651        }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/location/LocationProviderProxy.java#createAndBind

58    public static LocationProviderProxy createAndBind(   ---> 先去根据config去启动初始包
59            Context context, String name, String action,
60            int overlaySwitchResId, int defaultServicePackageNameResId,
61            int initialPackageNamesResId, Handler handler) {
62        LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
63                overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId,
64                handler);
65        if (proxy.bind()) {   ---> 然后才去bind
66            return proxy;
67        } else {
68            return null;
69        }

看下对应参数:

        name:NETWORK_PROVIDER

        action:"com.android.location.service.v3.NetworkLocationProvider"

        overlaySwitchResId:config_enableNetworkLocationOverlay     ---> 一般是 false

        ​defaultServicePackageNameResId​:三方包名

        ​initialPackageNamesResId​:配置的包含三方包名

72    private LocationProviderProxy(Context context, String name, String action,
73            int overlaySwitchResId, int defaultServicePackageNameResId,
74            int initialPackageNamesResId, Handler handler) {
75        mContext = context;
76        mName = name;
77        mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
78                defaultServicePackageNameResId, initialPackageNamesResId,
79                mNewServiceWork, handler);
80    }
107    public ServiceWatcher(Context context, String logTag, String action,
108            int overlaySwitchResId, int defaultServicePackageNameResId,
109            int initialPackageNamesResId, Runnable newServiceWork,
110            Handler handler) {
111        mContext = context;
112        mTag = logTag;
113        mAction = action;
114        mPm = mContext.getPackageManager();
115        mNewServiceWork = newServiceWork;
116        mHandler = handler;
117        Resources resources = context.getResources();
118
119        // Whether to enable service overlay.
120        boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
121        ArrayList<String> initialPackageNames = new ArrayList<String>();
122        if (enableOverlay) {  ---> 一般是false,所以走 else 的逻辑
123            // A list of package names used to create the signatures.
124            String[] pkgs = resources.getStringArray(initialPackageNamesResId);
125            if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs));
126            mServicePackageName = null;
127            if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
128        } else {
129            // The default package name that is searched for service implementation when overlay is
130            // disabled.
131            String servicePackageName = resources.getString(defaultServicePackageNameResId);
132            if (servicePackageName != null) initialPackageNames.add(servicePackageName);
133            mServicePackageName = servicePackageName;
134            if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName);  --->配置的三方包名
135        }
136        mSignatureSets = getSignatureSets(context, initialPackageNames);
137    }

走完后,我们再看上面提到的 proxy.bind 方法:

82    private boolean bind () {
83        return mServiceWatcher.start();
84    }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/ServiceWatcher.java#start

148    public boolean start() {
149        if (isServiceMissing()) return false;
150
151        synchronized (mLock) {
152            bindBestPackageLocked(mServicePackageName, false);  ---> 注意这个方法,false 传下去,会用到
153        }
154
155        // listen for user change
156        IntentFilter intentFilter = new IntentFilter();
157        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
158        intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
159        mContext.registerReceiverAsUser(new BroadcastReceiver() {
160            @Override
161            public void onReceive(Context context, Intent intent) {
162                final String action = intent.getAction();
163                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
164                        UserHandle.USER_NULL);
165                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
166                    switchUser(userId);
167                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
168                    unlockUser(userId);
169                }
170            }
171        }, UserHandle.ALL, intentFilter, null, mHandler);
172
173        // listen for relevant package changes if service overlay is enabled.
174        if (mServicePackageName == null) {
175            mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
176        }
177
178        return true;
179    }
192    /**
193     * Searches and binds to the best package, or do nothing if the best package
194     * is already bound, unless force rebinding is requested.
195     *
196     * @param justCheckThisPackage Only consider this package, or consider all
197     *            packages if it is {@code null}.
198     * @param forceRebind Force a rebinding to the best package if it's already
199     *            bound.
200     * @returns {@code true} if a valid package was found to bind to.
201     */
202    @GuardedBy("mLock")
203    private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
204        Intent intent = new Intent(mAction);
205        if (justCheckThisPackage != null) {
206            intent.setPackage(justCheckThisPackage);
207        }
208        final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
209                PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
210                mCurrentUserId);   ---> 查找
211        int bestVersion = Integer.MIN_VALUE;
212        ComponentName bestComponent = null;
213        boolean bestIsMultiuser = false;
214        if (rInfos != null) {
215            for (ResolveInfo rInfo : rInfos) {
216                final ComponentName component = rInfo.serviceInfo.getComponentName();
217                final String packageName = component.getPackageName();
218
219                // check signature
220                try {
221                    PackageInfo pInfo;
222                    pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
223                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
224                    if (!isSignatureMatch(pInfo.signatures)) {
225                        Log.w(mTag, packageName + " resolves service " + mAction
226                                + ", but has wrong signature, ignoring");
227                        continue;
228                    }
229                } catch (NameNotFoundException e) {
230                    Log.wtf(mTag, e);
231                    continue;
232                }
233
234                // check metadata  --> NLP中service需要配置metadata属性,因为下面会和默认最小值比对
235                int version = Integer.MIN_VALUE;
236                boolean isMultiuser = false;
237                if (rInfo.serviceInfo.metaData != null) {
238                    version = rInfo.serviceInfo.metaData.getInt(
239                            EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
240                    isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
241                }
242
243                if (version > bestVersion) {
244                    bestVersion = version;
245                    bestComponent = component;
246                    bestIsMultiuser = isMultiuser;
247                }
248            }
249
250            if (D) {
251                Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
252                        (justCheckThisPackage == null ? ""
253                                : "(" + justCheckThisPackage + ") "), rInfos.size(),
254                        (bestComponent == null ? "no new best component"
255                                : "new best component: " + bestComponent)));
256            }
257        } else {
258            if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
259        }
260
261        if (bestComponent == null) {
262            Slog.w(mTag, "Odd, no component found for service " + mAction);
263            unbindLocked();
264            return false;
265        }
266
267        final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
268        final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
269                && bestVersion == mBoundVersion && userId == mBoundUserId;
270        if (forceRebind || !alreadyBound) {   ---> forceRebind 传下来的参数是 false,第一次,alreadyBound 也为false
271            unbindLocked();  --> 执行
272            bindToPackageLocked(bestComponent, bestVersion, userId);
273        }
274        return true;
275    }
292    @GuardedBy("mLock")
293    private void bindToPackageLocked(ComponentName component, int version, int userId) {
294        Intent intent = new Intent(mAction);
295        intent.setComponent(component);
296        mBoundComponent = component;
297        mBoundPackageName = component.getPackageName();
298        mBoundVersion = version;
299        mBoundUserId = userId;
300        if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
301        mContext.bindServiceAsUser(intent, this,        ---> bind,成功后回调该 onServiceConnected 方法,失败回调 onServiceDisconnected
302                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
303                new UserHandle(userId));
304    }

绑定成功后回调:

367    @Override
368    public void onServiceConnected(ComponentName component, IBinder binder) {
369        synchronized (mLock) {
370            if (component.equals(mBoundComponent)) {
371                if (D) Log.d(mTag, component + " connected");
372                mBoundService = binder;
373                if (mHandler !=null && mNewServiceWork != null) {
374                    mHandler.post(mNewServiceWork);    ---> 这个是之前传下来的,现在执行这个
375                }
376            } else {
377                Log.w(mTag, "unexpected onServiceConnected: " + component);
378            }
379        }
380    }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/location/LocationProviderProxy.java#mNewServiceWork

95    private Runnable mNewServiceWork = new Runnable() {
96        @Override
97        public void run() {
98            if (D) Log.d(TAG, "applying state to connected service");
99
100            boolean enabled;
101            final ProviderProperties[] properties = new ProviderProperties[1];
102            ProviderRequest request;
103            WorkSource source;
104            synchronized (mLock) {
105                enabled = mEnabled;
106                request = mRequest;
107                source = mWorksource;
108            }
109
110
111            mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
112                @Override
113                public void run(IBinder binder) {
114                    ILocationProvider service = ILocationProvider.Stub.asInterface(binder);  ---> 这个service实际上就是bind三方的NLP
115                    try {
116                        // load properties from provider
117                        properties[0] = service.getProperties();
118                        if (properties[0] == null) {
119                            Log.e(TAG, mServiceWatcher.getBestPackageName() +
120                                    " has invalid location provider properties");
121                        }
122
123                        // apply current state to new service
124                        if (enabled) {
125                            service.enable();
126                            if (request != null) {
127                                service.setRequest(request, source);
128                            }
129                        }
130                    } catch (RemoteException e) {
131                        Log.w(TAG, e);
132                    } catch (Exception e) {
133                        // never let remote service crash system server
134                        Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
135                    }
136                }
137            });
138
139            synchronized (mLock) {
140                mProperties = properties[0];
141            }
142        }
143    };

至此,整个bind流程记录完毕,另外如何集成三方NLP呢?这个我们可以参考公众号:蘑菇君先生

Android R 集成 百度NLP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值