Android GPS 定位流程

Android P 代码:http://androidxref.com/9.0.0_r3/

上一篇幅我们梳理了位置开关打开的一个流程,这里我们梳理下请求Gps定位的一个流程

这里我们假设一个app发起Gps定位,首先调用 LocationManager 接口,通过AIDL最终调用到 LocationManagerService 里面的  requestLocationUpdates 方法:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/location/java/android/location/LocationManager.java#requestLocationUpdates

553    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
554    public void requestLocationUpdates(String provider, long minTime, float minDistance,
555            LocationListener listener) {
556        checkProvider(provider);
557        checkListener(listener);
558
559        LocationRequest request = LocationRequest.createFromDeprecatedProvider(  ---> 封装成LocationRequest,作为参数传下去
560                provider, minTime, minDistance, false);
561        requestLocationUpdates(request, listener, null, null);
562    }

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

2061    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2062            PendingIntent intent, String packageName) {
2063        if (request == null) request = DEFAULT_LOCATION_REQUEST;
2064        checkPackageName(packageName);
2065        int allowedResolutionLevel = getCallerAllowedResolutionLevel();   ---> 这里指的就是 fine、coarse、no location data 三种
2066        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2067                request.getProvider());
2068        WorkSource workSource = request.getWorkSource();
2069        if (workSource != null && !workSource.isEmpty()) {
2070            checkDeviceStatsAllowed();
2071        }
2072        boolean hideFromAppOps = request.getHideFromAppOps();
2073        if (hideFromAppOps) {
2074            checkUpdateAppOpsAllowed();
2075        }
2076        boolean callerHasLocationHardwarePermission =
2077                mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2078                        == PERMISSION_GRANTED;
2079        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2080                callerHasLocationHardwarePermission);
2081
2082        final int pid = Binder.getCallingPid();
2083        final int uid = Binder.getCallingUid();
2084        // providers may use public location API's, need to clear identity
2085        long identity = Binder.clearCallingIdentity();
2086        try {
2087            // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2088            // a location.
2089            checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2090
2091            synchronized (mLock) {
2092                Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
2093                        packageName, workSource, hideFromAppOps);
2094                requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);  ---> 继续看下这个
2095            }
2096        } finally {
2097            Binder.restoreCallingIdentity(identity);
2098        }
2099    }
2101    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2102            int pid, int uid, String packageName) {
2103        // Figure out the provider. Either its explicitly request (legacy use cases), or
2104        // use the fused provider
2105        if (request == null) request = DEFAULT_LOCATION_REQUEST;
2106        String name = request.getProvider();   ---> 获取此时的provide,下面就是根据这个provide决定走GPS还是走network,所以不能为空
2107        if (name == null) {
2108            throw new IllegalArgumentException("provider name must not be null");
2109        }
2110
2111        LocationProviderInterface provider = mProvidersByName.get(name);
2112        if (provider == null) {
2113            throw new IllegalArgumentException("provider doesn't exist: " + name);
2114        }
2115
2116        UpdateRecord record = new UpdateRecord(name, request, receiver);
2117        if (D) {
2118            Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2119                    + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2120                    + (record.mIsForegroundUid ? "foreground" : "background")
2121                    + (isThrottlingExemptLocked(receiver.mIdentity)
2122                    ? " [whitelisted]" : "") + ")");
2123        }   ---> 通过这个log就可以知道那个发起请求,请求的是gps还是network,是否是前台等
2124
2125        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2126        if (oldRecord != null) {
2127            oldRecord.disposeLocked(false);
2128        }
2129
2130        boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
2131        if (isProviderEnabled) {   ---> 允许才继续执行
2132            applyRequirementsLocked(name);
2133        } else {
2134            // Notify the listener that updates are currently disabled
2135            receiver.callProviderEnabledLocked(name, false);
2136        }
2137        // Update the monitoring here just in case multiple location requests were added to the
2138        // same receiver (this request may be high power and the initial might not have been).
2139        receiver.updateMonitoring(true);
2140    }
1732    private void applyRequirementsLocked(String provider) {
1733        LocationProviderInterface p = mProvidersByName.get(provider);
1734        if (p == null) return;   ---> 再次确认
1735
1736        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1737        WorkSource worksource = new WorkSource();
1738        ProviderRequest providerRequest = new ProviderRequest();
1739
1740        ContentResolver resolver = mContext.getContentResolver();
1741        long backgroundThrottleInterval = Settings.Global.getLong(  ---> 后台默认30min
1742                resolver,
1743                Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1744                DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1745        // initialize the low power mode to true and set to false if any of the records requires
1746
1747        providerRequest.lowPowerMode = true;
1748        if (records != null) {
1749            for (UpdateRecord record : records) {
1750                if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
1751                    if (checkLocationAccess(
1752                            record.mReceiver.mIdentity.mPid,
1753                            record.mReceiver.mIdentity.mUid,
1754                            record.mReceiver.mIdentity.mPackageName,
1755                            record.mReceiver.mAllowedResolutionLevel)) {
1756                        LocationRequest locationRequest = record.mRealRequest;
1757                        long interval = locationRequest.getInterval();
                           //系统和白名单的应用不受后台刷新时间的限制
1759                        if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
1760                            if (!record.mIsForegroundUid) {
1761                                interval = Math.max(interval, backgroundThrottleInterval);
1762                            }
1763                            if (interval != locationRequest.getInterval()) {
1764                                locationRequest = new LocationRequest(locationRequest);
1765                                locationRequest.setInterval(interval);
1766                            }
1767                        }
1768
1769                        record.mRequest = locationRequest;
1770                        providerRequest.locationRequests.add(locationRequest);
1771                        if (!locationRequest.isLowPowerMode()) {
1772                            providerRequest.lowPowerMode = false;
1773                        }
1774                        if (interval < providerRequest.interval) {
1775                            providerRequest.reportLocation = true;
1776                            providerRequest.interval = interval;
1777                        }
1778                    }
1779                }
1780            }
1781
1782            if (providerRequest.reportLocation) {
1783                // calculate who to blame for power
1784                // This is somewhat arbitrary. We pick a threshold interval
1785                // that is slightly higher that the minimum interval, and
1786                // spread the blame across all applications with a request
1787                // under that threshold.
1788                long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1789                for (UpdateRecord record : records) {
1790                    if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
1791                        LocationRequest locationRequest = record.mRequest;
1792
1793                        // Don't assign battery blame for update records whose
1794                        // client has no permission to receive location data.
1795                        if (!providerRequest.locationRequests.contains(locationRequest)) {
1796                            continue;
1797                        }
1798
1799                        if (locationRequest.getInterval() <= thresholdInterval) {
1800                            if (record.mReceiver.mWorkSource != null
1801                                    && isValidWorkSource(record.mReceiver.mWorkSource)) {
1802                                worksource.add(record.mReceiver.mWorkSource);
1803                            } else {
1804                                // Assign blame to caller if there's no WorkSource associated with
1805                                // the request or if it's invalid.
1806                                worksource.add(
1807                                        record.mReceiver.mIdentity.mUid,
1808                                        record.mReceiver.mIdentity.mPackageName);
1809                            }
1810                        }
1811                    }
1812                }
1813            }
1814        }
1815
1816        if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1817        p.setRequest(providerRequest, worksource);  ---> 这里就是调用对应的 provide 的,因为是请求Gps_provider
1818    }

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

