/*
|
* Copyright (C) 2006 The Android Open Source Project
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
package com.android.server.am;
|
|
import android.content.Context;
|
import android.content.Intent;
|
import android.os.IBinder;
|
import android.util.ArrayMap;
|
import android.util.ArraySet;
|
import android.util.proto.ProtoOutputStream;
|
|
import java.io.PrintWriter;
|
|
/**
|
* A particular Intent that has been bound to a Service.
|
*/
|
final class IntentBindRecord {
|
/** The running service. */
|
final ServiceRecord service;
|
/** The intent that is bound.*/
|
final Intent.FilterComparison intent; //
|
/** All apps that have bound to this Intent. */
|
final ArrayMap<ProcessRecord, AppBindRecord> apps
|
= new ArrayMap<ProcessRecord, AppBindRecord>();
|
/** Binder published from service. */
|
IBinder binder;
|
/** Set when we have initiated a request for this binder. */
|
boolean requested;
|
/** Set when we have received the requested binder. */
|
boolean received;
|
/** Set when we still need to tell the service all clients are unbound. */
|
boolean hasBound;
|
/** Set when the service's onUnbind() has asked to be told about new clients. */
|
boolean doRebind;
|
|
String stringName; // caching of toString
|
|
void dump(PrintWriter pw, String prefix) {
|
pw.print(prefix); pw.print("service="); pw.println(service);
|
dumpInService(pw, prefix);
|
}
|
|
void dumpInService(PrintWriter pw, String prefix) {
|
pw.print(prefix); pw.print("intent={");
|
pw.print(intent.getIntent().toShortString(false, true, false, false));
|
pw.println('}');
|
pw.print(prefix); pw.print("binder="); pw.println(binder);
|
pw.print(prefix); pw.print("requested="); pw.print(requested);
|
pw.print(" received="); pw.print(received);
|
pw.print(" hasBound="); pw.print(hasBound);
|
pw.print(" doRebind="); pw.println(doRebind);
|
for (int i=0; i<apps.size(); i++) {
|
AppBindRecord a = apps.valueAt(i);
|
pw.print(prefix); pw.print("* Client AppBindRecord{");
|
pw.print(Integer.toHexString(System.identityHashCode(a)));
|
pw.print(' '); pw.print(a.client); pw.println('}');
|
a.dumpInIntentBind(pw, prefix + " ");
|
}
|
}
|
|
IntentBindRecord(ServiceRecord _service, Intent.FilterComparison _intent) {
|
service = _service;
|
intent = _intent;
|
}
|
|
int collectFlags() {
|
int flags = 0;
|
for (int i=apps.size()-1; i>=0; i--) {
|
final ArraySet<ConnectionRecord> connections = apps.valueAt(i).connections;
|
for (int j=connections.size()-1; j>=0; j--) {
|
flags |= connections.valueAt(j).flags;
|
}
|
}
|
return flags;
|
}
|
|
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.shortInstanceName);
|
sb.append(':');
|
if (intent != null) {
|
intent.getIntent().toShortString(sb, false, false, false, false);
|
}
|
sb.append('}');
|
return stringName = sb.toString();
|
}
|
|
public void writeToProto(ProtoOutputStream proto, long fieldId) {
|
long token = proto.start(fieldId);
|
if (intent != null) {
|
intent.getIntent().writeToProto(proto,
|
IntentBindRecordProto.INTENT, false, true, false, false);
|
}
|
if (binder != null) {
|
proto.write(IntentBindRecordProto.BINDER, binder.toString());
|
}
|
proto.write(IntentBindRecordProto.AUTO_CREATE,
|
(collectFlags()&Context.BIND_AUTO_CREATE) != 0);
|
proto.write(IntentBindRecordProto.REQUESTED, requested);
|
proto.write(IntentBindRecordProto.RECEIVED, received);
|
proto.write(IntentBindRecordProto.HAS_BOUND, hasBound);
|
proto.write(IntentBindRecordProto.DO_REBIND, doRebind);
|
|
final int N = apps.size();
|
for (int i=0; i<N; i++) {
|
AppBindRecord a = apps.valueAt(i);
|
if (a != null) {
|
a.writeToProto(proto, IntentBindRecordProto.APPS);
|
}
|
}
|
proto.end(token);
|
}
|
}
|