下面列出了android.content.Context#BIND_AUTO_CREATE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void connectToTelecom() {
synchronized (mLock) {
if (mServiceConnection != null) {
// TODO: Is unbinding worth doing or wait for system to rebind?
mContext.unbindService(mServiceConnection);
mServiceConnection = null;
}
TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
Intent intent = new Intent(SERVICE_ACTION);
intent.setComponent(SERVICE_COMPONENT);
int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_AUTO_CREATE;
// Bind to Telecom and register the service
if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
mServiceConnection = serviceConnection;
}
}
}
public String toString() {
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("IntentBindRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
sb.append("CR ");
}
sb.append(service.shortName);
sb.append(':');
if (intent != null) {
intent.getIntent().toShortString(sb, false, false, false, false);
}
sb.append('}');
return stringName = sb.toString();
}
@Override
public String toString() {
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("IntentBindRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
if ((collectFlags() & Context.BIND_AUTO_CREATE) != 0) {
sb.append("CR ");
}
sb.append(service.shortName);
sb.append(':');
if (intent != null) {
sb.append(intent.getIntent().toString());
}
// 添加Process记录信息
sb.append(':');
if (apps.size() > 0) {
sb.append(apps.toString());
}
sb.append('}');
stringName = sb.toString();
return stringName;
}
private void bindService(boolean hasMediaStorePermission) {
long timeSinceLastStartRequest = SystemClock.uptimeMillis() - mServiceStartRequestTime;
if (!hasMediaStorePermission || mBinding != null
|| timeSinceLastStartRequest < SERVICE_RESTART_THRESHOLD_MS) {
return;
}
initAllPropertyFallbacks();
mServiceStartRequestTime = SystemClock.uptimeMillis();
Timber.i("Starting service at time %dl", mServiceStartRequestTime);
Intent serviceIntent = PlayerService.newIntent(mContext, true);
int bindFlags = Context.BIND_WAIVE_PRIORITY | Context.BIND_AUTO_CREATE;
mContext.bindService(serviceIntent, mConnection, bindFlags);
mContext.startService(serviceIntent);
}
ChildProcessConnection(Context context, int number, boolean inSandbox,
ChildProcessConnection.DeathCallback deathCallback,
Class<? extends ChildProcessService> serviceClass,
LinkerParams linkerParams) {
mContext = context;
mServiceNumber = number;
mInSandbox = inSandbox;
mDeathCallback = deathCallback;
mServiceClass = serviceClass;
mLinkerParams = linkerParams;
mInitialBinding = new ChildServiceConnection(Context.BIND_AUTO_CREATE);
mStrongBinding = new ChildServiceConnection(
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
mWaivedBinding = new ChildServiceConnection(
Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
}
ChildProcessConnection(Context context, int number, boolean inSandbox,
ChildProcessConnection.DeathCallback deathCallback,
Class<? extends ChildProcessService> serviceClass,
LinkerParams linkerParams) {
mContext = context;
mServiceNumber = number;
mInSandbox = inSandbox;
mDeathCallback = deathCallback;
mServiceClass = serviceClass;
mLinkerParams = linkerParams;
mInitialBinding = new ChildServiceConnection(Context.BIND_AUTO_CREATE);
mStrongBinding = new ChildServiceConnection(
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
mWaivedBinding = new ChildServiceConnection(
Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
}
public boolean hasAutoCreateConnections() {
// XXX should probably keep a count of the number of auto-create
// connections directly in the service.
for (int conni=connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
for (int i=0; i<cr.size(); i++) {
if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
return true;
}
}
}
return false;
}
public boolean hasAutoCreateConnections() {
// XXX should probably keep a count of the number of auto-create
// connections directly in the service.
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionBindRecord> cr = connections.valueAt(conni);
for (int i = 0; i < cr.size(); i++) {
if ((cr.get(i).flags & Context.BIND_AUTO_CREATE) != 0) {
return true;
}
}
}
return false;
}
@SuppressLint("InlinedApi")
public void bind() {
Log.d(TAG, "Connection(" + actionString + ") : bind()");
Intent intent = new Intent(actionString).setPackage(GMS_PACKAGE_NAME);
int flags = Context.BIND_AUTO_CREATE;
if (SDK_INT >= ICE_CREAM_SANDWICH) {
flags |= Context.BIND_ADJUST_WITH_ACTIVITY;
}
bound = context.bindService(intent, serviceConnection, flags);
if (!bound) {
context.unbindService(serviceConnection);
}
}
@WorkerThread
private IInstantAppResolver bind(String token)
throws ConnectionException, TimeoutException, InterruptedException {
boolean doUnbind = false;
synchronized (mLock) {
if (mRemoteInstance != null) {
return mRemoteInstance;
}
if (mBindState == STATE_PENDING) {
// there is a pending bind, let's see if we can use it.
if (DEBUG_INSTANT) {
Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection");
}
try {
waitForBindLocked(token);
if (mRemoteInstance != null) {
return mRemoteInstance;
}
} catch (TimeoutException e) {
// nope, we might have to try a rebind.
doUnbind = true;
}
}
if (mBindState == STATE_BINDING) {
// someone was binding when we called bind(), or they raced ahead while we were
// waiting in the PENDING case; wait for their result instead. Last chance!
if (DEBUG_INSTANT) {
Slog.i(TAG, "[" + token + "] Another thread is binding; waiting for connection");
}
waitForBindLocked(token);
// if the other thread's bindService() returned false, we could still have null.
if (mRemoteInstance != null) {
return mRemoteInstance;
}
throw new ConnectionException(ConnectionException.FAILURE_BIND);
}
mBindState = STATE_BINDING; // our time to shine! :)
}
// only one thread can be here at a time (the one that set STATE_BINDING)
boolean wasBound = false;
IInstantAppResolver instance = null;
try {
if (doUnbind) {
if (DEBUG_INSTANT) {
Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding");
}
mContext.unbindService(mServiceConnection);
}
if (DEBUG_INSTANT) {
Slog.v(TAG, "[" + token + "] Binding to instant app resolver");
}
final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
wasBound = mContext
.bindServiceAsUser(mIntent, mServiceConnection, flags, UserHandle.SYSTEM);
if (wasBound) {
synchronized (mLock) {
waitForBindLocked(token);
instance = mRemoteInstance;
return instance;
}
} else {
Slog.w(TAG, "[" + token + "] Failed to bind to: " + mIntent);
throw new ConnectionException(ConnectionException.FAILURE_BIND);
}
} finally {
synchronized (mLock) {
if (wasBound && instance == null) {
mBindState = STATE_PENDING;
} else {
mBindState = STATE_IDLE;
}
mLock.notifyAll();
}
}
}
void removeConnectionLocked(
ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
IBinder binder = c.conn.asBinder();
AppBindRecord b = c.binding;
ServiceRecord s = b.service;
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
s.connections.remove(binder);
}
}
b.connections.remove(c);
if (c.activity != null && c.activity != skipAct) {
if (c.activity.connections != null) {
c.activity.connections.remove(c);
}
}
if (b.client != skipApp) {
b.client.connections.remove(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.updateHasAboveClientLocked();
}
// If this connection requested whitelist management, see if we should
// now clear that state.
if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.updateWhitelistManager();
if (!s.whitelistManager && s.app != null) {
updateWhitelistManagerLocked(s.app);
}
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
}
clist = mServiceConnections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
mServiceConnections.remove(binder);
}
}
mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.name);
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
}
if (!c.serviceDead) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Disconnecting binding " + b.intent
+ ": shouldUnbind=" + b.intent.hasBound);
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
bumpServiceExecutingLocked(s, false, "unbind");
if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0
&& s.app.setProcState <= ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
// If this service's process is not already in the cached list,
// then update it in the LRU list here because this may be causing
// it to go down there and we want it to start out near the top.
mAm.updateLruProcessLocked(s.app, false, null);
}
mAm.updateOomAdjLocked(s.app, true);
b.intent.hasBound = false;
// Assume the client doesn't want to know about a rebind;
// we will deal with that later if it asks for one.
b.intent.doRebind = false;
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
serviceProcessGoneLocked(s);
}
}
// If unbound while waiting to start, remove the pending service
mPendingServices.remove(s);
if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
boolean hasAutoCreate = s.hasAutoCreateConnections();
if (!hasAutoCreate) {
if (s.tracker != null) {
s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
}
}
}
public String toString() {
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ConnectionRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" u");
sb.append(binding.client.userId);
sb.append(' ');
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
sb.append("CR ");
}
if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
sb.append("DBG ");
}
if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
sb.append("!FG ");
}
if ((flags&Context.BIND_IMPORTANT_BACKGROUND) != 0) {
sb.append("IMPB ");
}
if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
sb.append("ABCLT ");
}
if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
sb.append("OOM ");
}
if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
sb.append("WPRI ");
}
if ((flags&Context.BIND_IMPORTANT) != 0) {
sb.append("IMP ");
}
if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
sb.append("WACT ");
}
if ((flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0) {
sb.append("FGSA ");
}
if ((flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
sb.append("FGS ");
}
if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
sb.append("LACT ");
}
if ((flags&Context.BIND_VISIBLE) != 0) {
sb.append("VIS ");
}
if ((flags&Context.BIND_SHOWING_UI) != 0) {
sb.append("UI ");
}
if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
sb.append("!VIS ");
}
if (serviceDead) {
sb.append("DEAD ");
}
sb.append(binding.service.shortName);
sb.append(":@");
sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
sb.append('}');
return stringName = sb.toString();
}
public String toString() {
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ConnectionBindRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" p");
sb.append(binding.client.pid);
sb.append(' ');
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
sb.append("CR ");
}
if ((flags & Context.BIND_DEBUG_UNBIND) != 0) {
sb.append("DBG ");
}
if ((flags & Context.BIND_NOT_FOREGROUND) != 0) {
sb.append("!FG ");
}
if ((flags & Context.BIND_ABOVE_CLIENT) != 0) {
sb.append("ABCLT ");
}
if ((flags & Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
sb.append("OOM ");
}
if ((flags & Context.BIND_WAIVE_PRIORITY) != 0) {
sb.append("WPRI ");
}
if ((flags & Context.BIND_IMPORTANT) != 0) {
sb.append("IMP ");
}
if ((flags & Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
sb.append("WACT ");
}
if (serviceDead) {
sb.append("DEAD ");
}
sb.append(binding.service.shortName);
sb.append(":@");
sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
sb.append('}');
stringName = sb.toString();
return stringName;
}
private void removeConnectionLocked(ConnectionBindRecord c) {
IBinder binder = c.conn.asBinder();
ProcessBindRecord b = c.binding;
ServiceRecord s = b.service;
// ServiceRecord.connections<Map - Key:IBinder>
ArrayList<ConnectionBindRecord> clist = s.connections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
s.connections.remove(binder);
}
}
// ProcessBindRecord.connections<List>
b.connections.remove(c);
// ProcessRecord.connections<List>
b.client.connections.remove(c);
// PluginServiceServer.mServiceConnections<Map - Key:IBinder>
clist = mServiceConnections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
mServiceConnections.remove(binder);
}
}
// 若所有BindConnection都已不再连接,则清除其Map
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
}
// 之前已经打算解绑了?无需再做
if (c.serviceDead) {
return;
}
// 当所有应用都已解绑后,则直接调用onUnbind
if (b.intent.apps.size() == 0 && b.intent.hasBound) {
b.intent.hasBound = false;
s.service.onUnbind(b.intent.intent.getIntent());
if (LOG) {
LogDebug.i(PLUGIN_TAG, "PSM.removeConnectionLocked(): boundRef is 0, call onUnbind(), sr=" + s);
}
// 尝试释放Service对象
if ((c.flags & Context.BIND_AUTO_CREATE) != 0) {
recycleServiceIfNeededLocked(s);
}
} else {
if (LOG) {
LogDebug.i(PLUGIN_TAG, "PSM.removeConnectionLocked(): Not unbind, sr=" + s);
}
}
}