Android P 代码:http://androidxref.com/9.0.0_r3/
上一篇幅我们梳理了位置开关打开的一个流程,这里我们梳理下请求Gps定位的一个流程
这里我们假设一个app发起Gps定位,首先调用 LocationManager 接口,通过AIDL最终调用到 LocationManagerService 里面的 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 }
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 }
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 }
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}
文章同步来自微信公众号,更多内容关注公众号:蘑菇君先生