... ...
}
else if (strcmp(argv[optind], "list") == 0) {
Vector services = sm->listServices();
aout << "Found " << services.size() << " services:" << endl;
for (unsigned i = 0; i < services.size(); i++) {
String16 name = services[i];
sp service = sm->checkService(name);
aout << i
<< "\t" << good_old_string(name)
<< ": [" << good_old_string(get_interface_name(service)) << "]"
<< endl;
}
} else if (strcmp(argv[optind], "call") == 0) {
... ...
haha
// 这个好像是字符串转化相关的,String8 和 String16 都是 android 在 native
// 对 char 串的封装
static String8 good_old_string(const String16& src)
{
String8 name8;
char ch8[2];
ch8[1] = 0;
for (unsigned j = 0; j < src.size(); j++) {
char16_t ch = src[j];
if (ch < 128) ch8[0] = (char)ch;
name8.append(ch8);
}
return name8;
}
// get the name of the generic interface we hold a reference to
static String16 get_interface_name(sp service)
{
if (service != NULL) {
Parcel data, reply;
status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
if (err == NO_ERROR) {
return reply.readString16();
}
}
return String16();
}
status_t BBinder::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case INTERFACE_TRANSACTION:
reply->writeString16(getInterfaceDescriptor());
return NO_ERROR;
... ...
default:
return UNKNOWN_TRANSACTION;
}
}
... ...
} else if (strcmp(argv[optind], "call") == 0) {
optind++;
if (optind+1 < argc) {
int serviceArg = optind;
// 从 sm 那获取指定的 service 接口(Bp)
sp service = sm->checkService(String16(argv[optind++]));
// 获取服务的标示
String16 ifName = get_interface_name(service);
int32_t code = atoi(argv[optind++]);
if (service != NULL && ifName.size() > 0) {
Parcel data, reply;
// 呵呵,先写服务的标示
// the interface name is first
data.writeInterfaceToken(ifName);
// 支持的参数有3种类型:i32、s16 和 intent
// then the rest of the call arguments
while (optind < argc) {
// i32 就是 int32,非常简单的类型,
// 直接使用 parcel 的 writeInt32
if (strcmp(argv[optind], "i32") == 0) {
optind++;
if (optind >= argc) {
aerr << "service: no integer supplied for 'i32'" << endl;
wantsUsage = true;
result = 10;
break;
}
data.writeInt32(atoi(argv[optind++]));
} else if (strcmp(argv[optind], "s16") == 0) {
// s16 就是 String16,也是比较简单的类型
// parcel 都有现成的接口可用
optind++;
if (optind >= argc) {
aerr << "service: no string supplied for 's16'" << endl;
wantsUsage = true;
result = 10;
break;
}
data.writeString16(String16(argv[optind++]));
} else if (strcmp(argv[optind], "null") == 0) {
optind++;
data.writeStrongBinder(NULL);
} else if (strcmp(argv[optind], "intent") == 0) {
// 下面这个 intent 类型,就有点麻烦了,我暂时没去管它 ... ...
... ...
} else {
aerr << "service: unknown option " << argv[optind] << endl;
wantsUsage = true;
result = 10;
break;
}
}
// parcel 打好包好,调用 service 的 transact 函数
service->transact(code, data, &reply);
// 打印 parcel 打包的返回值
aout << "Result: " << reply << endl;
} else {
aerr << "service: Service " << argv[serviceArg]
<< " does not exist" << endl;
result = 10;
}
} else {
... ...
static final int TRANSACTION_startViewServer = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_stopViewServer = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_isViewServerRunning = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
// 然后去翻下 IBinder 发现是从 1 开始的
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
LAST_CALL_TRANSACTION = 0x00ffffff,
... ...
};
/*
* Starts the view server on the specified port.
*
* @param port The port to listener to.
*
* @return True if the server was successfully started, false otherwise.
*
* @see com.android.server.wm.ViewServer
* @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
*/
@Override
public boolean startViewServer(int port)
/**
* ===== NOTICE =====
* The first three methods must remain the first three methods. Scripts
* and tools rely on their transaction number to work properly.
*/
// This is used for debugging
boolean startViewServer(int port); // Transaction #1
boolean stopViewServer(); // Transaction #2
boolean isViewServerRunning(); // Transaction #3
@Override
public float getAnimationScale(int which) {
switch (which) {
case 0: return mWindowAnimationScale;
case 1: return mTransitionAnimationScale;
case 2: return mAnimatorDurationScale;
}
return 0;
}