package com.android.contacts;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.accounts.Account;
import android.app.Service;
import android.content.AsyncQueryHandler;
import android.content.BroadcastReceiver;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.provider.Settings.System;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.widget.Toast;
import android.os.ServiceManager;
import android.provider.ContactsContract.Contacts;
//import com.android.settings.AirplaneModeEnabler;
import com.android.contacts.ContactsUtils;
import com.android.contacts.model.ContactsAccount;
import com.android.contacts.ui.SimUtils;
import com.android.internal.telephony.AdnRecord;
import com.android.internal.telephony.IIccPhoneBook;
import com.android.internal.telephony.PhoneFactory;
import android.telephony.ServiceState;
import com.android.contacts.util.CommonUtil;
import com.android.contacts.util.Constants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.IccCard;
import com.google.android.collect.Lists;
import android.provider.Telephony.Intents;
import android.app.ActivityManagerNative;
import android.os.SystemProperties;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.FileReader;
public class SyncSimContactsService extends Service {
private static final String LOG_TAG = "SyncSimContactsService";
private static final String TAG = "SyncSimContactsService";
private static final String[] SIM_COLUMN = new String[] { "name", "number",
"emails", "sim_index" };
private static final int INDEX_NAME_COLUMN = 0;
private static final int INDEX_NUMBER_COLUMN = 1;
private static final int INDEX_EMAILS_COLUMN = 2;
private static final int INDEX_SIM_INDEX_COLUMN = 3;
private static final int MESSAGE_INIT = 11111;
private static final int MESSAGE_FINISH = 11112;
public static final String PREFS_SIM_FILE = "sim_sync_file";
public static final String PREFS_SIM_KEY = "sim_sync_key";
public static final String PREFS_SIM_KEY0 = "sim_sync_key0";
public static final String PREFS_SIM_KEY1 = "sim_sync_key1";
public static final String PREFS_SIM_STATE_IDLE = "sim.state.idle";
public static final String PREFS_SIM_STATE_BOOT_DELETED = "sim.state.boot.delete";
public static final String PREFS_SIM_STATE_SHUT_DELETED = "sim.state.shut.delete";
public static final String PREFS_SIM_STATE_IMPORTING = "sim.state.importing";
public static final String PREFS_SIM_STATE_IMPORTED = "sim.state.imported";
private static final int PATCH_INSERT_COUNT = 50;
private static final int DELETE_MAX_COUNT = 200;
private static boolean isWorking = false;
private int mSimIndex = 0;
private ServiceHandler mServiceHandler;
private int mStartId;
//TelephoneManager t = (TelephonyManager) mContext.getSystemService(mContext.TELEPHONY_SERVICE);
private boolean isDualSim = false;
private Context mContext;
private boolean mState = false;
private void setDualSim() {
if (TelephonyManager.getPhoneCount()>1)
isDualSim = true;
Log.w(TAG, "isDualSim = " + isDualSim);
return;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
mContext = this;
mServiceHandler = new ServiceHandler();
clearAllSyncState();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand mState = " + mState + " serviceId = " + startId);
if (!mState) {
setDualSim();
mStartId = startId;
mState = true;
Log.d(LOG_TAG, "--------onStartCommand::startId = " + startId);
doServicehandler(MESSAGE_INIT, startId, intent);
} else {
//stopSelf(startId);
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
unregisterSimLoadedReceiver();
super.onDestroy();
isWorking = false;
mState = false;
Log.d(TAG, "End Service onDestory mState = " + mState + " mStartId = " + mStartId);
}
private void clearSyncState() {
SharedPreferences.Editor editor = getSharedPreferences(PREFS_SIM_FILE,
MODE_PRIVATE).edit();
editor.putString(PREFS_SIM_KEY, PREFS_SIM_STATE_IDLE);
editor.commit();
}
private void setSyncState(String state) {
Log.d(LOG_TAG, "--------setSyncState key = " + PREFS_SIM_KEY
+ " , state = " + state);
SharedPreferences.Editor editor = getSharedPreferences(PREFS_SIM_FILE,
MODE_PRIVATE).edit();
editor.putString(PREFS_SIM_KEY, state);
editor.commit();
}
private String getSyncState() {
SharedPreferences pref = getSharedPreferences(PREFS_SIM_FILE,
MODE_PRIVATE);
return pref.getString(PREFS_SIM_KEY, PREFS_SIM_STATE_IDLE);
}
//for dual sim begin
public static void clearSyncState(Context context, int phoneId) {
SharedPreferences.Editor editor = context.getSharedPreferences(PREFS_SIM_FILE,
MODE_PRIVATE).edit();
editor.putString(PREFS_SIM_KEY + phoneId, PREFS_SIM_STATE_IDLE);
editor.commit();
}
public static void setSyncState(Context context, String state, int phoneId) {
Log.d(TAG, "setSyncState key = " + (PREFS_SIM_KEY + phoneId)
+ " , state = " + state);
SharedPreferences.Editor editor = context.getSharedPreferences(PREFS_SIM_FILE,
MODE_PRIVATE).edit();
editor.putString(PREFS_SIM_KEY + phoneId, state);
editor.commit();
}
public static String getSyncState(Context context, int phoneId) {
SharedPreferences pref = context.getSharedPreferences(PREFS_SIM_FILE,
MODE_PRIVATE);
return pref.getString(PREFS_SIM_KEY + phoneId, PREFS_SIM_STATE_IDLE);
}
//for dual sim end
// clear SharedPreferences
public void clearAllSyncState() {
SharedPreferences.Editor editor = getSharedPreferences(PREFS_SIM_FILE, MODE_PRIVATE).edit();
editor.clear();
editor.commit();
}
private Uri getSimDeleteUri() {
return RawContacts.CONTENT_URI
.buildUpon()
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER,
"true").build();
}
private void waitForBootCompleted(final int startId, int phoneId) {
Message msg = Message.obtain(mWaitHandler);
msg.what = MESSAGE_WAIT;
msg.arg1 = startId;
//add for dual sim begin
if (isDualSim)
msg.arg2 = phoneId;
//add for dual sim end
mWaitHandler.sendMessageDelayed(msg, WAIT_DELAY_TIME);
}
private static final int MESSAGE_WAIT = 11001;
private WaitHandler mWaitHandler = new WaitHandler();
private static final int WAIT_MAX_COUNT = 60;
private int mCurrentCount = 0;
private static final int WAIT_DELAY_TIME = 5 * 1000; // 5s
private class WaitHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_WAIT:
Log.d(LOG_TAG, "-------------waitForBootCompleted");
int serviceStartId = msg.arg1;
int phoneId = -1;
if (isDualSim) {
phoneId = msg.arg2;
}
if (isBootCompleted()) {
checkSimPrefsAndDo(serviceStartId, phoneId);
} else if (mCurrentCount <= WAIT_MAX_COUNT) {
mCurrentCount++;
waitForBootAndImport(serviceStartId, phoneId);
}
break;
default:
break;
}
}
}
//added for dual sim begin
private void clearSimAction(final int serviceStartId, final boolean boot, int phoneId) {
Log.d(TAG, "clearSimAction::begin boot is " + boot + " begin clear sim contacts thread!");
SimClearThread simClear = new SimClearThread(serviceStartId, boot, phoneId);
simClear.start();
}
private class SimClearThread extends Thread {
private int mServiceStartId;
private ContactsAccount mAccount;
private final int mPhoneId;
private int mSimIndex = 0;
private ContentResolver mResolver;
private boolean mBoot = false;
SimClearThread(int id, boolean boot, int phoneId) {
mServiceStartId = id;
mPhoneId = phoneId;
mBoot = boot;
}
@Override
public void run() {
Log.d(TAG, "serviceId = " + mServiceStartId + " mPhoneId = " + mPhoneId + " mBoot = " +mBoot);
StringBuffer where = new StringBuffer();
where.append(RawContacts.ACCOUNT_NAME).append("=\'").append(
mPhoneId == 0 ? Account.SIM1_ACCOUNT_NAME : Account.SIM2_ACCOUNT_NAME).append("\'")
.append(" AND " + RawContacts.SIM_INDEX + "<>0");
getContentResolver().delete(getSimDeleteUri(), where.toString(), null);
if (mBoot) {
Log.v(TAG, "BOOT COMPLEMENTED DELETE");
setSyncState(mContext, PREFS_SIM_STATE_BOOT_DELETED, mPhoneId);
} else {
Log.v(TAG, "SHUTDOWN DELETE");
setBootCompleteState(false);
setSyncState(mContext, PREFS_SIM_STATE_SHUT_DELETED, mPhoneId);
}
return;
}
}
//added for dual sim end
private void deleteSimAction(final int startId, final boolean boot, final int phoneId) {
Log.d(LOG_TAG, "-------deleteSimAction::begin boot is " + boot);
isWorking = true;
if(phoneId == 0 ){
getContentResolver().delete(getSimDeleteUri(),
RawContacts.ACCOUNT_NAME + " = 'SIM1'", null);
}else if(phoneId == 1){
getContentResolver().delete(getSimDeleteUri(),
RawContacts.ACCOUNT_NAME + " = 'SIM2'", null);
}else {
Log.e(TAG, "this is the wrong phoneID");
return;
}
if (boot) {
Log.v(LOG_TAG, "boot complement");
setSyncState(PREFS_SIM_STATE_BOOT_DELETED);
setBootCompleteState(false);
//setBootCompleteState(true);
} else {
Log.v(LOG_TAG, "shutdown");
setSyncState(PREFS_SIM_STATE_SHUT_DELETED);
}
return;
}
private void deleteSimAction(final int startId, final boolean boot) {
Log.d(LOG_TAG, "-------deleteSimAction::begin boot is " + boot);
isWorking = true;
getContentResolver().delete(getSimDeleteUri(),
RawContacts.SIM_INDEX + "<>0", null);
if (boot) {
Log.v(LOG_TAG, "boot complement");
setSyncState(PREFS_SIM_STATE_BOOT_DELETED);
setBootCompleteState(false);
} else {
Log.v(LOG_TAG, "shutdown");
setSyncState(PREFS_SIM_STATE_SHUT_DELETED);
}
return;
}
private void querySimAction(final int startId) {
Log.d(LOG_TAG, "-------querySimAction::begin");
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
// Cursor c = getContentResolver().query(
// Uri.parse("content://icc/adn"), SIM_COLUMN, null, null,
// null);
Log.d(LOG_TAG, "-------querySimAction::end");
doServicehandler(MESSAGE_FINISH, startId, null);
}
}).start();
}
//added for dual sim begin
private void importDualSimAction(int serviceId, int phoneId) {
String accountName = Account.SIM1_ACCOUNT_NAME;
Uri uri = SimUtils.SIM1_URI;
if (phoneId == 1) {
accountName = Account.SIM2_ACCOUNT_NAME;
uri = SimUtils.SIM2_URI;
}
DualSimcardImportThread simImport = new DualSimcardImportThread(serviceId,
new ContactsAccount(accountName, Account.SIM_ACCOUNT_TYPE, uri), phoneId);
simImport.start();
}
private static Object[] PREFS_SIM_STATE_LOCK = new Object[] {new Object(), new Object()};
private class DualSimcardImportThread extends Thread {
private int mServiceStartId;
private ContactsAccount mAccount;
private final int mPhoneId;
private int mSimIndex = 0;
private ContentResolver mResolver;
DualSimcardImportThread(int id, ContactsAccount account, int phoneId) {
mServiceStartId = id;
mAccount = account;
mPhoneId = phoneId;
mResolver = getContentResolver();
}
@Override
public void run() {
Log.d(TAG, "Begin import thread, first delete sim contacts in databases");
deleteSimAction(mServiceStartId, true, mPhoneId);
synchronized (PREFS_SIM_STATE_LOCK[mPhoneId]) {
if (PREFS_SIM_STATE_IMPORTING.equals(getSyncState(mContext, mPhoneId))
|| PREFS_SIM_STATE_IMPORTED.equals(getSyncState(mContext, mPhoneId))) {
return;
}
setSyncState(mContext, PREFS_SIM_STATE_IMPORTING, mPhoneId);
String whichSIM = mAccount.getContactsAccountName();
Log.v(TAG, "query " + whichSIM + " begin mAccount.getContactsAccountUri() = " + mAccount.getContactsAccountUri());
Cursor simCursor = null;
try {
simCursor = mResolver.query(mAccount.getContactsAccountUri(),
SIM_COLUMN, null, null, null);
} catch (Exception e) {
Log.d("TAG","query " + whichSIM + " crash ");
}
Log.d(TAG, "query " + whichSIM + " return cursor = " + simCursor);
if (simCursor == null || simCursor.getCount() == 0) {
Log.d(TAG, "Count of contacts on " + whichSIM + " is 0");
clearSimAction(mServiceStartId, true, mPhoneId);
doServicehandler(MESSAGE_FINISH, mServiceStartId, null);
return;
}
Log.d(TAG, "Count of contacts on " + whichSIM + " is " + simCursor.getCount());
Log.d(TAG, "query " + whichSIM + " end ");
int phoneId = 0;
if (Account.SIM2_ACCOUNT_NAME.equals(mAccount
.getContactsAccountName())) {
phoneId = 1;
}
int anrNum = 0;
int emailNum = 0;
IIccPhoneBook iccIpb = IIccPhoneBook.Stub
.asInterface(ServiceManager.getService(PhoneFactory
.getServiceName("simphonebook", phoneId)));
try {
anrNum = iccIpb.getAnrNum();
emailNum = iccIpb.getEmailNum();
Log.d(TAG, whichSIM + " anrNum = " + anrNum + "emailNum = " + emailNum);
} catch (RemoteException ex) {
Log.v(TAG, whichSIM + "excetpion", ex);
} catch (SecurityException ex) {
Log.v(TAG, whichSIM + "excetpion", ex);
}
String oneSimCursorValue;
boolean hasExistOldSimRecord;
mSimIndex = getEffectiveSimIndex();
ArrayList<ContentProviderOperation> simList = new ArrayList<ContentProviderOperation>();
Log.i(TAG, "Build " + whichSIM + " operation list begin");
simCursor.moveToPosition(-1);
while (simCursor.moveToNext()) {
String name_sim = simCursor.getString(simCursor
.getColumnIndex("name"));
String phoneNumber = simCursor.getString(simCursor
.getColumnIndex("number"));
String anr = simCursor.getString(simCursor
.getColumnIndex("anr"));
String mail = simCursor.getString(simCursor
.getColumnIndex("email"));
if (name_sim == null) {
name_sim = "";
}
if (phoneNumber == null) {
phoneNumber = "";
}
if (anr == null) {
anr = "";
for (int i = 1; i < anrNum; i++) {
anr += ":";
}
}
if (mail == null) {
mail = "";
}
oneSimCursorValue = "/" + name_sim + "/" + phoneNumber + "/"
+ anr + "/" + mail + "/";
Log.d(TAG, "new " + whichSIM + " contacts data : " + oneSimCursorValue);
Log.d(TAG, whichSIM + " insertSimContactsBatch::begin ");
insertSimContactsBatch(simCursor, mAccount, simList);
Log.d(TAG, whichSIM + " insertSimContactsBatch::end ");
}
Log.i(TAG, "Batch insert " + whichSIM + " contacts into databases begin");
try {
if(checkSimEnabled(phoneId)){
getContentResolver().applyBatch(ContactsContract.AUTHORITY, simList);
}
} catch (RemoteException e) {
Log.w(TAG, "Batch insert " + whichSIM + " contacts into databases fail", e);
} catch (OperationApplicationException e) {
Log.w(TAG, "Batch insert " + whichSIM + " contacts into databases fail", e);
}
Log.i(TAG, "Batch insert " + whichSIM + " contacts into databases end");
/*
Log.d(TAG, "Clear old " + whichSIM + " contacts begin");
String where = "";
for (int i = 0; i < sims.size(); i++) {
String id = sims.get(i);
where += "(" + (RawContacts._ID + "=" + Long.parseLong(id) + ") or ");
}
if (where.length() > 0) {
where = where.trim().substring(0,
where.length() - " or ".length());
Log.i(TAG, "Clear old " + whichSIM + " where is : " + where);
getContentResolver().delete(getSimDeleteUri(), where, null);
}
Log.d(TAG, "Clear old " + whichSIM + " contacts end");
where = "";
Log.i(TAG, "Delete some no data contacts on " + whichSIM + " begin");
// Delete empty sim record
for (int i = 0; i < old_sims.size(); i++) {
String id = old_sims.get(i);
if (!sims.contains(id)) {
where += "(" + RawContacts._ID + "=" + Long.parseLong(id) +") or ";
}
}
if (where.length() > 0) {
where = where.trim().substring(0,
where.length() - " or ".length());
Log.i(TAG, "Delete some no data contacts on " + whichSIM + " where is : " + where);
getContentResolver().delete(getSimDeleteUri(), where, null);
}
*/
Log.i(TAG, "Delete some no data contacts on " + whichSIM + " end");
setSyncState(mContext, PREFS_SIM_STATE_IMPORTED, mPhoneId);
doServicehandler(MESSAGE_FINISH, mServiceStartId, null);
mResolver.notifyChange(ContactsContract.Contacts.CONTENT_URI, null);
}
Log.d(TAG, "End import thread");
}
private int getEffectiveSimIndex() {
Cursor cursor = getContentResolver().query(RawContacts.CONTENT_URI,
new String[] {RawContacts.SIM_INDEX},
RawContacts.SIM_INDEX + "<>0",
null,
RawContacts.SIM_INDEX + " desc");
Log.v(LOG_TAG, "RawContacts.CONTENT_URI sim count is " + cursor.getCount());
int max_sim_index = 1;
try {
if (cursor.moveToFirst()) {
max_sim_index = cursor.getInt(0);
return max_sim_index + 1;
} else {
return 1;
}
} catch (Exception e) {
Log.v(LOG_TAG, "Fail query raw contact");
return 1;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
//added for dual sim begin
/**
* apply batch operation object add
*
* @param cursor
*/
private void insertSimContactsBatch(Cursor cursor,
ContactsAccount account, ArrayList<ContentProviderOperation> simList) {
int sim_index = Integer.valueOf(cursor
.getString(cursor.getColumnIndex("sim_index")));
String name = cursor.getString(cursor.getColumnIndex("name"));
String phoneNumber = cursor.getString(cursor
.getColumnIndex("number"));
String anr = cursor.getString(cursor.getColumnIndex("anr"));
String email = cursor.getString(cursor.getColumnIndex("email"));
String[] otherPhoneNumber = SimUtils.splitString(anr);
String[] otherMail = email == null ? null : email.split(",");
sim_index = mSimIndex++;
Log.w(TAG, "sim_index = " + sim_index);
ContentValues SimValues = new ContentValues();
SimValues.put(RawContacts.SIM_INDEX, sim_index);
SimValues.put(RawContacts.ACCOUNT_NAME,
account.getContactsAccountName());
SimValues.put(RawContacts.ACCOUNT_TYPE,
account.getContactsAccountType());
SimValues.put(RawContacts.AGGREGATION_MODE,
RawContacts.AGGREGATION_MODE_DISABLED);
int firstIndex = simList.size();
ContentProviderOperation simOperation = ContentProviderOperation
.newInsert(RawContacts.CONTENT_URI).withValues(SimValues)
.withYieldAllowed(true).build();
simList.add(simOperation);
if (!TextUtils.isEmpty(name)) {
ContentValues NameValues = new ContentValues();
NameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
NameValues.put(StructuredName.GIVEN_NAME, name);
ContentProviderOperation nameOperation = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex)
.withValues(NameValues).withYieldAllowed(true).build();
simList.add(nameOperation);
}
if (!TextUtils.isEmpty(phoneNumber)) {
ContentValues NumberValues = new ContentValues();
NumberValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
NumberValues.put(Phone.TYPE, Phone.TYPE_HOME);
NumberValues.put("data15", 0);
NumberValues.put(Phone.NUMBER, phoneNumber);
NumberValues.put(Data.IS_PRIMARY, 1);
NumberValues.put(Data.IS_SUPER_PRIMARY, 0);
ContentProviderOperation phoneOpertion = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex)
.withValues(NumberValues).withYieldAllowed(true)
.build();
simList.add(phoneOpertion);
}
// add othernumber
if (otherPhoneNumber != null) {
for (int i = 0; i < otherPhoneNumber.length; i++) {
if (!TextUtils.isEmpty(otherPhoneNumber[i])) {
ContentValues values = new ContentValues();
values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
values.put("data15", i + 1);
values.put(Phone.TYPE, NUMBERTYPE[i]);
values.put(Phone.NUMBER, otherPhoneNumber[i]);
values.put(Data.IS_PRIMARY, 1);
values.put(Data.IS_SUPER_PRIMARY, 0);
Log.d(LOG_TAG, NUMBERTYPE[i] + "===== " + otherPhoneNumber[i]);
ContentProviderOperation otherOperation = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID,
firstIndex).withValues(values)
.withYieldAllowed(true).build();
simList.add(otherOperation);
}
}
}
if (otherMail != null) {
for (int i = 0; i < otherMail.length; i++) {
String mail = otherMail[i];
if (!TextUtils.isEmpty(mail)) {
ContentValues mailValue = new ContentValues();
mailValue.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
mailValue.put("data15", i);
mailValue.put(Email.DATA, email);
mailValue.put(Data.IS_SUPER_PRIMARY, 0);
ContentProviderOperation emailOperation = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID,
firstIndex).withValues(mailValue)
.withYieldAllowed(true).build();
simList.add(emailOperation);
}
}
}
}
}
private void waitForBootAndImport(int serviceStartId, int phoneId) {
Message msg = Message.obtain(mWaitHandler);
msg.what = MESSAGE_WAIT;
msg.arg1 = serviceStartId;
msg.arg2 = phoneId;
mWaitHandler.sendMessageDelayed(msg, WAIT_DELAY_TIME);
}
//added for dual sim end
private void importSimAction(int id) {
// SyncSimContactsService.this.sendBroadcast(new Intent("com.android.contacts.SIM_OPERATE_START"));
isWorking = true;
SimcardImportThread simImport = new SimcardImportThread(id);
simImport.start();
}
private class SimcardImportThread extends Thread {
private int serviceId;
// private Cursor mSimCursor;
int a = 0;
//Lino modify for NEWMS00131859 begin 2011-10-27
ContentValues[] cvs;//haojie add
int DifferentSimCount = 0;
//Lino modify for NEWMS00131859 end 2011-10-27
// ArrayList<ContentProviderOperation>
ArrayList<ContentProviderOperation> simList = null;
SimcardImportThread(int id) {
serviceId = id;
}
private ArrayList<String> getOldSimIndex() {
ArrayList<String> old_sims = new ArrayList<String>();
Cursor total_cursor = getContentResolver().query(
RawContacts.CONTENT_URI,
new String[] { RawContacts.SIM_INDEX },
RawContacts.SIM_INDEX + "<>0", null, RawContacts.SIM_INDEX);
Log.d(LOG_TAG, "total_cursor.length = " + total_cursor.getCount());
try {
if (total_cursor != null && total_cursor.moveToFirst()) {
do {
old_sims.add(total_cursor.getString(0));
} while (total_cursor.moveToNext());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (total_cursor != null) {
total_cursor.close();
total_cursor = null;
}
}
return old_sims;
}
private ArrayList<String>[] getOldSimInfo() {
String name = "", mobileNumber = "", homeNumber = "", workNumber = "", otherNumber = "", email = "";
ArrayList<String>[] oldSimInfo = new ArrayList[2];
oldSimInfo[0] = new ArrayList<String>();
oldSimInfo[1] = new ArrayList<String>();
String sim_index = "0";
int row = 0;
Cursor c = getContentResolver().query(
Uri.parse("content://" + "com.android.contacts"
+ "/phone_or_email"),
new String[] { "sim_index", "data.data1", "data2",
Data.MIMETYPE }, RawContacts.SIM_INDEX + "<>0",
null, RawContacts.SIM_INDEX);
// prevSimCursor = new String[c.getCount()];
try {
if (c.moveToFirst()) {
sim_index = c.getString(0);
Log.v(LOG_TAG, "the first sim_index is " + sim_index);
do {
if (!c.getString(0).equals(sim_index)) {
oldSimInfo[0].add("/" + name + "/" + homeNumber
+ mobileNumber + "/" + workNumber + "/"
+ otherNumber + "/" + email + "/");
oldSimInfo[1].add(sim_index);
Log.d(LOG_TAG, "sim_index = " + sim_index);
Log.d(LOG_TAG,
"get a row check:" + oldSimInfo[0].get(row));
row++;
sim_index = c.getString(0);
homeNumber = "";
mobileNumber = "";
workNumber = "";
otherNumber = "";
name = "";
email = "";
}
if (Phone.CONTENT_ITEM_TYPE.equals(c.getString(3))) {
if ((Phone.TYPE_HOME + "").equals(c.getString(2))) {
homeNumber = c.getString(1);
if (homeNumber == null) {
homeNumber = "";
}
} else if ((Phone.TYPE_MOBILE + "").equals(c
.getString(2))) {
mobileNumber = c.getString(1);
if (mobileNumber == null) {
mobileNumber = "";
}
} else if ((Phone.TYPE_WORK + "").equals(c
.getString(2))) {
workNumber = c.getString(1);
if (workNumber == null) {
workNumber = "";
}
} else if ((Phone.TYPE_OTHER + "").equals(c
.getString(2))) {
otherNumber = c.getString(1);
if (otherNumber == null) {
otherNumber = "";
}
}
} else if (StructuredName.CONTENT_ITEM_TYPE.equals(c
.getString(3))) {
name = c.getString(1);
if (name == null) {
name = "";
}
} else if (Email.CONTENT_ITEM_TYPE.equals(c
.getString(3))) {
email = c.getString(1);
if (email == null) {
email = "";
}
}
} while (c.moveToNext());
// add the last record
oldSimInfo[0].add("/" + name + "/" + homeNumber
+ mobileNumber + "/" + workNumber + "/"
+ otherNumber + "/" + email + "/");
Log.d(LOG_TAG, "get a row check:" + oldSimInfo[0].get(row));
oldSimInfo[1].add(sim_index);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (c != null) {
c.close();
c = null;
}
}
return oldSimInfo;
}
private SparseBooleanArray buildSimContactsList(Cursor cursor,
ArrayList<String>[] oldSimInfo) {
SparseBooleanArray sim_flag = new SparseBooleanArray();
String oneSimCursorValue;
boolean hasExistOldSimRecord;
ContentResolver contresolver = SyncSimContactsService.this
.getContentResolver();// haojie add
if (cursor.moveToFirst()) {
do {
String name_sim = cursor.getString(cursor
.getColumnIndex("name"));
String phoneNumber = cursor.getString(cursor
.getColumnIndex("number"));
// TODO get otherNumber and email
String anr = cursor.getString(cursor.getColumnIndex("anr"));
String mail = cursor.getString(cursor
.getColumnIndex("email"));
String mobile_number = "", work_number = "", other_number = "";
if (name_sim == null) {
name_sim = "";
}
if (phoneNumber == null) {
phoneNumber = "";
}
if (mail == null) {
mail = "";
}
String[] otherPhoneNumber = splitString(anr);
if (otherPhoneNumber != null) {
for (int i = 0; i < otherPhoneNumber.length; i++) {
switch (i) {
case 0:
mobile_number = otherPhoneNumber[i];
break;
case 1:
work_number = otherPhoneNumber[i];
break;
case 2:
other_number = otherPhoneNumber[i];
break;
}
}
}
oneSimCursorValue = "/" + name_sim + "/" + phoneNumber
+ mobile_number + "/" + work_number + "/"
+ other_number + "/" + mail + "/";
Log.d(LOG_TAG, "oneSimCursorValue = " + oneSimCursorValue);
hasExistOldSimRecord = false;
for (int i = 0; i < oldSimInfo[0].size(); i++) {
if (sim_flag.get(
Integer.parseInt(oldSimInfo[1].get(i)), false)) {
continue;
}
if (oneSimCursorValue.equals(oldSimInfo[0].get(i))) {
hasExistOldSimRecord = true;
sim_flag.put(
Integer.parseInt(oldSimInfo[1].get(i)),
true);
break;
}
}
if (!hasExistOldSimRecord) {
Log.d(LOG_TAG,
"-------importOneSimContactsToPhoneTest::begin");
// importOneSimContactsToPhoneTest(mSimCursor);
insertSimContactsBatch(cursor);
}
} while (cursor.moveToNext());
try {
contresolver
.applyBatch(ContactsContract.AUTHORITY, simList);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
return null;
}
return sim_flag;
}
private void clearOldSimContactsList(SparseBooleanArray sim_flag,
ArrayList<String> old_sims, ArrayList<String> sims) {
if (sim_flag == null) {
getContentResolver().delete(getSimDeleteUri(),
RawContacts.SIM_INDEX + "<>0", null);
return;
}
String args[] = new String[sims.size()];
int s = 0;
for (int i = 0; i < sims.size(); i++) {
if (!sim_flag.get(Integer.parseInt(sims.get(i)), false)) {
args[s++] = sims.get(i);
/*
* getContentResolver().delete(getSimDeleteUri(),
* RawContacts.SIM_INDEX + "='" + sims.get(i) + "'", null);
*/
}
}
String where = "";
String[] args2 = new String[s];
for (int u = 0; u < s; u++) {
args2[u] = "'" + args[u] + "'";
where += (RawContacts.SIM_INDEX + "=" + args2[u] + " or ");
}
if (where.length() > 0) {
where = where.trim().substring(0,
where.length() - " or ".length());
getContentResolver().delete(getSimDeleteUri(), where, null);
}
where = "";
// Delete empty sim record
for (int i = 0; i < old_sims.size(); i++) {
if (!sims.contains(old_sims.get(i))) {
s++;
where += (RawContacts.SIM_INDEX + "=" + old_sims.get(i) + " or ");
}
if (i % DELETE_MAX_COUNT == 0) {
if (where.length() > 0) {
where = where.trim().substring(0,
where.length() - " or ".length());
getContentResolver().delete(getSimDeleteUri(), where,
null);
}
Log.v(LOG_TAG, "where = " + where);
where = "";
}
}
Log.v(LOG_TAG, "delete sim records is " + s);
if (where.length() > 0) {
where = where.trim().substring(0,
where.length() - " or ".length());
getContentResolver().delete(getSimDeleteUri(), where, null);
}
}
@Override
public void run() {
deleteSimAction(serviceId, true);
setSyncState(PREFS_SIM_STATE_IMPORTING);
Log.v(LOG_TAG, "query IccProvider start");
// add by chengyake for preventing crash Monday, October 29 2011 begin
Cursor simCursor = null;
try {
simCursor = getContentResolver().query(Uri.parse("content://icc/adn"), SIM_COLUMN,
null, null, null);
if(simCursor == null){
Log.d(LOG_TAG, "simCursor == null");
deleteSimAction(mStartId, true);
setSyncState(PREFS_SIM_STATE_IMPORTED);
isWorking = false;
doServicehandler(MESSAGE_FINISH, serviceId, null);
}else{
simList = new ArrayList<ContentProviderOperation>();
ArrayList<String> old_sims = getOldSimIndex();
ArrayList<String>[] oldSimInfo = getOldSimInfo();
SparseBooleanArray sim_flag = buildSimContactsList(simCursor,oldSimInfo);
clearOldSimContactsList(sim_flag,old_sims,oldSimInfo[1]);
}
} catch (Exception e) {
Log.d("LOG_TAG", "query IccProvider crash");
} finally{
// SyncSimContactsService.this.sendBroadcast(new Intent("com.android.contacts.SIM_OPERATE_END"));
if(simCursor != null){
simCursor.close();
}
}
Log.v(LOG_TAG, "sim operate complete");
setSyncState(PREFS_SIM_STATE_IMPORTED);
isWorking = false;
doServicehandler(MESSAGE_FINISH, serviceId, null);
getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null);
}
private int getEffectiveSimIndex(){
Cursor cursor = getContentResolver().query(RawContacts.CONTENT_URI,
new String[] {RawContacts.SIM_INDEX},
RawContacts.SIM_INDEX + "<>0",
null,
RawContacts.SIM_INDEX + " desc");
Log.v(LOG_TAG, "RawContacts.CONTENT_URI sim count is " + cursor.getCount());
int max_sim_index = 1;
try {
if(cursor.moveToFirst()){
max_sim_index = cursor.getInt(0);
return max_sim_index + 1;
}else{
return 1;
}
} catch (Exception e) {
Log.v(LOG_TAG, "Fail query raw contact");
return 1;
}finally{
if(cursor != null){
cursor.close();
}
}
}
//Lino modify for NEWMS00131859 end 2011-10-27
/**
* apply batch operation object add
* @param cursor
*/
private void insertSimContactsBatch(final Cursor cursor){
Log.v(LOG_TAG, "importOneSimContactsToPhoneTest");
String name = cursor.getString(cursor.getColumnIndex("name"));
String phoneNumber = cursor.getString(cursor
.getColumnIndex("number"));
int sim_index = Integer.valueOf(cursor.getString(cursor
.getColumnIndex("sim_index")));
String anr = cursor.getString(cursor.getColumnIndex("anr"));
String email = cursor.getString(cursor.getColumnIndex("email"));
// String[] otherPhoneNumber = null;
// if (anr != null) {
String[] otherPhoneNumber = splitString(anr);
// }
sim_index = ++mSimIndex;
Log.i(LOG_TAG,"sim_index" + sim_index);
ContentValues Values = new ContentValues();
ContentValues SimValues = new ContentValues();
ContentValues NameValues = new ContentValues();
ContentValues NumberValues = new ContentValues();
ContentValues OtherValues[] = new ContentValues[otherPhoneNumber.length];
ContentValues EmailValues = new ContentValues();
// add sim index
SimValues.put(RawContacts.SIM_INDEX, sim_index);
// Log.v(LOG_TAG, "sim_index=" + sim_index);
SimValues.put("sim_index", sim_index);
SimValues.put(RawContacts.ACCOUNT_NAME, Constants.SIM_ACCOUNT_NAME);
SimValues.put(RawContacts.ACCOUNT_TYPE, Constants.SIM_ACCOUNT_TYPE);
// Uri rawContactUri =
// SyncSimContactsService.this.getContentResolver()
// .insert(RawContacts.CONTENT_URI, SimValues);
// long rawContactId = ContentUris.parseId(rawContactUri);
int firstIndex = simList.size();
ContentProviderOperation simOperation = ContentProviderOperation
.newInsert(RawContacts.CONTENT_URI).withValues(SimValues)
.withYieldAllowed(true).build();
simList.add(simOperation);
// Log.d(LOG_TAG, "rawContactId=" + rawContactId);
if (!TextUtils.isEmpty(name)) { // && name.length() > 0){
NameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
NameValues.put(StructuredName.GIVEN_NAME, name);
ContentProviderOperation nameOperation = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex)
.withValues(NameValues).build();
simList.add(nameOperation);
}
if (!TextUtils.isEmpty(phoneNumber)) { // && phoneNumber.length() >
// 0){
NumberValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
NumberValues.put(Phone.TYPE, Phone.TYPE_HOME);
NumberValues.put(Phone.NUMBER, phoneNumber);
NumberValues.put(Data.IS_PRIMARY, 1);
NumberValues.put(Data.IS_SUPER_PRIMARY, 0);
ContentProviderOperation phoneOpertion = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex)
.withValues(NumberValues)
.build();
simList.add(phoneOpertion);
}
// add othernumber
if (otherPhoneNumber != null) {
for (int i = 0; i < otherPhoneNumber.length; i++) {
if (!TextUtils.isEmpty(otherPhoneNumber[i])) { // &&
// otherPhoneNumber[i].length()
// > 0) {
ContentValues values = new ContentValues();
OtherValues[i] = values;
OtherValues[i].put(Data.MIMETYPE,
Phone.CONTENT_ITEM_TYPE);
OtherValues[i].put(Phone.TYPE, NUMBERTYPE[i]);
OtherValues[i].put(Phone.NUMBER, otherPhoneNumber[i]);
OtherValues[i].put(Data.IS_PRIMARY, 1);
OtherValues[i].put(Data.IS_SUPER_PRIMARY, 0);
ContentProviderOperation otherOperation = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID,
firstIndex).withValues(OtherValues[i])
.build();
simList.add(otherOperation);
}
}
}
if (!TextUtils.isEmpty(email)) { // && email.length() > 0){
EmailValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
EmailValues.put(Email.TYPE, Email.TYPE_HOME);
EmailValues.put(Email.DATA, email);
EmailValues.put(Data.IS_PRIMARY, 1);
EmailValues.put(Data.IS_SUPER_PRIMARY, 0);
ContentProviderOperation emailOperation = ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex)
.withValues(EmailValues).build();
simList.add(emailOperation);
}
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private void doServicehandler(int what, int arg1, Object obj) {
// added for dual sim begin
Log.w(TAG, "start send message to handler intent = " + obj);
Intent intent = (Intent) obj;
if (isDualSim) {
int sendtimes = 1;
if (MESSAGE_INIT == what) {
if (isSendTwice(intent)) {
sendtimes = 2;
}
}
Log.e(TAG, "before send message sendtime = " + sendtimes);
if (sendtimes == 1) {
int phoneId = 0;
if (null != intent) {
phoneId = intent.getIntExtra(IccCard.INTENT_KEY_PHONE_ID, 0);
}
Message msgDualSim = mServiceHandler.obtainMessage(what);
msgDualSim.arg1 = arg1;
msgDualSim.arg2 = phoneId;
msgDualSim.obj = obj;
mServiceHandler.sendMessageDelayed(msgDualSim, 500L);
return;
}
for (int i = 0; i < sendtimes; i++) {
Message msgDualSim = mServiceHandler.obtainMessage(what);
msgDualSim.arg1 = arg1;
msgDualSim.arg2 = i;
msgDualSim.obj = obj;
mServiceHandler.sendMessageDelayed(msgDualSim, 500L);
}
}
// added for dual sim end
else {
Message msg = mServiceHandler.obtainMessage(what);
msg.arg1 = arg1;
msg.obj = obj;
mServiceHandler.sendMessage(msg);
}
}
private boolean isSendTwice(Intent intent){
boolean isSendTwoTimes = false;
String action = intent.getAction();
//if(!action.equals("android.intent.action.SelectSimCard")&& !action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)){
if(action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)){
//isSendTwoTimes = false;
isSendTwoTimes = true;
}else if(action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED0) ||
action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED1)){
isSendTwoTimes = false;
}
else if(!action.equals("android.intent.action.SelectSimCard") &&
!action.equals("android.intent.action.FDN_STATE_CHANGED0") &&
!action.equals("android.intent.action.FDN_STATE_CHANGED1") ){
isSendTwoTimes = true;
}else if(action.equals("android.intent.action.SelectSimCard")) {
boolean sim1Changed = intent.getBooleanExtra("SIM1", false);
boolean sim2Changed = intent.getBooleanExtra("SIM2", false);
if(sim1Changed && sim2Changed){
isSendTwoTimes = true;
}
}
Log.d(TAG, "isSendTwoTimes = "+ isSendTwoTimes);
return isSendTwoTimes;
}
private final String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric";
private BroadcastReceiver mProcessSimLoadedReceiver = null;
private void registerSimLoadedReceiver(){
Log.d(LOG_TAG, "registerSimLoadedReceiver");
if(mProcessSimLoadedReceiver == null){
mProcessSimLoadedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)){
String stateExtra = intent
.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
Log.d(LOG_TAG, "stateExtra = " + stateExtra);
if (stateExtra != null && stateExtra.equals(IccCard.INTENT_VALUE_ICC_LOADED)) {
importSimAction(mStartId);
}
}
}
};
}
IntentFilter filter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
registerReceiver(mProcessSimLoadedReceiver, filter);
}
//added for dual sim begin
private void registerSimLoadedReceiver(final int serviceStartId) {
if (mProcessSimLoadedReceiver == null) {
Log.d(TAG, "registerSimLoadedReceiver, serviceStartId = " + serviceStartId);
mProcessSimLoadedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
String stateExtra = intent
.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
Log.d(TAG, "[mProcessSimLoadedReceiver]phoneId = " +
intent.getIntExtra(IccCard.INTENT_KEY_PHONE_ID, -1) + ", stateExtra = " + stateExtra);
if (IccCard.INTENT_VALUE_ICC_LOADED.equals(stateExtra)) {
doServicehandler(MESSAGE_INIT, serviceStartId, intent);
} else if ("android.intent.action.FDN_STATE_CHANGED0".equals(action)
|| "android.intent.action.FDN_STATE_CHANGED1".equals(action)) {
doServicehandler(MESSAGE_INIT, serviceStartId, intent);
}
}
}
};
IntentFilter filter = new IntentFilter(
TelephonyIntents.ACTION_SIM_STATE_CHANGED);
registerReceiver(mProcessSimLoadedReceiver, filter);
filter = new IntentFilter("android.intent.action.FDN_STATE_CHANGED0");
registerReceiver(mProcessSimLoadedReceiver, filter);
filter = new IntentFilter("android.intent.action.FDN_STATE_CHANGED1");
registerReceiver(mProcessSimLoadedReceiver, filter);
filter = new IntentFilter(
TelephonyIntents.ACTION_SIM_STATE_CHANGED0);
registerReceiver(mProcessSimLoadedReceiver, filter);
filter = new IntentFilter(
TelephonyIntents.ACTION_SIM_STATE_CHANGED1);
registerReceiver(mProcessSimLoadedReceiver, filter);
}
}
//added for dual sim end
private void unregisterSimLoadedReceiver() {
Log.d(LOG_TAG, "unregisterSimLoadedReceiver");
if (mProcessSimLoadedReceiver != null) {
unregisterReceiver(mProcessSimLoadedReceiver);
mProcessSimLoadedReceiver = null;
}
}
private class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_INIT:
int startId = msg.arg1;
Intent intent = (Intent) msg.obj;
Log.w(TAG, "intent = " + intent);
if (intent != null) {
String action = intent.getAction();
Log.d(LOG_TAG, "-------------action = " + action);
//added for dual sim begin
if (isDualSim) {
int phoneId = msg.arg2;
String whichSIM = "SIM" + (phoneId + 1);
TelephonyManager t = (TelephonyManager) getSystemService(PhoneFactory
.getServiceName(Context.TELEPHONY_SERVICE, phoneId));
Log.d(TAG, "[ServiceHandler] phoneId = " + phoneId + ", ACTION = " + action);
if (action.equals(Intent.ACTION_BOOT_COMPLETED) ) {
//deleteSimAction(startId, true);
if (!isBootCompleted()) {
setBootCompleteState(true);
}
synchronized (PREFS_SIM_STATE_LOCK[phoneId]) {
clearSyncState(mContext, phoneId);
if (TelephonyManager.SIM_STATE_ABSENT == t.getSimState() || !checkSimEnabled(phoneId)) {
Log.d(TAG, whichSIM + " IS ABSENT or sim "+ phoneId + " is disabled");
clearSimAction(startId, true, phoneId);
if (isAllSimAbsent()) {
doServicehandler(MESSAGE_FINISH, startId, null);
break;
}
}
}
String sim_oper_num = t.getSimOperator();
Log.d(TAG, whichSIM + " PROPERTY_ICC_OPERATOR_NUMERIC value is " + sim_oper_num);
if ((sim_oper_num != null && sim_oper_num.length() != 0)) {
importDualSimAction(startId, phoneId);
} else {
clearSimAction(startId, true, phoneId);
registerSimLoadedReceiver(startId);
}
} else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED) ||
action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED0) ||
action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED1)) {
if(TelephonyManager.SIM_STATE_ABSENT == t.getSimState() || !checkSimEnabled(phoneId)){
Log.d(TAG, whichSIM + " IS ABSENT or sim "+ phoneId + " is disabled in SIM_STATE_CHANGED");
synchronized (PREFS_SIM_STATE_LOCK[phoneId]) {
clearSyncState(mContext, phoneId);
clearSimAction(startId, true, phoneId);
}
}else {
String stateExtra = intent
.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
//phoneId = intent.getIntExtra(IccCard.INTENT_KEY_PHONE_ID, -1);
Log.d(TAG, "[ServiceHandler: in SIM_STATE_CHANGED] ACTION_SIM_STATE_CHANGED phoneId = " + phoneId + " INTENT_KEY_ICC_STATE = " + stateExtra);
if (TelephonyManager.SIM_STATE_READY == t.getSimState() && IccCard.INTENT_VALUE_ICC_LOADED.equals(stateExtra) && checkSimEnabled(phoneId)) {
if (!isBootCompleted()) {
clearSyncState(mContext, phoneId);
//setBootCompleteState(true);
}
checkSimPrefsAndDo(startId, phoneId);
} else {
clearSyncState(mContext, phoneId);
clearSimAction(startId, true, phoneId);
registerSimLoadedReceiver(startId);
//finishServiceSelf(startId);
}
}
} else if (TelephonyIntents.SIM_ADNCACHE_LOADED.equals(action)) {
Log.v(TAG, "IccCard.INTENT_KEY_PHONE_ID = " + phoneId);
if (t.getAdnCachestate() == Constants.ADNCACHE_STATE_NOT_READY) {
Log.w(TAG, "importSimAction return when adn cache state not ready.");
return;
}else{
String sim_sync_state = getSyncState(mContext, phoneId);
Log.d(TAG, "[andCache loaded] sim_sync_state = " + sim_sync_state + " , phoneId = " + phoneId);
if (PREFS_SIM_STATE_BOOT_DELETED.equals(sim_sync_state)
|| PREFS_SIM_STATE_IDLE.equals(sim_sync_state)) {
importDualSimAction(startId, phoneId);
} else if (PREFS_SIM_STATE_IMPORTED.equals(sim_sync_state)) {
doServicehandler(MESSAGE_FINISH, startId, null);
}
}
} else if ("android.intent.action.FDN_STATE_CHANGED0".equals(action)
|| "android.intent.action.FDN_STATE_CHANGED1".equals(action)) {
phoneId = intent.getIntExtra("phone_id", -1);
boolean isEnableFDN = intent.getBooleanExtra("fdn_status", false);
Log.d(TAG, "in FDN changed phoneId = " + phoneId + " fdn enable is " + isEnableFDN);
if(phoneId < 0){
Log.e(TAG, "receive fdn phoneId < 0");
doServicehandler(MESSAGE_FINISH, startId, null);
return;
}
if(isEnableFDN){
//if fdn is activited, we need to delete sim phoneId contacts in database
synchronized (PREFS_SIM_STATE_LOCK[phoneId]) {
clearSyncState(mContext, phoneId);
//no need to find sim card is disabled
if (TelephonyManager.SIM_STATE_ABSENT == t.getSimState() || !checkSimEnabled(phoneId)) {
Log.d(TAG, whichSIM + " IS ABSENT or sim "+ phoneId + " is disabled or fdn is enable");
clearSimAction(startId, true, phoneId);
doServicehandler(MESSAGE_FINISH, startId, null);
}
}
}else{
//if fdn is disable
Log.d(TAG, "begin to import from sim card in fdn ");
airModeImport(startId, phoneId);
//checkSimPrefsAndDo(startId, phoneId);
}
}else if(action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)){
Log.d(TAG, "enter to airplan mode = " + intent.getBooleanExtra("state", false));
boolean airMode = intent.getBooleanExtra("state", false);
//deleteSimAction(startId, true);
if (airMode) {
Log.d(TAG, "airplan mode is turn on");
// deleteSimAction(startId, true);
clearSimAction(startId, true, phoneId);
doServicehandler(MESSAGE_FINISH, startId, null);
}else{
Log.d(TAG, "airplan mode is turn off");
setBootCompleteState(true);
synchronized (PREFS_SIM_STATE_LOCK[phoneId]) {
clearSyncState(mContext, phoneId);
if (TelephonyManager.SIM_STATE_ABSENT == t.getSimState() || !checkSimEnabled(phoneId)) {
Log.d(TAG, whichSIM + " IS ABSENT or sim "+ phoneId + " is disabled");
clearSimAction(startId, true, phoneId);
doServicehandler(MESSAGE_FINISH, startId, null);
}
}
String sim_oper_num = t.getSimOperator();
Log.d(TAG, whichSIM + " PROPERTY_ICC_OPERATOR_NUMERIC value is " + sim_oper_num);
if ((sim_oper_num != null && sim_oper_num.length() != 0)) {
importDualSimAction(startId, phoneId);
} else {
clearSimAction(startId, true, phoneId);
registerSimLoadedReceiver(startId);
}
}
}else if(action.equals("android.intent.action.SelectSimCard")){
Log.d(TAG, "Enable or disable sim card");
//once receive this message, you should know which sim card state is changed or all changed
phoneId = -1;
boolean sim1Changed = intent.getBooleanExtra("SIM1", false);
boolean sim2Changed = intent.getBooleanExtra("SIM2", false);
boolean isSim1Enabled = true;
boolean isSim2Enabled = true;
Log.d(TAG, "SIM1 changed : "+ sim1Changed + " SIM2 changed : "+ sim2Changed);
if(sim1Changed){
//if sim1 changed,get sim1 status
phoneId = 0;
isSim1Enabled = Settings.System.getInt(mContext.getContentResolver(),
PhoneFactory.getSetting(Settings.System.SIM_STANDBY, phoneId), 1) == 1;
Log.d(TAG, "isSim1Enable is ["+isSim1Enabled+"]");
if(isSim1Enabled){
//import from sim card
Log.d(TAG, "begin to import from sim1 in selectSimCard");
airModeImport(startId, phoneId);
}else{
//delete sim card contacts
Log.d(TAG, "begin to delete sim1 card contacts in selectSimCard");
//deleteSimAction(startId, true, phoneId);
clearSimAction(startId, true, phoneId);
//finishServiceSelf(startId);
}
}
if(sim2Changed){
//if sim1 changed,get sim1 status
phoneId = 1;
isSim2Enabled = Settings.System.getInt(mContext.getContentResolver(),
PhoneFactory.getSetting(Settings.System.SIM_STANDBY, phoneId), 1) == 1;
Log.d(TAG, "isSim2Enable is ["+isSim2Enabled+"]");
if(isSim2Enabled){
//import from sim card
Log.d(TAG, "begin to import from sim2 in selectSimCard");
airModeImport(startId, phoneId);
}else{
//delete sim card contacts
Log.d(TAG, "begin to delete sim2 card contacts in selectSimCard");
//deleteSimAction(startId, true, phoneId);
//deleteSimAction(startId, false, phoneId);
clearSimAction(startId, false, phoneId);
//finishServiceSelf(startId);
}
}
if(!isSim1Enabled || !isSim2Enabled){
Log.d(TAG, "sim1 or sim2 is disabled so finish this service");
finishServiceSelf(startId);
}
}
}// added for dual sim end
else {
if (action.equals(Intent.ACTION_BOOT_COMPLETED) || action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED) ||
action.equals(TelephonyIntents.ACTION_STK_REFRESH_SIM_CONTACTS)) {
clearSyncState();
Log.v(LOG_TAG, "action is " + action);
//deleteSimAction(startId, true);
isWorking = false;
String sim_oper_num = android.os.SystemProperties.get(PROPERTY_ICC_OPERATOR_NUMERIC);
if (sim_oper_num == null) {
Log.d(LOG_TAG, "PROPERTY_ICC_OPERATOR_NUMERIC value's null");
} else if (sim_oper_num.length() == 0) {
Log.d(LOG_TAG, "PROPERTY_ICC_OPERATOR_NUMERIC value's length is 0");
} else {
Log.d(LOG_TAG,"sim_oper_num = " + sim_oper_num);
}
boolean isAirplaneEnable = false;
if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
isAirplaneEnable = intent.getBooleanExtra("state", false);
}
//if sim card is absent, finish this service
if (TelephonyManager.SIM_STATE_ABSENT == ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).getSimState()
|| isAirplaneEnable) {
Log.d(LOG_TAG, "sim is not absent");
deleteSimAction(startId, true);
doServicehandler(MESSAGE_FINISH, startId, null);
}
if ((sim_oper_num != null && sim_oper_num.length() != 0)) {
Log.d(LOG_TAG, "PROPERTY_ICC_OPERATOR_NUMERIC is not null and start import sim action");
boolean isFdnEnable = CommonUtil.isFdnEnable(mContext);
if(!isFdnEnable && !isAirplaneEnable) {
importSimAction(startId);
} else {
finishServiceSelf(startId);
}
} else {
registerSimLoadedReceiver();
}
} else if (action.equals(Intent.ACTION_SHUTDOWN)) {
Log.v(LOG_TAG, "action is " + action);
//deleteSimAction(startId, false);
} else if (action
.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
String stateExtra = intent
.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
Log.d(LOG_TAG, "-------------stateExtra = "
+ stateExtra);
if (stateExtra.equals(IccCard.INTENT_VALUE_ICC_LOADED)) {
if (!isBootCompleted()) {
setBootCompleteState(true);
}
String sim_sync_state = getSyncState();
Log.d(LOG_TAG, "-------------sim_sync_state = " + sim_sync_state);
if (sim_sync_state.equals(PREFS_SIM_STATE_BOOT_DELETED)
|| sim_sync_state.equals(PREFS_SIM_STATE_IDLE)) {
importSimAction(msg.arg1);
} else if (sim_sync_state.equals(PREFS_SIM_STATE_IMPORTED)) {
querySimAction(msg.arg1);
}
} else {
finishServiceSelf(msg.arg1);
}
} else if ("android.intent.action.FDN_STATE_CHANGED0".equals(action)
|| "android.intent.action.FDN_STATE_CHANGED1".equals(action)) {
clearSyncState();
boolean fdnStatus = intent.getBooleanExtra("fdn_status", false);
Log.d(LOG_TAG, "action ACTION_FDN_STATE_CHANGED with fdn_status " + fdnStatus);
if (fdnStatus) {
deleteSimAction(startId, true);
doServicehandler(MESSAGE_FINISH, startId, null);
} else {
importSimAction(startId);
}
}
}
}
break;
case MESSAGE_FINISH: {
int serviceId = msg.arg1;
finishServiceSelf(serviceId);
break;
}
default:
break;
}
}
}
private boolean isAllSimAbsent(){
boolean isNoSimCard = false;
final TelephonyManager telManger1= (TelephonyManager) getSystemService(PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE, 0));
final TelephonyManager telManger2= (TelephonyManager) getSystemService(PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE, 1));
if(TelephonyManager.SIM_STATE_ABSENT == telManger1.getSimState() && TelephonyManager.SIM_STATE_ABSENT == telManger2.getSimState()){
Log.d(TAG, "there is no sim card");
isNoSimCard = true;
}
Log.d(TAG, "isAllSimAbsent = " + isNoSimCard);
return isNoSimCard;
}
private boolean checkSimEnabled(int phoneId){
//if sim card is disabled
boolean isSimEnabled = Settings.System.getInt(mContext.getContentResolver(),
PhoneFactory.getSetting(Settings.System.SIM_STANDBY, phoneId), 1) == 1;
//if fdn is disabled
final TelephonyManager telManger= (TelephonyManager) getSystemService(PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE,phoneId));
boolean isFdnEnabled = telManger.getIccFdnEnabled();
//if airplan mode is enabled
boolean isAirModeOn = false;
int airMode = Settings.System.getInt(getContentResolver(),Settings.System.AIRPLANE_MODE_ON, 0);
if(airMode == 1)
isAirModeOn = true;
Log.d(TAG, "[CheckSimEnabled] phoneId=" +phoneId + " isSimEnabled = " + isSimEnabled + " isFdnEnabled = " + isFdnEnabled + " isAirModeOn = " + isAirModeOn + " return result = " + (isSimEnabled && !isFdnEnabled && !isAirModeOn));
return isSimEnabled && !isFdnEnabled && !isAirModeOn;
}
private void airModeImport(int startId, int phoneId){
TelephonyManager t = (TelephonyManager) getSystemService(PhoneFactory
.getServiceName(Context.TELEPHONY_SERVICE, phoneId));
if(!isBootCompleted()){
setBootCompleteState(true);
}
synchronized (PREFS_SIM_STATE_LOCK[phoneId]) {
clearSyncState(mContext, phoneId);
if (TelephonyManager.SIM_STATE_ABSENT == t.getSimState()) {
Log.d(TAG, "SIM" + phoneId+ " IS ABSENT");
clearSimAction(startId, true, phoneId);
doServicehandler(MESSAGE_FINISH, startId, null);
}
}
String sim_oper_num = t.getSimOperator();
Log.d(TAG, "SIM" +phoneId+ " PROPERTY_ICC_OPERATOR_NUMERIC value is " + sim_oper_num);
if ((sim_oper_num != null && sim_oper_num.length() != 0)) {
importDualSimAction(startId, phoneId);
} else {
clearSimAction(startId, true, phoneId);
registerSimLoadedReceiver(startId);
}
return;
}
private static final int BOOT_IDLE = 0;
private static final int BOOT_COMPLETED = 1;
private static final String FILE_BOOT_COMPLETE = "/data/data/com.android.contacts/boot_flag";
private static final String BOOT_COMPLETE_SYSTEM_FLAG = "dev.bootcomplete";
private static Object BOOT_COMPLETED_FILE_LOCK = new Object();
public static boolean isBootCompleted() {
synchronized (BOOT_COMPLETED_FILE_LOCK) {
try {
FileReader file = new FileReader(FILE_BOOT_COMPLETE);
char[] buffer = new char[1024];
int len = file.read(buffer, 0, 1024);
int value = Integer.valueOf((new String(buffer, 0, len)).trim());
boolean result = (value == BOOT_COMPLETED);
Log.d(LOG_TAG, "-------------isBootCompleted = " + result);
return result;
} catch (Exception e) {
Log.e(LOG_TAG, "-------------isBootCompleted io fail");
return false;
}
}
}
/**
* @deprecated set flag for boot complete
*/
private void setBootCompleteState(boolean boot) {
synchronized (BOOT_COMPLETED_FILE_LOCK) {
File f = new File(FILE_BOOT_COMPLETE);
if (f.exists()) {
f.delete();
}
if (boot) {
try {
f.createNewFile();
} catch (IOException e) {
Log.d(LOG_TAG, "-------------createNewFile_failed - " + FILE_BOOT_COMPLETE);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
String stateTmp = "" + BOOT_COMPLETED;
bw.write(stateTmp);
bw.write("\r\n");
bw.close();
} catch (IOException e) {
Log.d(LOG_TAG, "-------------write_file_failed - " + FILE_BOOT_COMPLETE);
}
Log.d(LOG_TAG, "-------------setBootCompleteState");
}
}
}
public static final String BROADCAST_ACTION_REFRESH = "com.android.contacts.refresh.afterSync";
private void finishServiceSelf(int serviceId) {
if (isDualSim) {
String sim1_sync_state = getSyncState(mContext,0);
String sim2_sync_state = getSyncState(mContext,1);
boolean sim1_sync_over = PREFS_SIM_STATE_IMPORTED.equals(sim1_sync_state)
|| PREFS_SIM_STATE_BOOT_DELETED.equals(sim1_sync_state);
boolean sim2_sync_over = PREFS_SIM_STATE_IMPORTED.equals(sim2_sync_state)
|| PREFS_SIM_STATE_BOOT_DELETED.equals(sim2_sync_state);
if (sim1_sync_over && sim2_sync_over) {
Log.d(TAG, "service call stopSelf, serviceStartId = " + serviceId);
stopSelf();
}
//SyncSimContactsReceiver.finishStartingService(
// SyncSimContactsService.this, serviceId);
stopSelf();
Log.d(TAG, "finish service 22222222222222222222");
} else {
String sim_sync_state = getSyncState();
if (sim_sync_state.equals(PREFS_SIM_STATE_IMPORTED)
|| sim_sync_state.equals(PREFS_SIM_STATE_BOOT_DELETED)) {
Intent refresh = new Intent(BROADCAST_ACTION_REFRESH);
sendBroadcast(refresh);
Log.d(LOG_TAG, "-------sendBroadcast::refresh");
}
SyncSimContactsReceiver.finishStartingService(
SyncSimContactsService.this, serviceId);
}
}
public static boolean isWorking(){
return isWorking;
}
public final int[] NUMBERTYPE = {Phone.TYPE_MOBILE,Phone.TYPE_WORK,Phone.TYPE_OTHER};
// public final int[] NUMBERTYPE = {Phone.TYPE_HOME,Phone.TYPE_WORK,Phone.TYPE_OTHER};
public static final String[] EMAILPHONE = {"phonehome","phonemobile","homework","","","","phoneother","email"};
private static String[] splitString(String source){
String[] result = {"","",""};
if(source == null || source.equals("")){
return result;
}
Integer pos;
String strSource = source;
Integer times=0;
while ( (pos = strSource.indexOf(AdnRecord.ANR_SPLIT_FLG)) >=0 ) {
result[times] = strSource.substring(0, pos);
strSource = strSource.substring(pos+1);
times++;
}
if (strSource.length() > 0) {
result[times] = strSource;
}
return result;
}
private void checkSimPrefsAndDo(int serviceStartId,int phoneId) {
String sim_sync_state = getSyncState(mContext, phoneId);
Log.d(TAG, "[checkSimPrefsAndDo] sim_sync_state = " + sim_sync_state + " , phoneId = " + phoneId);
if (PREFS_SIM_STATE_BOOT_DELETED.equals(sim_sync_state)
|| PREFS_SIM_STATE_IDLE.equals(sim_sync_state)) {
importDualSimAction(serviceStartId, phoneId);
} else if (PREFS_SIM_STATE_IMPORTED.equals(sim_sync_state)) {
doServicehandler(MESSAGE_FINISH, serviceStartId, null);
} else if (PREFS_SIM_STATE_IMPORTING.equals(sim_sync_state)){
//do nothing
}
else {
waitForBootAndImport(serviceStartId, phoneId);
}
}
private String[] getSimContactRecordFromLocalCursor(Cursor c) {
Map<Integer,String> anrMap = new HashMap<Integer,String>();
int anrNum = 0;
String[] record = {"","","",""};
if (c != null) {
try {
c.moveToPosition(-1);
while (c.moveToNext()) {
if (Phone.CONTENT_ITEM_TYPE.equals(c.getString(2))) {
int numberIndex = c.getInt(1);
if (numberIndex == 0) {
record[1] = c.getString(0);
} else {
anrMap.put(numberIndex, c.getString(0));
anrNum = anrNum > numberIndex ? anrNum : numberIndex;
}
} else if (StructuredName.CONTENT_ITEM_TYPE.equals(c
.getString(2))) {
record[0] = c.getString(0);
if (record[0] == null) {
record[0] = "";
}
} else if (Email.CONTENT_ITEM_TYPE.equals(c
.getString(2))) {
record[3] = c.getString(0);
if (record[3] == null) {
record[3] = "";
}
}
}
} catch (Exception e) {
Log.e(TAG, "get information of sim contact fail", e);
} finally {
c.close();
c = null;
}
}
String anr = "";
for (int i = 1; i <= anrNum; i++) {
String anrNumber = anrMap.get(i);
anr += ":";
if (!TextUtils.isEmpty(anrNumber)) {
anr += anrNumber;
}
}
anr = anr.length() > 0 ? anr.substring(1) : "";
record[2] = anr;
return record;
}
}