这篇来写关于Service的第二种启动方式bindService(),这种启动方式也是经常会用到的。简单来看看:
#MainActivity.java
private MyService bindService = null;
Intent intent = null;
intent = new Intent(BinderActicityA.this, MyService.class);
bindService(intent,conn,BIND_AUTO_CREATE);
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyService.MyBinder binder = (MyService.MyBinder) service;
bindService = binder.getService();
bindService.play();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
MyService.java
public class MyService extends Service {
private final IBinder binder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
public void play() {
System.out.println("通过Binder得到Service的引用来调用Service内部的方法");
}
@Override
public void onDestroy() {
// 当调用者退出(即使没有调用unbindService)或者主动停止服务时会调用
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
// 当调用者退出(即使没有调用unbindService)或者主动停止服务时会调用
System.out.println("调用者退出了");
return super.onUnbind(intent);
}
}
进入源码:
#ContextWrapper.java
Context mBase;
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
#Context
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
#ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
AMS
#ActivityManagerService.java
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
#ActiveService.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
...
ActivityRecord activity = null;
//token不为空, 代表着发起方具有activity上下文
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;//存在token, 却找不到activity为空,则直接返回
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
//根据发送端所在进程的SchedGroup来决定是否为前台service.
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
//根据用户传递进来Intent来检索相对应的服务
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
//查询到相应的Service
ServiceRecord s = res.record;
boolean permissionsReviewRequired = false;
// If permissions need a review before any of the app components can run,
// we schedule binding to the service but do not start its process, then
// we launch a review activity to which is passed a callback to invoke
// when done to start the bound service's process to completing the binding.
if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
s.packageName, s.userId)) {
permissionsReviewRequired = true;
// Show a permission review UI only for binding from a foreground app
if (!callerFg) {
Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
+ s.packageName + " requires a permissions review");
return 0;
}
final ServiceRecord serviceRecord = s;
final Intent serviceIntent = service;
RemoteCallback callback = new RemoteCallback(
new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
synchronized(mAm) {
final long identity = Binder.clearCallingIdentity();
try {
if (!mPendingServices.contains(serviceRecord)) {
return;
}
// If there is still a pending record, then the service
// binding request is still valid, so hook them up. We
// proceed only if the caller cleared the review requirement
// otherwise we unbind because the user didn't approve.
if (!mAm.getPackageManagerInternalLocked()
.isPermissionsReviewRequired(
serviceRecord.packageName,
serviceRecord.userId)) {
try {
bringUpServiceLocked(serviceRecord,
serviceIntent.getFlags(),
callerFg, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
} else {
unbindServiceLocked(connection);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
});
...
}
}
final long origId = Binder.clearCallingIdentity();
try {
取消服务的重启调度
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
+ s);
}
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
//创建对象ConnectionRecord,此处connection来自发起者
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);// clist是ServiceRecord.connections的成员变量
b.connections.add(c);//b是指AppBindRecord
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null) {
// This could have made the service more important.
//更新service所在进程的优先级
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
|| s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
+ " doRebind=" + b.intent.doRebind);
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
//Service已经正在运行,则调用InnerConnection的代理对象
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
// If this is the first app connected back to this binding,
// and the service had previously asked to be told when
// rebound, then do so.
//当第一个app连接到该binding, 且之前已被bind过, 则回调onRebind()方法
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
//回调onBind()方法
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMap(s.userId).ensureNotStartingBackground(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
分析:
通过retrieveServiceLocked(),根据用户传递进来Intent来检索相对应的服务。
通过retrieveAppBindingLocked().创建AppBindRecord对象记录着当前ServiceRecord, intent以及发起方的进程信息。
通过bringUpServiceLocked()拉起目标服务。
#ActiveService.java
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
ServiceRecord r = null;
userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
false, ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
ServiceMap smap = getServiceMap(userId);
final ComponentName comp = service.getComponent();
if (comp != null) {
//根据服务名查找相应的ServiceRecord
r = smap.mServicesByName.get(comp);
}
if (r == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
//根据Intent查找相应的ServiceRecord
r = smap.mServicesByIntent.get(filter);
}
if (r == null) {
try {
//通过PKMS来查询相应的service
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
service, resolvedType,
ActivityManagerService.STOCK_PM_FLAGS, userId);
ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
return null;
}
//获取组件名
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
if (userId > 0) {
//服务是否属于单例模式
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
sInfo.name, sInfo.flags)
&& mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
userId = 0;
smap = getServiceMap(0);
}
sInfo = new ServiceInfo(sInfo);
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
}
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
Intent.FilterComparison filter
= new Intent.FilterComparison(service.cloneFilter());
//创建Restarter对象
ServiceRestarter res = new ServiceRestarter();
...
//创建ServiceRecord对象
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
res.setService(r);
smap.mServicesByName.put(name, r);
smap.mServicesByIntent.put(filter, r);
//确保该组件不再位于pending队列
for (int i=mPendingServices.size()-1; i>=0; i--) {
ServiceRecord pr = mPendingServices.get(i);
if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
&& pr.name.equals(name)) {
mPendingServices.remove(i);
}
}
}
} catch (RemoteException ex) {
//运行在同一个进程,不会发生RemoteException
}
}
if (r != null) {
//各种权限检查,不满足条件则返回为null的service
if (mAm.checkComponentPermission(r.permission,
callingPid, callingUid, r.appInfo.uid, r.exported)
!= PackageManager.PERMISSION_GRANTED) {
//当exported=false则不允许启动
if (!r.exported) {
return new ServiceLookupResult(null, "not exported from uid "
+ r.appInfo.uid);
}
return new ServiceLookupResult(null, r.permission);
} else if (r.permission != null && callingPackage != null) {
final int opCode = AppOpsManager.permissionToOpCode(r.permission);
if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
return null;
}
}
//创建Service查询结果对象
return new ServiceLookupResult(r, null);
}
return null;
}
分析:根据服务名从ServiceMap.mServicesByName中查找相应的ServiceRecord,如果没有找到,则往下执行;根据Intent从ServiceMap.mServicesByIntent中查找相应的ServiceRecord,如果还是没有找到,则往下执行;通过PKMS来查询相应的ServiceInfo,如果仍然没有找到,则不再往下执行。
# ServiceRecord.java
public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord i = bindings.get(filter);
if (i == null) {
//创建连接ServiceRecord和filter的记录信息
i = new IntentBindRecord(this, filter);
bindings.put(filter, i);
}
//此处app是指调用方所在进程
AppBindRecord a = i.apps.get(app);
if (a != null) {
return a;
}
//创建ServiceRecord跟进程绑定的记录信息
a = new AppBindRecord(this, i, app);
i.apps.put(app, a);
return a;
}
AppBindRecord对象记录着当前ServiceRecord,intent以及发起方的进程信息。
#ActiveServices.java
private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) throws TransactionTooLargeException {
// 进程已存在的情况
if (r.app != null && r.app.thread != null) {
//调用service.onStartCommand()过程
sendServiceArgsLocked(r, execInFg, false);
return null;
}
....
//服务正在启动,设置package停止状态为false
AppGlobals.getPackageManager().setPackageStoppedState(
r.packageName, false, r.userId);
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
// 启动服务
realStartServiceLocked(r, app, execInFg);
return null;
}
//对于进程没有启动的情况
if (app == null) {
//启动service所要运行的进程,最终还是会调用到
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
...
return msg;
}
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
...
return null;
}
# ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {
...
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
//发送delay消息
bumpServiceExecutingLocked(r, execInFg, "create");
boolean created = false;
try {
...
mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//服务进入 onCreate()
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
mAm.appDiedLocked(app); //应用死亡处理
throw e;
} finally {
if (!created) {
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
if (newService) {
app.services.remove(r);
r.app = null;
}
//尝试重新启动服务
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
...
}
# ActiveServices.java
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
通过bindService方式启动的服务, 那么该serviceRecord的bindings则一定不会空.
# ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
//发送bind开始的消息
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//服务进入 onBind()
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
throw e;
} catch (RemoteException e) {
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
return false;
}
}
return true;
}
#ApplicationThreadProxy (客户端)
class ApplicationThreadProxy implements IApplicationThread {
private final IBinder mRemote;
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,
int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeInt(rebind ? 1 : 0);
data.writeInt(processState);
mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
}
#ApplicationThreadNative(远程服务端)
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
case SCHEDULE_BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
IBinder token = data.readStrongBinder();
Intent intent = Intent.CREATOR.createFromParcel(data);
boolean rebind = data.readInt() != 0;
int processState = data.readInt();
scheduleBindService(token, intent, rebind, processState);
return true;
}
}
}
#ApplicationThread.java
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
//---------关键-----
sendMessage(H.BIND_SERVICE, s);
}
#ActivityThread.java
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
if (!data.rebind) {
// 执行Service.onBind()回调方法
IBinder binder = s.onBind(data.intent);
//将onBind返回值传递回去
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (Exception e) {
...
}
}
}
#MyService.java
public abstract IBinder onBind(Intent intent);