Android T 的 location 代码都整到一起了,看上去有序些,但代码梳理起来感觉太细了,整体代码目录结构如下:
再看下之前介绍的Android P 上的目录:
这里我们还是按照先Gps定位,后网络的顺序梳理下流程。还是一样的套路,通过LocationManager提供的API接口往下梳理:
frameworks/base/location/java/android/location/LocationManager.java
继续看流程:/frameworks/base/services/core/java/com/android/server/location/LocationManagerService.java
public void registerLocationListener(String provider, LocationRequest request,
ILocationListener listener, String packageName, @Nullable String attributionTag, String listenerId) {
// packageName 请求者报名
// request 封装的请求参数
// provider 请求的哪个Provide
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, listenerId);
// check 权限是不是被授予
int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), identity.getPid());
LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, PERMISSION_COARSE);
// clients in the system process should have an attribution tag set
if (identity.getPid() == Process.myPid() && attributionTag == null) {
Log.w(TAG, "system location request with no attribution tag", new IllegalArgumentException());
}
request = validateLocationRequest(provider, request, identity);
// 检查该Provide是否存在,存在就调用registerLocationRequest
LocationProviderManager manager = getLocationProviderManager(provider);
Preconditions.checkArgument(manager != null, "provider \"" + provider + "\" does not exist");
manager.registerLocationRequest(request, identity, permissionLevel, listener);
}
继续看流程:frameworks/base/services/core/java/com/android/server/location/provider/LocationProviderManager.java
public void registerLocationRequest(LocationRequest request, CallerIdentity identity,
@PermissionLevel int permissionLevel, ILocationListener listener) {
//封装成 LocationListenerRegistration
LocationListenerRegistration registration = new LocationListenerRegistration(
request,
identity,
new LocationListenerTransport(listener),
permissionLevel);
synchronized (mLock) {
Preconditions.checkState(mState != STATE_STOPPED);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(listener.asBinder(), registration);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
protected final class LocationListenerRegistration extends LocationRegistration implements IBinder.DeathRecipient {
LocationListenerRegistration(LocationRequest request, CallerIdentity identity,
LocationListenerTransport transport, @PermissionLevel int permissionLevel) {
super(request, identity, transport, permissionLevel); ---> 父类的
}
protected abstract class LocationRegistration extends Registration implements
OnAlarmListener, ProviderEnabledListener {
protected <TTransport extends LocationTransport & ProviderTransport> LocationRegistration(
LocationRequest request, CallerIdentity identity, TTransport transport,
@PermissionLevel int permissionLevel) {
super(request, identity, transport, permissionLevel); ---> 父类的
mProviderTransport = transport;
mWakeLock = Objects.requireNonNull(mContext.getSystemService(PowerManager.class))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
mWakeLock.setReferenceCounted(true);
mWakeLock.setWorkSource(request.getWorkSource());
mWakeLockReleaser = new ExternalWakeLockReleaser(identity, mWakeLock);
}
protected abstract class Registration extends RemoteListenerRegistration<LocationRequest,
LocationTransport> {
protected Registration(LocationRequest request, CallerIdentity identity,
LocationTransport transport, @PermissionLevel int permissionLevel) {
super(Objects.requireNonNull(request), identity, transport); ---> 父类的
Preconditions.checkArgument(identity.getListenerId() != null);
Preconditions.checkArgument(permissionLevel > PERMISSION_NONE);
Preconditions.checkArgument(!request.getWorkSource().isEmpty());
mPermissionLevel = permissionLevel;
mProviderLocationRequest = request;
}
public abstract class RemoteListenerRegistration<TRequest, TListener> extends
RemovableListenerRegistration<TRequest, TListener> {
protected RemoteListenerRegistration(@Nullable TRequest request, CallerIdentity identity, TListener listener) {
super(chooseExecutor(identity), request, listener); ---> 父类的
mIdentity = Objects.requireNonNull(identity);
}
public abstract class RemovableListenerRegistration<TRequest, TListener> extends
RequestListenerRegistration<TRequest, TListener> {
protected RemovableListenerRegistration(Executor executor, @Nullable TRequest request,
TListener listener) {
super(executor, request, listener); ---> 父类的
}
public class RequestListenerRegistration<TRequest, TListener> extends
ListenerRegistration<TListener> {
protected RequestListenerRegistration(Executor executor, TRequest request,
TListener listener) {
super(executor, listener); ---> 父类的
mRequest = request;
}
public class ListenerRegistration<TListener> implements ListenerExecutor {
protected ListenerRegistration(Executor executor, TListener listener) {
mExecutor = Objects.requireNonNull(executor);
mActive = false;
mListener = Objects.requireNonNull(listener);
}
这里只是 new LocationListenerRegistration,结果牵扯出这么多,都看晕了,不知道为啥谷歌搞得这么多
然后在执行: putRegistration(listener.asBinder(), registration);
代码位置:frameworks/base/services/core/java/com/android/server/location/listeners/ListenerMultiplexer.java
protected final void putRegistration(@NonNull TKey key, @NonNull TRegistration registration) {
replaceRegistration(key, key, registration);
}
// 注意参数,oldKey和key是同一个key
protected final void replaceRegistration(@NonNull TKey oldKey, @NonNull TKey key,
@NonNull TRegistration registration) {
Objects.requireNonNull(oldKey);
Objects.requireNonNull(key);
Objects.requireNonNull(registration);
synchronized (mRegistrations) {
// adding listeners reentrantly is not supported
Preconditions.checkState(!mReentrancyGuard.isReentrant());
// new key may only have a prior registration if the oldKey is the same as the key
Preconditions.checkArgument(oldKey == key || !mRegistrations.containsKey(key));
// since adding a registration can invoke a variety of callbacks, we need to ensure
// those callbacks themselves do not re-enter, as this could lead to out-of-order
// callbacks. further, we buffer service updates since adding a registration may
// involve removing a prior registration. note that try-with-resources ordering is
// meaningful here as well. we want to close the reentrancy guard first, as this may
// generate additional service updates, then close the update service buffer.
try (UpdateServiceBuffer ignored1 = mUpdateServiceBuffer.acquire();
ReentrancyGuard ignored2 = mReentrancyGuard.acquire()) {
boolean wasEmpty = mRegistrations.isEmpty();
TRegistration oldRegistration = null;
int index = mRegistrations.indexOfKey(oldKey); ---> 第一次里面找不到
if (index >= 0) {
oldRegistration = removeRegistration(index, oldKey != key);
}
if (oldKey == key && index >= 0) {
mRegistrations.setValueAt(index, registration);
} else {
mRegistrations.put(key, registration); ---> ArrayMap<TKey, TRegistration> mRegistrations = new ArrayMap<>()
}
if (wasEmpty) { ---> 上面判断了,第一次肯定是空的
onRegister(); ---> 这个又调回 LocationProviderManager#onRegister()方法
}
registration.onRegister(key);
if (oldRegistration == null) {
onRegistrationAdded(key, registration);
} else {
onRegistrationReplaced(key, oldRegistration, registration);
}
onRegistrationActiveChanged(registration);
}
}
}
// LocationProviderManager#onRegister()方法,注册这些listen
protected void onRegister() {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mLock));
}
mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(mBackgroundThrottleIntervalChangedListener);
mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(mBackgroundThrottlePackageWhitelistChangedListener);
mSettingsHelper.addOnLocationPackageBlacklistChangedListener(mLocationPackageBlacklistChangedListener);
mSettingsHelper.addAdasAllowlistChangedListener(mAdasPackageAllowlistChangedListener);
mSettingsHelper.addIgnoreSettingsAllowlistChangedListener(mIgnoreSettingsPackageWhitelistChangedListener);
mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
mAppForegroundHelper.addListener(mAppForegroundChangedListener);
mLocationPowerSaveModeHelper.addListener(mLocationPowerSaveModeChangedListener);
mScreenInteractiveHelper.addListener(mScreenInteractiveChangedListener);
}
再继续会看剩下的逻辑 registration.onRegister(key) 又是调用哪个?
调用的是 RemovableListenerRegistration#onRegister(Object key) —> LocationProviderManager#onRemovableListenerRegister()
看下代码:frameworks/base/services/core/java/com/android/server/location/provider/LocationProviderManager.java
protected final void onRemovableListenerRegister() {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mLock));
}
// name 指的是 Provide
// getIdentity 指的是 PID 包名之类的
// getRequest 就是request封装的一些参数
Log.d(TAG, mName + " provider added registration from " + getIdentity() + " -> " + getRequest());
EVENT_LOG.logProviderClientRegistered(mName, getIdentity(), super.getRequest());
// initialization order is important as there are ordering dependencies
mPermitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel, getIdentity());
mForeground = mAppForegroundHelper.isAppForeground(getIdentity().getUid());
mProviderLocationRequest = calculateProviderLocationRequest();
mIsUsingHighPower = isUsingHighPower();
onProviderListenerRegister();
if (mForeground) {
EVENT_LOG.logProviderClientForeground(mName, getIdentity());
}
}
// 再看下 onProviderListenerRegister 方法:
protected final void onProviderListenerRegister() {
long registerTimeMs = SystemClock.elapsedRealtime();
mExpirationRealtimeMs = getRequest().getExpirationRealtimeMs(registerTimeMs);
// add alarm for expiration
if (mExpirationRealtimeMs <= registerTimeMs) {
onAlarm();
} else if (mExpirationRealtimeMs < Long.MAX_VALUE) {
// Set WorkSource to null in order to ensure the alarm wakes up the device even when
// it is idle. Do this when the cost of waking up the device is less than the power
// cost of not performing the actions set off by the alarm, such as unregistering a
// location request.
mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this, null);
}
// start listening for provider enabled/disabled events
addEnabledListener(this);
onLocationListenerRegister();
// if the provider is currently disabled, let the client know immediately
int userId = getIdentity().getUserId(); ---> 多用户,一般是0
if (!isEnabled(userId)) {
onProviderEnabledChanged(mName, userId, false);
}
}
// 如果Provide没有使能就调用 deliverOnProviderEnabledChanged 通知注册的listen
public void onProviderEnabledChanged(String provider, int userId, boolean enabled) {
Preconditions.checkState(mName.equals(provider));
if (userId != getIdentity().getUserId()) {
return;
}
// we choose not to hold a wakelock for provider enabled changed events
executeSafely(getExecutor(), () -> mProviderTransport,
listener -> listener.deliverOnProviderEnabledChanged(mName, enabled),
this::onProviderOperationFailure);
}
registration.onRegister(key) 看完了,再继续往下看,再回到上面那个图,很明显首次oldRegistration是null,所以就执行: onRegistrationAdded(key, registration),就跳到去执行: LocationProviderManager#onRegistrationAdded(具体的可以看下代码,就是把这些记录到statsd中,statsd是后台运行的原生服务,用于收集指标这些)
OK,再往下看,接着就执行: onRegistrationActiveChanged(registration);
private void onRegistrationActiveChanged(TRegistration registration) {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mRegistrations));
}
// 这两个判断条件很重要,前者是是否注册,后者是否活跃
boolean active = registration.isRegistered() && isActive(registration); ---> 看下面的isActive() 方法
boolean changed = registration.setActive(active);
// 如果changed 为false,结束
if (changed) {
if (active) {
if (++mActiveRegistrationsCount == 1) {
onActive(); ---> 下面也贴了这个方法
}
registration.onActive();
} else {
registration.onInactive();
if (--mActiveRegistrationsCount == 0) {
onInactive();
}
}
updateService();
}
}
// registration.setActive(active) 方法:
final boolean setActive(boolean active) {
if (active != mActive) {
mActive = active;
return true;
}
return false;
}
// 看下 isActive() 方法实现:
protected boolean isActive(Registration registration) {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mLock));
}
if (!registration.isPermitted()) {
return false;
}
boolean isBypass = registration.getRequest().isBypass(); ---> 这个可以理解为不受限位置的应用或者服务
if (!isActive(isBypass, registration.getIdentity())) { ---> 根据这两个参数来判断是不是Active,看下面的分析
return false;
}
// 也就是说想走到下面,必须满足isBypass为false
if (!isBypass) {
switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) {
case LOCATION_MODE_FOREGROUND_ONLY:
if (!registration.isForeground()) {
return false;
}
break;
case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
if (!GPS_PROVIDER.equals(mName)) {
break;
}
// fall through
case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
// fall through
case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
if (!mScreenInteractiveHelper.isInteractive()) {
return false;
}
break;
case LOCATION_MODE_NO_CHANGE:
// fall through
default:
break;
}
}
return true;
}
// isActive(isBypass, registration.getIdentity()) 两个参数的方法:
/* 几种情况:
1. 系统应用,是isBypass的,返回ture
2. 系统应用,是isBypass的,且Provider已经使能,返回ture
3. 非系统应用,是isBypass的,然后不在黑名单里面,返回ture
*/
private boolean isActive(boolean isBypass, CallerIdentity identity) {
if (identity.isSystemServer()) {
if (!isBypass) {
if (!isEnabled(mUserHelper.getCurrentUserId())) {
return false;
}
}
} else {
if (!isBypass) {
if (!isEnabled(identity.getUserId())) {
return false;
}
if (!mUserHelper.isCurrentUserId(identity.getUserId())) {
return false;
}
}
if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
identity.getPackageName())) {
return false;
}
}
return true;
}
// onActive() 方法:
protected final void onActive() {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mLock));
}
EVENT_LOG.logProviderClientActive(mName, getIdentity());
if (!getRequest().isHiddenFromAppOps()) {
mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, getIdentity());
}
onHighPowerUsageChanged();
onProviderListenerActive();
}
protected final void onProviderListenerActive() {
// a new registration may not get a location immediately, the provider request may be
// delayed. therefore we deliver a historical location if available. since delivering an
// older location could be considered a breaking change for some applications, we only
// do so for apps targeting S+.
if (isChangeEnabled(DELIVER_HISTORICAL_LOCATIONS, getIdentity().getUid())) {
long maxLocationAgeMs = getRequest().getIntervalMillis();
Location lastDeliveredLocation = getLastDeliveredLocation();
if (lastDeliveredLocation != null) {
// ensure that location is fresher than the last delivered location
maxLocationAgeMs = min(maxLocationAgeMs,
lastDeliveredLocation.getElapsedRealtimeAgeMillis() - 1);
}
// requests are never delayed less than MIN_REQUEST_DELAY_MS, so it only makes sense
// to deliver historical locations to clients with a last location older than that
if (maxLocationAgeMs > MIN_REQUEST_DELAY_MS) {
Location lastLocation = getLastLocationUnsafe(
getIdentity().getUserId(),
getPermissionLevel(),
getRequest().isBypass(),
maxLocationAgeMs);
if (lastLocation != null) { ---> 现在没有任何位置信息是不会走这里
executeOperation(acceptLocationChange(LocationResult.wrap(lastLocation)));
}
}
}
}
OK,首先我没能理解这个 ++mActiveRegistrationsCount == 1,这个条件满足执行onActive()方法,虽然上面也看了这个代码。为了流程先跳过吧,这里吐槽一句,Android T 的location代码谷歌写的真是……
接着再看:updateService()
protected final void updateService() {
synchronized (mRegistrations) {
if (mUpdateServiceBuffer.isBuffered()) {
mUpdateServiceBuffer.markUpdateServiceRequired();
return;
}
// 这个其实就是把现在的 Registrations 遍历一遍,判断是否是isActive
ArrayList<TRegistration> actives = new ArrayList<>(mRegistrations.size());
final int size = mRegistrations.size();
for (int i = 0; i < size; i++) {
TRegistration registration = mRegistrations.valueAt(i);
if (registration.isActive()) { ---> 之前流程是 setActive 过的
actives.add(registration);
}
}
if (actives.isEmpty()) {
if (mServiceRegistered) {
mMerged = null;
mServiceRegistered = false;
unregisterWithService();
}
return;
}
TMergedRegistration merged = mergeRegistrations(actives); ---> 下面看下这个方法
if (!mServiceRegistered || !Objects.equals(merged, mMerged)) {
if (mServiceRegistered) {
mServiceRegistered = reregisterWithService(mMerged, merged, actives);
} else {
mServiceRegistered = registerWithService(merged, actives); ---> 首次,看这个
}
mMerged = mServiceRegistered ? merged : null;
}
}
}
// mergeRegistrations(actives),通过合并多个注册并计算功耗归因责任,生成一个合并后的提供者请求对象,该请求包含了合并注册的相关参数信息
protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mLock));
}
long intervalMs = ProviderRequest.INTERVAL_DISABLED;
int quality = LocationRequest.QUALITY_LOW_POWER;
long maxUpdateDelayMs = Long.MAX_VALUE;
boolean adasGnssBypass = false;
boolean locationSettingsIgnored = false;
boolean lowPower = true;
for (Registration registration : registrations) {
LocationRequest request = registration.getRequest();
// passive requests do not contribute to the provider request, and passive requests
// must handle the batching parameters of non-passive requests
if (request.getIntervalMillis() == LocationRequest.PASSIVE_INTERVAL) {
continue;
}
intervalMs = min(request.getIntervalMillis(), intervalMs);
quality = min(request.getQuality(), quality);
maxUpdateDelayMs = min(request.getMaxUpdateDelayMillis(), maxUpdateDelayMs);
adasGnssBypass |= request.isAdasGnssBypass();
locationSettingsIgnored |= request.isLocationSettingsIgnored();
lowPower &= request.isLowPower();
}
if (intervalMs == ProviderRequest.INTERVAL_DISABLED) {
return ProviderRequest.EMPTY_REQUEST;
}
if (maxUpdateDelayMs / 2 < intervalMs) {
// reduces churn if only the batching parameter has changed
maxUpdateDelayMs = 0;
}
// calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold
// interval slightly higher that the minimum interval, and spread the blame across all
// contributing registrations under that threshold (since worksource does not allow us to
// represent differing power blame ratios).
long thresholdIntervalMs;
try {
thresholdIntervalMs = Math.multiplyExact(Math.addExact(intervalMs, 1000) / 2, 3);
} catch (ArithmeticException e) {
// check for and handle overflow by setting to one below the passive interval so passive
// requests are automatically skipped
thresholdIntervalMs = LocationRequest.PASSIVE_INTERVAL - 1;
}
WorkSource workSource = new WorkSource();
for (Registration registration : registrations) {
if (registration.getRequest().getIntervalMillis() <= thresholdIntervalMs) {
workSource.add(registration.getRequest().getWorkSource());
}
}
return new ProviderRequest.Builder()
.setIntervalMillis(intervalMs)
.setQuality(quality)
.setMaxUpdateDelayMillis(maxUpdateDelayMs)
.setAdasGnssBypass(adasGnssBypass)
.setLocationSettingsIgnored(locationSettingsIgnored)
.setLowPower(lowPower)
.setWorkSource(workSource)
.build();
}
// registerWithService(merged, actives) [参数: TMergedRegistration merged 和 ArrayList<TRegistration> actives]
protected boolean registerWithService(ProviderRequest request, Collection<Registration> registrations) {
return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations);
}
@GuardedBy("mLock")
@Override
protected boolean reregisterWithService(ProviderRequest oldRequest,
ProviderRequest newRequest, Collection<Registration> registrations) {
if (Build.IS_DEBUGGABLE) {
Preconditions.checkState(Thread.holdsLock(mLock));
}
// calculate how long the new request should be delayed before sending it off to the
// provider, under the assumption that once we send the request off, the provider will
// immediately attempt to deliver a new location satisfying that request.
long delayMs;
if (!oldRequest.isBypass() && newRequest.isBypass()) {
delayMs = 0;
} else if (newRequest.getIntervalMillis() > oldRequest.getIntervalMillis()) {
// if the interval has increased, tell the provider immediately, so it can save power
// (even though technically this could burn extra power in the short term by producing
// an extra location - the provider itself is free to detect an increasing interval and
// delay its own location)
delayMs = 0;
} else {
delayMs = calculateRequestDelayMillis(newRequest.getIntervalMillis(), registrations);
}
// the delay should never exceed the new interval
Preconditions.checkState(delayMs >= 0 && delayMs <= newRequest.getIntervalMillis());
if (delayMs < MIN_REQUEST_DELAY_MS) {
setProviderRequest(newRequest); ---> 到了这里是不是就是我们比较熟悉的流程了
} else {
if (D) {
Log.d(TAG, mName + " provider delaying request update " + newRequest + " by "
+ TimeUtils.formatDuration(delayMs));
}
if (mDelayedRegister != null) {
mAlarmHelper.cancel(mDelayedRegister);
mDelayedRegister = null;
}
mDelayedRegister = new OnAlarmListener() {
@Override
public void onAlarm() {
synchronized (mLock) {
if (mDelayedRegister == this) {
mDelayedRegister = null;
setProviderRequest(newRequest);
}
}
}
};
// Set WorkSource to null in order to ensure the alarm wakes up the device even when it
// is idle. Do this when the cost of waking up the device is less than the power cost of
// not performing the actions set off by the alarm, such as unregistering a location
// request.
mAlarmHelper.setDelayedAlarm(delayMs, mDelayedRegister, null);
}
return true;
}
setProviderRequest(newRequest) 继续看这个,比较熟悉的流程看下
void setProviderRequest(ProviderRequest request) {
if (mDelayedRegister != null) {
mAlarmHelper.cancel(mDelayedRegister);
mDelayedRegister = null;
}
EVENT_LOG.logProviderUpdateRequest(mName, request);
mProvider.getController().setRequest(request); ---> 这个就是各个调用到 Provide
FgThread.getHandler().post(() -> {
for (IProviderRequestListener listener : mProviderRequestListeners) {
try {
listener.onProviderRequestChanged(mName, request);
} catch (RemoteException e) {
mProviderRequestListeners.remove(listener);
}
}
});
}
至此,Android 13 的GPS定位发起大致梳理完毕,下一篇有时间继续。只想吐槽一句,搞得真繁琐,调用流程……