GPS服务

功能概述

    GPS的服务是由LocationManagerService实现,它主要用来获取底层传来的GPS数据,
并传递给上层应用;同时接收管理层的控制指令,向下层传递。需要注意的是该类实现了Runnable接口,
因此它会作为一个线程运行。

权限声明

LocationManagerService

public class LocationManagerService extends ILocationManager.Stub implements Runnable {
    ......
    private static final String ACCESS_FINE_LOCATION =
        android.Manifest.permission.ACCESS_FINE_LOCATION;
    private static final String ACCESS_COARSE_LOCATION =
        android.Manifest.permission.ACCESS_COARSE_LOCATION;
    private static final String ACCESS_MOCK_LOCATION =
        android.Manifest.permission.ACCESS_MOCK_LOCATION;
    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
        android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
    private static final String INSTALL_LOCATION_PROVIDER =
        android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
    ......
}

服务线程的运行

run

public void run() {
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    Looper.prepare();
    mLocationHandler = new LocationWorkerHandler();
    initialize();
    Looper.loop();
}

initialize

private void initialize() {
    // 首先获取Wake lock
    PowerManager powerManager = 
        (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);

    // 加载所有Provider
    loadProviders();

    // 注册wifi或mobile的连接通知
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    // 注册package的变化通知
    intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
    intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
    mContext.registerReceiver(mBroadcastReceiver, intentFilter);
    IntentFilter sdFilter = 
        new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
    mContext.registerReceiver(mBroadcastReceiver, sdFilter);

    // 监控settings的设置变化
    ......
    SettingsObserver settingsObserver = new SettingsObserver();
    mSettings.addObserver(settingsObserver);
}

_loadProvidersLocked

private void _loadProvidersLocked() {
    // 加载真实的具有定位功能的Provider
    if (GpsLocationProvider.isSupported()) {
        // Create a gps location provider
        GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
        mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
        mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
        addProvider(gpsProvider);
        mGpsLocationProvider = gpsProvider;
    }

    // 加载虚拟的Provider
    PassiveProvider passiveProvider = new PassiveProvider(this);
    addProvider(passiveProvider);
    mEnabledProviders.add(passiveProvider.getName());

    // 加载具有网络定位功能的Provider
    if (mNetworkLocationProviderPackageName != null) {
        mNetworkLocationProvider =
            new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
                    mNetworkLocationProviderPackageName, mLocationHandler);
        addProvider(mNetworkLocationProvider);
    }

    // 加载具有地址信息和经纬度转换功能的Provider
    if (mGeocodeProviderPackageName != null) {
        mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName);
    }

    // 更新Provider状态
    updateProvidersLocked();
}

封装定位信息的回调

UpdateRecord

private class UpdateRecord {
    ......
    UpdateRecord(String provider, long minTime, 
                 float minDistance, boolean singleShot,
                 Receiver receiver, int uid) {
        mProvider = provider;
        mReceiver = receiver;
        ......

        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
        if (records == null) {
            records = new ArrayList<UpdateRecord>();
            mRecordsByProvider.put(provider, records);
        }
        if (!records.contains(this)) {
            records.add(this);
        }
    }

    ......
}

Receiver

private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
    final ILocationListener mListener;
    final PendingIntent mPendingIntent;
    ......
    Receiver(ILocationListener listener) {
        mListener = listener;
        mPendingIntent = null;
        mKey = listener.asBinder();
    }

    Receiver(PendingIntent intent) {
        mPendingIntent = intent;
        mListener = null;
        mKey = intent;
    }
    ......
}

注册状态信息的回调

public boolean addGpsStatusListener(IGpsStatusListener listener) {
    ...... 
    if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
            PackageManager.PERMISSION_GRANTED) {
        throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
    }

    try {
        mGpsStatusProvider.addGpsStatusListener(listener);
    } catch (RemoteException e) {
        return false;
    }
    return true;
}

发送定位请求

requestLocationUpdates

public void requestLocationUpdates(String provider, Criteria criteria,
                                    long minTime, float minDistance, 
                                    boolean singleShot, ILocationListener listener) {
    ...... 
    try {
        synchronized (mLock) {
            // 将回调接口封装成Receiver对象
            requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot,
                    getReceiver(listener));
        }
    } 
    ...... 
}

requestLocationUpdatesLocked

