17d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/*
27d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Copyright (C) 2008 The Android Open Source Project
37d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
47d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
57d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * you may not use this file except in compliance with the License.
67d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * You may obtain a copy of the License at
77d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
87d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
97d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Unless required by applicable law or agreed to in writing, software
117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * See the License for the specific language governing permissions and
147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * limitations under the License.
157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpackage com.android.phone;
187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.Service;
207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Intent;
217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.OperatorInfo;
227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Binder;
247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.IBinder;
267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.RemoteCallbackList;
287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.RemoteException;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneFactory;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Service code used to assist in querying the network for service
377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * availability.
387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpublic class NetworkQueryService extends Service {
407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // debug data
417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "NetworkQuery";
427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = false;
437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // static events
457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NETWORK_SCAN_COMPLETED = 100;
467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // static states indicating the query status of the service
487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int QUERY_READY = -1;
497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int QUERY_IS_RUNNING = -2;
507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // error statuses that will be retured in the callback.
527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public static final int QUERY_OK = 0;
537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public static final int QUERY_EXCEPTION = 1;
547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** state of the query service */
567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private int mState;
577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** local handle to the phone object */
597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Phone mPhone;
607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Class for clients to access.  Because we know this service always
637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * runs in the same process as its clients, we don't need to deal with
647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * IPC.
657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public class LocalBinder extends Binder {
677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        INetworkQueryService getService() {
687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return mBinder;
697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final IBinder mLocalBinder = new LocalBinder();
727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Local handler to receive the network query compete callback
757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from the RIL.
767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    Handler mHandler = new Handler() {
787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // if the scan is complete, broadcast the results.
827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // to all registerd callbacks.
837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NETWORK_SCAN_COMPLETED:
847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("scan completed, broadcasting results");
857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    broadcastQueryResults((AsyncResult) msg.obj);
867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    };
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * List of callback objects, also used to synchronize access to
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * itself and to changes in state.
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    final RemoteCallbackList<INetworkQueryServiceCallback> mCallbacks =
967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        new RemoteCallbackList<INetworkQueryServiceCallback> ();
977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Implementation of the INetworkQueryService interface.
1007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final INetworkQueryService.Stub mBinder = new INetworkQueryService.Stub() {
1027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /**
1047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Starts a query with a INetworkQueryServiceCallback object if
1057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * one has not been started yet.  Ignore the new query request
1067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * if the query has been started already.  Either way, place the
1077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * callback object in the queue to be notified upon request
1087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * completion.
1097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
1107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void startNetworkQuery(INetworkQueryServiceCallback cb) {
1117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (cb != null) {
1127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // register the callback to the list of callbacks.
1137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                synchronized (mCallbacks) {
1147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mCallbacks.register(cb);
1157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("registering callback " + cb.getClass().toString());
1167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    switch (mState) {
1187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        case QUERY_READY:
1197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // TODO: we may want to install a timeout here in case we
1207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // do not get a timely response from the RIL.
1217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            mPhone.getAvailableNetworks(
1227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED));
1237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            mState = QUERY_IS_RUNNING;
1247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            if (DBG) log("starting new query");
1257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            break;
1267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // do nothing if we're currently busy.
1287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        case QUERY_IS_RUNNING:
1297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            if (DBG) log("query already in progress");
1307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            break;
1317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        default:
1327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
1337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
1347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
1357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /**
1387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Stops a query with a INetworkQueryServiceCallback object as
1397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * a token.
1407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
1417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void stopNetworkQuery(INetworkQueryServiceCallback cb) {
1427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // currently we just unregister the callback, since there is
1437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // no way to tell the RIL to terminate the query request.
1447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // This means that the RIL may still be busy after the stop
1457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // request was made, but the state tracking logic ensures
1467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // that the delay will only last for 1 request even with
1477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // repeated button presses in the NetworkSetting activity.
1487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (cb != null) {
1497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                synchronized (mCallbacks) {
1507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("unregistering callback " + cb.getClass().toString());
1517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mCallbacks.unregister(cb);
1527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
1537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
1547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    };
1567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
1587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void onCreate() {
1597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mState = QUERY_READY;
1607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = PhoneFactory.getDefaultPhone();
1617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Required for service implementation.
1657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
1677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void onStart(Intent intent, int startId) {
1687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Handle the bind request.
1727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
1747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public IBinder onBind(Intent intent) {
1757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: Currently, return only the LocalBinder instance.  If we
1767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // end up requiring support for a remote binder, we will need to
1777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // return mBinder as well, depending upon the intent.
1787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("binding service implementation");
1797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mLocalBinder;
1807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Broadcast the results from the query to all registered callback
1847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * objects.
1857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void broadcastQueryResults (AsyncResult ar) {
1877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // reset the state.
1887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (mCallbacks) {
1897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mState = QUERY_READY;
1907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // see if we need to do any work.
1927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (ar == null) {
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG) log("AsyncResult is null.");
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
1967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // TODO: we may need greater accuracy here, but for now, just a
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // simple status integer will suffice.
1997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int exception = (ar.exception == null) ? QUERY_OK : QUERY_EXCEPTION;
2007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG) log("AsyncResult has exception " + exception);
2017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Make the calls to all the registered callbacks.
2037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            for (int i = (mCallbacks.beginBroadcast() - 1); i >= 0; i--) {
2047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                INetworkQueryServiceCallback cb = mCallbacks.getBroadcastItem(i);
2057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG) log("broadcasting results to " + cb.getClass().toString());
2067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
2077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    cb.onQueryComplete((ArrayList<OperatorInfo>) ar.result, exception);
2087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (RemoteException e) {
2097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
2107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
2117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // finish up.
2137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mCallbacks.finishBroadcast();
2147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static void log(String msg) {
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, msg);
2197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
221