1294    @Override
1295    public void setRequest(ProviderRequest request, WorkSource source) {
1296        sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
1297    }

handlemessage 处理这个消息: 

2298                case SET_REQUEST:
2299                    GpsRequest gpsRequest = (GpsRequest) msg.obj;
2300                    handleSetRequest(gpsRequest.request, gpsRequest.source);
2301                    break;
1299    private void handleSetRequest(ProviderRequest request, WorkSource source) {
1300        mProviderRequest = request;
1301        mWorkSource = source;
1302        updateRequirements();
1303    }
1305    // Called when the requirements for GPS may have changed
1306    private void updateRequirements() {
1307        if (mProviderRequest == null || mWorkSource == null) {
1308            return;
1309        }
1310
1311        boolean singleShot = false;
1312
1313        // see if the request is for a single update
1314        if (mProviderRequest.locationRequests != null
1315                && mProviderRequest.locationRequests.size() > 0) {
1316            // if any request has zero or more than one updates
1317            // requested, then this is not single-shot mode
1318            singleShot = true;
1319
1320            for (LocationRequest lr : mProviderRequest.locationRequests) {
1321                if (lr.getNumUpdates() != 1) {
1322                    singleShot = false;
1323                }
1324            }
1325        }
1326
1327        if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
1328        if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
1329            // update client uids
1330            updateClientUids(mWorkSource);
1331
1332            mFixInterval = (int) mProviderRequest.interval;
1333            mLowPowerMode = (boolean) mProviderRequest.lowPowerMode;
1334            // check for overflow
1335            if (mFixInterval != mProviderRequest.interval) {
1336                Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
1337                mFixInterval = Integer.MAX_VALUE;
1338            }
1339
1340            // apply request to GPS engine
1341            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {  ---> 这个能力表示Gps是否可以连续定位(周期性的更新位置)
1342                // change period and/or lowPowerMode
1343                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1344                        mFixInterval, 0, 0, mLowPowerMode)) { 
1345                    Log.e(TAG, "set_position_mode failed in updateRequirements");
1346                }
1347            } else if (!mStarted) {  ---> 之前没有启动过,现在启动
1348                // start GPS
1349                startNavigating(singleShot);
1350            } else {
1351                // GNSS Engine is already ON, but no GPS_CAPABILITY_SCHEDULING
1352                mAlarmManager.cancel(mTimeoutIntent);
1353                if (mFixInterval >= NO_FIX_TIMEOUT) {
1354                    // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1355                    // and our fix interval is not short
1356                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1357                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);                }
1358            }
1359        } else {
1360            updateClientUids(new WorkSource());
1361
1362            stopNavigating();
1363            mAlarmManager.cancel(mWakeupIntent);
1364            mAlarmManager.cancel(mTimeoutIntent);
1365        }
1366    }
1485    private void startNavigating(boolean singleShot) {
1486        if (!mStarted) {
1487            if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
1488            mTimeToFirstFix = 0;
1489            mLastFixTime = 0;
1490            mStarted = true;
1491            mSingleShot = singleShot;
1492            mPositionMode = GPS_POSITION_MODE_STANDALONE;
1493            // Notify about suppressed output, if speed limit was previously exceeded.
1494            // Elsewhere, we check again with every speed output reported.
1495            if (mItarSpeedLimitExceeded) {
1496                Log.i(TAG, "startNavigating with ITAR limit in place. Output limited  " +
1497                        "until slow enough speed reported.");
1498            }
1499
1500            boolean agpsEnabled =
1501                    (Settings.Global.getInt(mContext.getContentResolver(),
1502                            Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1503            mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
1504
1505            if (DEBUG) {
1506                String mode;
1507
1508                switch (mPositionMode) {   ---> GPS 几种工作模式
1509                    case GPS_POSITION_MODE_STANDALONE:
1510                        mode = "standalone";
1511                        break;
1512                    case GPS_POSITION_MODE_MS_ASSISTED:
1513                        mode = "MS_ASSISTED";
1514                        break;
1515                    case GPS_POSITION_MODE_MS_BASED:
1516                        mode = "MS_BASED";
1517                        break;
1518                    default:
1519                        mode = "unknown";
1520                        break;
1521                }
1522                Log.d(TAG, "setting position_mode to " + mode);
1523            }
1524            //这里最短时间一般就是1s上报GPS位置,如果低于1s,底层会去判断
1525            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1526            mLowPowerMode = (boolean) mProviderRequest.lowPowerMode;
1527            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1528                    interval, 0, 0, mLowPowerMode)) {
1529                mStarted = false;
1530                Log.e(TAG, "set_position_mode failed in startNavigating()");
1531                return;
1532            }
1533            if (!native_start()) {  ---> 通过JNI往底层
1534                mStarted = false;
1535                Log.e(TAG, "native_start failed in startNavigating()");
1536                return;
1537            }
1538
1539            // reset SV count to zero
1540            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
1541            mLocationExtras.reset();
1542            mFixRequestTime = SystemClock.elapsedRealtime();
1543            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1544                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1545                // and our fix interval is not short
1546http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp#native_start1546                if (mFixInterval >= NO_FIX_TIMEOUT) {
1547                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1548                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1549                }
1550            }
1551        }
1552    }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp#native_start

1416static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
1417    if (gnssHal != nullptr) {
1418        auto result = gnssHal->start(); ---> 因为涉及到各平台,代码无法展示,大家可以跟着流程看下Vendor仓库
1419        if (!result.isOk()) {
1420            return JNI_FALSE;
1421        } else {
1422            return result;
1423        }
1424    } else {
1425        return JNI_FALSE;
1426    }
1427}

文章同步来自微信公众号,更多内容关注公众号:蘑菇君先生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值