//packages/service/***/Call.java
public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) {
setHandle(connection.getHandle(), connection.getHandlePresentation());//这个函数很重要,会启动一个查询
setCallerDisplayName(connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
setExtras(connection.getExtras());
if (mIsIncoming) {
// We do not handle incoming calls immediately when they are verified by the connection
// service. We allow the caller-info-query code to execute first so that we can read the
// direct-to-voicemail property before deciding if we want to show the incoming call to
// the user or if we want to reject the call.
mDirectToVoicemailQueryPending = true;
// Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
// showing the user the incoming call screen.
mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis(
mContext.getContentResolver()));
}
}
//Call.java
public void setHandle(Uri handle, int presentation) {
startCallerInfoLookup();
}
private void startCallerInfoLookup() {
final String number = mHandle == null ? null : mHandle.getSchemeSpecificPart();
mQueryToken++; // Updated so that previous queries can no longer set the information.
mCallerInfo = null;
if (!TextUtils.isEmpty(number)) {
mHandler.post(new Runnable() {
@Override
public void run() {
mCallerInfoAsyncQueryFactory.startQuery(mQueryToken,
mContext,number,mCallerInfoQueryListener,Call.this);
}});
}
}
private static final ComponentName SERVICE_COMPONENT = new ComponentName(
"com.android.server.telecom",
"com.android.server.telecom.components.TelecomService");
private void connectToTelecom() {
synchronized (mLock) {
TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
Intent intent = new Intent(SERVICE_ACTION);
intent.setComponent(SERVICE_COMPONENT);
// Bind to Telecom and register the service
if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
mServiceConnection = serviceConnection;
} }}
public void onBootPhase(int phase) {//这个在系统启动阶段就会触发
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
connectToTelecom();
}}
//TelecomService.java
TelecomSystem.setInstance(
new TelecomSystem(
context,
new MissedCallNotifierImpl(context.getApplicationContext()),
new CallerInfoAsyncQueryFactory() {
@Override
public CallerInfoAsyncQuery startQuery(int token, Context context,
String number,CallerInfoAsyncQuery.OnQueryCompleteListener listener,
Object cookie) {
return CallerInfoAsyncQuery.startQuery(token, context, number, listener, cookie);
}},
new HeadsetMediaButtonFactory() {},
new ProximitySensorManagerFactory() {},
new InCallWakeLockControllerFactory() {},
new ViceNotifier() {}));
//frameworks/base/telephony/java/com/android/internal/CallerInfoAsyncQuery.java
/**
* Factory method to start the query based on a number.
*
* Note: if the number contains an "@" character we treat it
* as a SIP address, and look it up directly in the Data table
* rather than using the PhoneLookup table.
* TODO: But eventually we should expose two separate methods, one for
* numbers and one for SIP addresses, and then have
* PhoneUtils.startGetCallerInfo() decide which one to call based on
* the phone type of the incoming connection.
*/
public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
OnQueryCompleteListener listener, Object cookie) {
int subId = SubscriptionManager.getDefaultSubId();
return startQuery(token, context, number, listener, cookie, subId);
}
/**
* Factory method to start the query with a Uri query spec.
*/
public static CallerInfoAsyncQuery startQuery(int token, Context context, Uri contactRef,
OnQueryCompleteListener listener, Object cookie) {
c.mHandler.startQuery(token,
cw, // cookie
contactRef, // uri,注意这里的查询地址
null, // projection
null, // selection
null, // selectionArgs
null); // orderBy
return c;
}
//frameworks/base/***/CallerInfoAsyncQuery.java
public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, OnQueryCompleteListener listener, Object cookie, int subId) {
// Construct the URI object and query params, and start the query.
final Uri contactRef = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon().appendPath(number)
.appendQueryParameter(PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS, String.valueOf(PhoneNumberUtils.isUriNumber(number)))
.build();
CallerInfoAsyncQuery c = new CallerInfoAsyncQuery();
c.allocate(context, contactRef);
//create cookieWrapper, start query
CookieWrapper cw = new CookieWrapper();
cw.listener = listener; cw.cookie = cookie;
cw.number = number; cw.subId = subId;
// check to see if these are recognized numbers, and use shortcuts if we can.
if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
cw.event = EVENT_EMERGENCY_NUMBER;
} else if (PhoneNumberUtils.isVoiceMailNumber(subId, number)) {
cw.event = EVENT_VOICEMAIL_NUMBER;
} else {
cw.event = EVENT_NEW_QUERY;
}
c.mHandler.startQuery(token,
cw, // cookie
contactRef, // uri
null, // projection
null, // selection
null, // selectionArgs
null); // orderBy
return c;
}
//AsyncQueryHandler.java
public void startQuery(int token, Object cookie, Uri uri,
String[] projection, String selection, String[] selectionArgs,
String orderBy) {
// Use the token as what so cancelOperations works properly
Message msg = mWorkerThreadHandler.obtainMessage(token);
msg.arg1 = EVENT_ARG_QUERY;
WorkerArgs args = new WorkerArgs();
args.handler = this;
args.uri = uri;
msg.obj = args;
mWorkerThreadHandler.sendMessage(msg);
}
//AsyncQueryHandler.java
public void handleMessage(Message msg) {
WorkerArgs args = (WorkerArgs) msg.obj;
CookieWrapper cw = (CookieWrapper) args.cookie;
if (cw == null) {
// Normally, this should never be the case for calls originating
// from within this code.
// However, if there is any code that this Handler calls (such as in
// super.handleMessage) that DOES place unexpected messages on the
// queue, then we need pass these messages on.
} else {
switch (cw.event) {
case EVENT_NEW_QUERY://它的值跟AsyncQueryHandler的EVENT_ARG_QUERY一样,都是1
//start the sql command.
super.handleMessage(msg);
break;
case EVENT_END_OF_QUEUE:
// query was already completed, so just send the reply.
// passing the original token value back to the caller
// on top of the event values in arg1.
Message reply = args.handler.obtainMessage(msg.what);
reply.obj = args;
reply.arg1 = msg.arg1;
reply.sendToTarget();
break;
default:
}}}}
//AsyncQueryHandler.java
protected class WorkerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
final ContentResolver resolver = mResolver.get();
WorkerArgs args = (WorkerArgs) msg.obj;
int token = msg.what;
int event = msg.arg1;
switch (event) {
case EVENT_ARG_QUERY:
Cursor cursor;
try {
cursor = resolver.query(args.uri, args.projection,
args.selection, args.selectionArgs,
args.orderBy);
// Calling getCount() causes the cursor window to be filled,
// which will make the first access on the main thread a lot faster.
if (cursor != null) {
cursor.getCount();
}}
args.result = cursor;
break;
}
// passing the original token value back to the caller
// on top of the event values in arg1.
Message reply = args.handler.obtainMessage(token);
reply.obj = args;
reply.arg1 = msg.arg1;
reply.sendToTarget();
}}
<provider android:name="ContactsProvider2" android:authorities="contacts;com.android.contacts" android:readPermission="android.permission.READ_CONTACTS" android:writePermission="android.permission.WRITE_CONTACTS"> <path-permission android:pathPrefix="/search_suggest_query" android:readPermission="android.permission.GLOBAL_SEARCH" /> <path-permission android:pathPattern="/contacts/.*/photo" android:readPermission="android.permission.GLOBAL_SEARCH" /> <grant-uri-permission android:pathPattern=".*" /> </provider>
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// check the token and if needed, create the callerinfo object.
if (mCallerInfo == null) {
if (cw.event == EVENT_EMERGENCY_NUMBER) {
} else if (cw.event == EVENT_VOICEMAIL_NUMBER) {
} else {
mCallerInfo = CallerInfo.getCallerInfo(mContext, mQueryUri, cursor);
}
}
}
//notify the listener that the query is complete.
if (cw.listener != null) {
cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
}
}
}
//CallerInfo.java
public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) {
CallerInfo info = new CallerInfo();
if (cursor != null) {
if (cursor.moveToFirst()) {
columnIndex = cursor.getColumnIndex(PhoneLookup.LOOKUP_KEY);
if (columnIndex != -1) {
info.lookupKey = cursor.getString(columnIndex);
}
info.contactExists = true;
}
cursor.close();
cursor = null;
}
info.needUpdate = false;
info.name = normalize(info.name);
info.contactRefUri = contactRef;
return info;
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有