private void requestLocationUpdatesLocked(String provider, long minTime, float minDistance,
        boolean singleShot, Receiver receiver) {

    LocationProviderInterface p = mProvidersByName.get(provider);
    ......
    // 验证是否具有权限
    checkPermissionsSafe(provider);
    ......
    try {
        // 保存回调对象
        UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, singleShot,
                receiver, callingUid);
        UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
        ......

        boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
        if (isProviderEnabled) {
            long minTimeForProvider = getMinTimeLocked(provider);
            p.setMinTime(minTimeForProvider, mTmpWorkSource);
            // 开启Provider导航
            if (!singleShot || !p.requestSingleShotFix()) {
                p.enableLocationTracking(true);
            }
        } else {
            // 更新回调的状态
            receiver.callProviderEnabledLocked(provider, false);
        }
    } finally {
        Binder.restoreCallingIdentity(identity);
    }
}

checkPermissionsSafe

private void checkPermissionsSafe(String provider) {
    if ((LocationManager.GPS_PROVIDER.equals(provider)
             || LocationManager.PASSIVE_PROVIDER.equals(provider))
        && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED)) {
        throw new SecurityException("Provider " + provider
                + " requires ACCESS_FINE_LOCATION permission");
    }
    if (LocationManager.NETWORK_PROVIDER.equals(provider)
        && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED)
        && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED)) {
        throw new SecurityException("Provider " + provider
                + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
    }
}

获取定位信息

reportLocation

public void reportLocation(Location location, boolean passive) {
    if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
            != PackageManager.PERMISSION_GRANTED) {
        throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
    }

    mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
    Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
    m.arg1 = (passive ? 1 : 0);
    mLocationHandler.sendMessageAtFrontOfQueue(m);
}

handleLocationChangedLocked

private void handleLocationChangedLocked(Location location, boolean passive) {
    String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
    ...... 
    LocationProviderInterface p = mProvidersByName.get(provider);
    ...... 

    // 通知并处理所有回调
    final int N = records.size();
    for (int i=0; i<N; i++) {
        ......
        if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
            if (lastLoc == null) {
                lastLoc = new Location(location);
                r.mLastFixBroadcast = lastLoc;
            } else {
                lastLoc.set(location);
            }
            if (!receiver.callLocationChangedLocked(location)) {
                receiverDead = true;
            }
        }

        long prevStatusUpdateTime = r.mLastStatusBroadcast;
        if ((newStatusUpdateTime > prevStatusUpdateTime) &&
            (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {

            r.mLastStatusBroadcast = newStatusUpdateTime;
            if (!receiver.callStatusChangedLocked(provider, status, extras)) {
                receiverDead = true;
            }
        }
        ...... 
    }
    ...... 
}

callLocationChangedLocked

public boolean callLocationChangedLocked(Location location) {
    if (mListener != null) {
        try {
            synchronized (this) {
                // 调用回调处理
                mListener.onLocationChanged(location);
                if (mListener != mProximityListener) {
                    // 增加引用计数
                    incrementPendingBroadcastsLocked();
                }
            }
        } catch (RemoteException e) {
            return false;
        }
    } else {
        Intent locationChanged = new Intent();
        locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
        try {
            synchronized (this) {
                // 使用PendingIntent处理回调
                mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
                // 增加引用计数
                incrementPendingBroadcastsLocked();
            }
        } catch (PendingIntent.CanceledException e) {
            return false;
        }
    }
    return true;
}

内部消息处理

LocationWorkerHandler

private class LocationWorkerHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        try {
            if (msg.what == MESSAGE_LOCATION_CHANGED) {
                synchronized (mLock) {
                    ......
                    if (!passive) {
                        // 通知其他的Provider更新位置
                        for (int i = mProviders.size() - 1; i >= 0; i--) {
                            LocationProviderInterface p = mProviders.get(i);
                            if (!provider.equals(p.getName())) {
                                p.updateLocation(location);
                            }
                        }
                    }

                    // 处理位置更新
                    if (isAllowedBySettingsLocked(provider)) {
                        handleLocationChangedLocked(location, passive);
                    }
                }
            } else if (msg.what == MESSAGE_PACKAGE_UPDATED) {
                ......
                if (mNetworkLocationProvider != null &&
                    mNetworkLocationProviderPackageName.startsWith(packageDot)) {
                    mNetworkLocationProvider.reconnect();
                }
                if (mGeocodeProvider != null &&
                    mGeocodeProviderPackageName.startsWith(packageDot)) {
                    mGeocodeProvider.reconnect();
                }
            }
        } catch (Exception e) {
        }
    }
}

向Provider发送命令

命令格式

command 描述 备注
delete_aiding_data 删除GPS数据,可根据参数选择删除的类型  
force_time_injection 强制时间同步  
force_xtra_injection 强制数据同步  

sendExtraCommand

public boolean sendExtraCommand(String provider, String command, Bundle extras) {
    ......
    checkPermissionsSafe(provider);
    ...... 
    synchronized (mLock) {
        LocationProviderInterface p = mProvidersByName.get(provider);
        if (p == null) {
            return false;
        }

        return p.sendExtraCommand(command, extras);
    }
}