blob: db09fc4e918608ed6110041e8b699b99ab23e4e4 [file] [log] [blame]
/*
* Copyright (c) 2015, Motorola Mobility LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of Motorola Mobility nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package com.android.service.ims.presence;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.format.TimeMigrationUtils;
import android.text.TextUtils;
import android.content.ComponentName;
import com.android.ims.ImsConfig;
import com.android.ims.ImsException;
import com.android.ims.ImsManager;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.ims.RcsException;
import com.android.ims.RcsManager;
import com.android.ims.RcsManager.ResultCode;
import com.android.ims.RcsPresence;
import com.android.ims.RcsPresence.PublishState;
import com.android.ims.RcsPresenceInfo;
import com.android.ims.internal.ContactNumberUtils;
import com.android.ims.internal.Logger;
import java.util.ArrayList;
import java.util.List;
public class CapabilityPolling {
private Logger logger = Logger.getLogger(this.getClass().getName());
private final Context mContext;
public static final String ACTION_PERIODICAL_DISCOVERY_ALARM =
"com.android.service.ims.presence.periodical_capability_discovery";
private PendingIntent mDiscoveryAlarmIntent = null;
public static final int ACTION_POLLING_NORMAL = 0;
public static final int ACTION_POLLING_NEW_CONTACTS = 1;
private long mCapabilityPollInterval = 604800000L;
private long mMinCapabilityPollInterval = 60480000L;
private long mCapabilityCacheExpiration = 7776000000L;
private long mNextPollingTimeStamp = 0L;
private final Object mScheduleSyncObj = new Object();
private boolean mInitialized = false;
private AlarmManager mAlarmManager = null;
private EABContactManager mEABContactManager = null;
private boolean mStackAvailable = false;
private int mPublished = -1;
private int mProvisioned = -1;
private HandlerThread mDiscoveryThread;
private Handler mDiscoveryHandler;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
logger.info("onReceive(), intent: " + intent +
", context: " + context);
String action = intent.getAction();
if (RcsManager.ACTION_RCS_SERVICE_AVAILABLE.equals(action)) {
enqueueServiceStatusChanged(true);
} else if (RcsManager.ACTION_RCS_SERVICE_UNAVAILABLE.equals(action)) {
enqueueServiceStatusChanged(false);
} else if (RcsManager.ACTION_RCS_SERVICE_DIED.equals(action)) {
logger.warn("No handler for this intent: " + action);
} else if (RcsPresence.ACTION_PUBLISH_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(
RcsPresence.EXTRA_PUBLISH_STATE,
RcsPresence.PublishState.PUBLISH_STATE_NOT_PUBLISHED);
enqueuePublishStateChanged(state);
} else if (ImsConfig.ACTION_IMS_CONFIG_CHANGED.equals(action)) {
int item = intent.getIntExtra(ImsConfig.EXTRA_CHANGED_ITEM, -1);
if ((ImsConfig.ConfigConstants.CAPABILITIES_POLL_INTERVAL == item) ||
(ImsConfig.ConfigConstants.CAPABILITIES_CACHE_EXPIRATION == item)) {
enqueueSettingsChanged();
} else if ((ImsConfig.ConfigConstants.VLT_SETTING_ENABLED == item) ||
(ImsConfig.ConfigConstants.LVC_SETTING_ENABLED == item) ||
(ImsConfig.ConfigConstants.EAB_SETTING_ENABLED == item)) {
enqueueProvisionStateChanged();
}
} else if(TelephonyIntents.ACTION_SIM_STATE_CHANGED.equalsIgnoreCase(action)) {
String stateExtra = intent.getStringExtra(
IccCardConstants.INTENT_KEY_ICC_STATE);
logger.print("SIM_STATE_CHANGED: " + stateExtra);
if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equalsIgnoreCase(stateExtra)) {
enqueueSimLoaded();
}
} else {
logger.debug("No interest in this intent: " + action);
}
}
};
private static CapabilityPolling sInstance = null;
public static synchronized CapabilityPolling getInstance(Context context) {
if ((sInstance == null) && (context != null)) {
sInstance = new CapabilityPolling(context);
}
return sInstance;
}
private CapabilityPolling(Context context) {
mContext = context;
ContactNumberUtils.getDefault().setContext(mContext);
PresencePreferences.getInstance().setContext(mContext);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mEABContactManager = new EABContactManager(mContext.getContentResolver(),
mContext.getPackageName());
setRcsTestMode(PresencePreferences.getInstance().getRcsTestMode());
logger.debug("CapabilityPolling is created.");
}
public void setRcsTestMode(boolean test) {
logger.setRcsTestMode(test);
PresencePreferences pref = PresencePreferences.getInstance();
if (pref != null) {
if (pref.getRcsTestMode() != test) {
pref.setRcsTestMode(test);
}
}
}
private void initialise() {
if (mInitialized) {
return;
}
PresenceSetting.init(mContext);
long capabilityPollInterval = PresenceSetting.getCapabilityPollInterval();
logger.print("getCapabilityPollInterval: " + capabilityPollInterval);
if (capabilityPollInterval == -1) {
capabilityPollInterval = mContext.getResources().getInteger(
R.integer.capability_poll_interval);
}
if (capabilityPollInterval < 10) {
capabilityPollInterval = 10;
}
long capabilityCacheExpiration = PresenceSetting.getCapabilityCacheExpiration();
logger.print("getCapabilityCacheExpiration: " + capabilityCacheExpiration);
if (capabilityCacheExpiration == -1) {
capabilityCacheExpiration = mContext.getResources().getInteger(
R.integer.capability_cache_expiration);
}
if (capabilityCacheExpiration < 10) {
capabilityCacheExpiration = 10;
}
int publishTimer = PresenceSetting.getPublishTimer();
logger.print("getPublishTimer: " + publishTimer);
int publishTimerExtended = PresenceSetting.getPublishTimerExtended();
logger.print("getPublishTimerExtended: " + publishTimerExtended);
int maxEntriesInRequest = PresenceSetting.getMaxNumberOfEntriesInRequestContainedList();
logger.print("getMaxNumberOfEntriesInRequestContainedList: " + maxEntriesInRequest);
if ((capabilityPollInterval <= 30 * 60) || // default: 7 days
(capabilityCacheExpiration <= 60 * 60) || // default: 90 days
(maxEntriesInRequest <= 20) || // default: 100
(publishTimer <= 10 * 60) || // default: 20 minutes
(publishTimerExtended <= 20 * 60)) { // default: 1 day
setRcsTestMode(true);
}
if (capabilityCacheExpiration < capabilityPollInterval) {
capabilityPollInterval = capabilityCacheExpiration;
}
mCapabilityPollInterval = capabilityPollInterval * 1000;
mMinCapabilityPollInterval = mCapabilityPollInterval / 10;
logger.info("mCapabilityPollInterval: " + mCapabilityPollInterval +
", mMinCapabilityPollInterval: " + mMinCapabilityPollInterval);
mCapabilityCacheExpiration = capabilityCacheExpiration * 1000;
logger.info("mCapabilityCacheExpiration: " + mCapabilityCacheExpiration);
mInitialized = true;
}
public void start() {
mDiscoveryThread = new HandlerThread("Presence-DiscoveryThread");
mDiscoveryThread.start();
mDiscoveryHandler = new Handler(mDiscoveryThread.getLooper(), mDiscoveryCallback);
registerForBroadcasts();
if (isPollingReady()) {
schedulePolling(5 * 1000, ACTION_POLLING_NORMAL);
}
}
public void stop() {
cancelDiscoveryAlarm();
clearPollingTasks();
mContext.unregisterReceiver(mReceiver);
mDiscoveryThread.quit();
}
private void registerForBroadcasts() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(RcsManager.ACTION_RCS_SERVICE_AVAILABLE);
intentFilter.addAction(RcsManager.ACTION_RCS_SERVICE_UNAVAILABLE);
intentFilter.addAction(RcsManager.ACTION_RCS_SERVICE_DIED);
intentFilter.addAction(RcsPresence.ACTION_PUBLISH_STATE_CHANGED);
intentFilter.addAction(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
}
private boolean isPollingReady() {
if (mPublished == -1) {
RcsManager rcsManager = RcsManager.getInstance(mContext, 0);
if (rcsManager != null) {
mStackAvailable = rcsManager.isRcsServiceAvailable();
logger.print("isPollingReady, mStackAvailable: " + mStackAvailable);
try {
RcsPresence rcsPresence = rcsManager.getRcsPresenceInterface();
if (rcsPresence != null) {
int state = rcsPresence.getPublishState();
mPublished = (PublishState.PUBLISH_STATE_200_OK == state) ? 1 : 0;
logger.print("isPollingReady, mPublished: " + mPublished);
}
} catch (RcsException ex) {
logger.warn("RcsPresence.getPublishState failed, exception: " + ex);
mPublished = -1;
}
}
}
if (mProvisioned == -1) {
ImsManager imsManager = ImsManager.getInstance(mContext,
SubscriptionManager.getDefaultVoicePhoneId());
if (imsManager != null) {
try {
ImsConfig imsConfig = imsManager.getConfigInterface();
if (imsConfig != null) {
mProvisioned = imsConfig.getProvisionedValue(
ImsConfig.ConfigConstants.EAB_SETTING_ENABLED);
logger.print("isPollingReady, mProvisioned: " + mProvisioned);
}
} catch (ImsException ex) {
logger.warn("ImsConfig.getEabProvisioned failed, exception: " + ex);
mProvisioned = -1;
}
}
}
logger.print("isPollingReady, mProvisioned: " + mProvisioned +
", mStackAvailable: " + mStackAvailable + ", mPublished: " + mPublished);
return mStackAvailable && (mPublished == 1) && (mProvisioned == 1);
}
private void serviceStatusChanged(boolean enabled) {
logger.print("Enter serviceStatusChanged: " + enabled);
mStackAvailable = enabled;
if (isPollingReady()) {
schedulePolling(0, ACTION_POLLING_NORMAL);
} else {
cancelDiscoveryAlarm();
clearPollingTasks();
}
}
private void publishStateChanged(int state) {
logger.print("Enter publishStateChanged: " + state);
mPublished = (PublishState.PUBLISH_STATE_200_OK == state) ? 1 : 0;
if (mPublished == 1) {
PresencePreferences pref = PresencePreferences.getInstance();
if (pref != null) {
String mdn_old = pref.getLine1Number();
String subscriberId_old = pref.getSubscriberId();
if (TextUtils.isEmpty(mdn_old) && TextUtils.isEmpty(subscriberId_old)) {
String mdn = getLine1Number();
pref.setLine1Number(mdn);
String subscriberId = getSubscriberId();
pref.setSubscriberId(subscriberId);
}
}
}
if (isPollingReady()) {
schedulePolling(0, ACTION_POLLING_NORMAL);
} else {
cancelDiscoveryAlarm();
clearPollingTasks();
}
}
private void provisionStateChanged() {
ImsManager imsManager = ImsManager.getInstance(mContext,
SubscriptionManager.getDefaultVoicePhoneId());
if (imsManager == null) {
return;
}
try {
ImsConfig imsConfig = imsManager.getConfigInterface();
if (imsConfig == null) {
return;
}
boolean volteProvision = imsConfig.getProvisionedValue(
ImsConfig.ConfigConstants.VLT_SETTING_ENABLED)
== ImsConfig.FeatureValueConstants.ON;
boolean vtProvision = imsConfig.getProvisionedValue(
ImsConfig.ConfigConstants.LVC_SETTING_ENABLED)
== ImsConfig.FeatureValueConstants.ON;
boolean eabProvision = imsConfig.getProvisionedValue(
ImsConfig.ConfigConstants.EAB_SETTING_ENABLED)
== ImsConfig.FeatureValueConstants.ON;
logger.print("Provision state changed, VolteProvision: "
+ volteProvision + ", vtProvision: " + vtProvision
+ ", eabProvision: " + eabProvision);
if ((mProvisioned == 1) && !eabProvision) {
logger.print("EAB Provision is disabled, clear all capabilities!");
if (mEABContactManager != null) {
mEABContactManager.updateAllCapabilityToUnknown();
}
}
mProvisioned = eabProvision ? 1 : 0;
} catch (ImsException ex) {
logger.warn("ImsConfig.getEabProvisioned failed, exception: " + ex);
mProvisioned = -1;
return;
}
if (isPollingReady()) {
schedulePolling(0, ACTION_POLLING_NORMAL);
} else {
cancelDiscoveryAlarm();
clearPollingTasks();
}
}
private void settingsChanged() {
logger.print("Enter settingsChanged.");
cancelDiscoveryAlarm();
clearPollingTasks();
mInitialized = false;
if (isPollingReady()) {
schedulePolling(0, ACTION_POLLING_NORMAL);
}
}
private void newContactAdded(String number) {
if (TextUtils.isEmpty(number)) {
return;
}
EABContactManager.Request request = new EABContactManager.Request(number)
.setLastUpdatedTimeStamp(0);
int result = mEABContactManager.update(request);
if (result <= 0) {
return;
}
if (isPollingReady()) {
schedulePolling(5 * 1000, ACTION_POLLING_NEW_CONTACTS);
}
}
private void verifyPollingResult(int counts) {
if (isPollingReady()) {
PresencePreferences pref = PresencePreferences.getInstance();
if ((pref != null) && pref.getRcsTestMode()) {
counts = 1;
}
long lm = (long)(1 << (counts - 1));
schedulePolling(30 * 1000 * lm, ACTION_POLLING_NORMAL);
}
}
public synchronized void schedulePolling(long msec, int type) {
logger.print("schedulePolling msec=" + msec + " type=" + type);
if (!isPollingReady()) {
logger.debug("Cancel the polling since the network is not ready");
return;
}
if (type == ACTION_POLLING_NEW_CONTACTS) {
cancelDiscoveryAlarm();
}
if (mNextPollingTimeStamp != 0L) {
long scheduled = mNextPollingTimeStamp - System.currentTimeMillis();
if ((scheduled > 0) && (scheduled < msec)) {
logger.print("There has been a discovery scheduled at "
+ getTimeString(mNextPollingTimeStamp));
return;
}
}
long nextTime = System.currentTimeMillis() + msec;
logger.print("A new discovery needs to be started in " +
(msec / 1000) + " seconds at "
+ getTimeString(nextTime));
cancelDiscoveryAlarm();
if (msec <= 0) {
enqueueDiscovery(type);
return;
}
Intent intent = new Intent(ACTION_PERIODICAL_DISCOVERY_ALARM);
intent.setClass(mContext, AlarmBroadcastReceiver.class);
intent.putExtra("pollingType", type);
mDiscoveryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + msec, mDiscoveryAlarmIntent);
mNextPollingTimeStamp = nextTime;
}
private synchronized void doCapabilityDiscovery(int type) {
logger.print("doCapabilityDiscovery type=" + type);
if (!isPollingReady()) {
logger.debug("doCapabilityDiscovery isPollingReady=false");
return;
}
long delay = 0;
List<Contacts.Item> list = null;
initialise();
mNextPollingTimeStamp = 0L;
Cursor cursor = null;
EABContactManager.Query baseQuery = new EABContactManager.Query()
.orderBy(EABContactManager.COLUMN_LAST_UPDATED_TIMESTAMP,
EABContactManager.Query.ORDER_ASCENDING);
try {
logger.debug("doCapabilityDiscovery.query:\n" + baseQuery);
cursor = mEABContactManager.query(baseQuery);
if (cursor == null) {
logger.print("Cursor is null, there is no database found.");
return;
}
int count = cursor.getCount();
if (count == 0) {
logger.print("Cursor.getCount() is 0, there is no items found in db.");
return;
}
list = new ArrayList<Contacts.Item>();
list.clear();
long current = System.currentTimeMillis();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long id = cursor.getLong(cursor.getColumnIndex(Contacts.Impl._ID));
long last = cursor.getLong(cursor.getColumnIndex(
Contacts.Impl.CONTACT_LAST_UPDATED_TIMESTAMP));
Contacts.Item item = new Contacts.Item(id);
item.setLastUpdateTime(last);
item.setNumber(cursor.getString(
cursor.getColumnIndex(Contacts.Impl.CONTACT_NUMBER)));
item.setName(cursor.getString(
cursor.getColumnIndex(Contacts.Impl.CONTACT_NAME)));
item.setVolteTimestamp(cursor.getLong(
cursor.getColumnIndex(Contacts.Impl.VOLTE_CALL_CAPABILITY_TIMESTAMP)));
item.setVideoTimestamp(cursor.getLong(
cursor.getColumnIndex(Contacts.Impl.VIDEO_CALL_CAPABILITY_TIMESTAMP)));
if ((current - last < 0) ||
(current - last >= mCapabilityPollInterval - mMinCapabilityPollInterval)) {
logger.print("This item will be updated:\n"
+ item);
if (item.isValid()) {
list.add(item);
}
} else {
logger.print("The first item which will be updated next time:\n" + item);
delay = randomCapabilityPollInterval() - (current - last);
if (delay > 0) {
break;
}
}
}
} catch (Exception ex) {
logger.warn("Exception in doCapabilityDiscovery: " + ex);
if (delay <= 0) {
delay = 5 * 60 * 1000;
}
} finally {
if (cursor != null) {
cursor.close();
}
}
if (delay <= 0) {
delay = randomCapabilityPollInterval();
}
logger.print("Polling delay: " + delay);
schedulePolling(delay, ACTION_POLLING_NORMAL);
updateObsoleteItems();
if ((list != null) && (list.size() > 0)) {
PollingsQueue queue = PollingsQueue.getInstance(mContext);
if (queue != null) {
queue.setCapabilityPolling(this);
queue.add(type, list);
}
}
}
private long randomCapabilityPollInterval() {
double random = Math.random() * 0.2 + 0.9;
logger.print("The random for this time polling is: " + random);
random = random * mCapabilityPollInterval;
return (long)random;
}
private void updateObsoleteItems() {
long current = System.currentTimeMillis();
long last = current - mCapabilityCacheExpiration;
long last3year = current - 3 * 365 * 24 * 3600000L;
StringBuilder sb = new StringBuilder();
sb.append("((");
sb.append(Contacts.Impl.VOLTE_CALL_CAPABILITY_TIMESTAMP + "<='" + last + "'");
sb.append(" OR ");
sb.append(Contacts.Impl.VIDEO_CALL_CAPABILITY_TIMESTAMP + "<='" + last + "'");
sb.append(") AND ");
sb.append(Contacts.Impl.CONTACT_LAST_UPDATED_TIMESTAMP + ">='" + last3year + "'");
sb.append(")");
EABContactManager.Query baseQuery = new EABContactManager.Query()
.setFilterByTime(sb.toString())
.orderBy(EABContactManager.COLUMN_ID,
EABContactManager.Query.ORDER_ASCENDING);
Cursor cursor = null;
List<Contacts.Item> list = null;
try {
logger.debug("updateObsoleteItems.query:\n" + baseQuery);
cursor = mEABContactManager.query(baseQuery);
if (cursor == null) {
logger.print("Cursor is null, there is no database found.");
return;
}
int count = cursor.getCount();
if (count == 0) {
logger.print("Cursor.getCount() is 0, there is no obsolete items found.");
return;
}
list = new ArrayList<Contacts.Item>();
list.clear();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long id = cursor.getLong(cursor.getColumnIndex(Contacts.Impl._ID));
Contacts.Item item = new Contacts.Item(id);
item.setLastUpdateTime(cursor.getLong(
cursor.getColumnIndex(Contacts.Impl.CONTACT_LAST_UPDATED_TIMESTAMP)));
item.setNumber(cursor.getString(
cursor.getColumnIndex(Contacts.Impl.CONTACT_NUMBER)));
item.setName(cursor.getString(
cursor.getColumnIndex(Contacts.Impl.CONTACT_NAME)));
item.setVolteTimestamp(cursor.getLong(
cursor.getColumnIndex(Contacts.Impl.VOLTE_CALL_CAPABILITY_TIMESTAMP)));
item.setVideoTimestamp(cursor.getLong(
cursor.getColumnIndex(Contacts.Impl.VIDEO_CALL_CAPABILITY_TIMESTAMP)));
logger.print("updateObsoleteItems, the obsolete item:\n" + item);
if ((item.lastUpdateTime() > 0) && item.isValid()) {
list.add(item);
}
}
} catch (Exception ex) {
logger.warn("Exception in updateObsoleteItems: " + ex);
} finally {
if (cursor != null) {
cursor.close();
}
}
if ((list == null) || (list.size() <= 0)) {
return;
}
for (Contacts.Item item : list) {
EABContactManager.Request request = new EABContactManager.Request(item.id());
if (item.volteTimestamp() <= last) {
request.setVolteCallCapability(false);
request.setVolteCallCapabilityTimeStamp(current);
}
if (item.videoTimestamp() <= last) {
request.setVideoCallCapability(false);
request.setVideoCallCapabilityTimeStamp(current);
}
int result = mEABContactManager.update(request);
if (result <= 0) {
logger.print("Failed to update this request: " + request);
}
}
}
private void cancelDiscoveryAlarm() {
if (mDiscoveryAlarmIntent != null) {
mAlarmManager.cancel(mDiscoveryAlarmIntent);
mDiscoveryAlarmIntent = null;
mNextPollingTimeStamp = 0L;
}
}
private void clearPollingTasks() {
PollingsQueue queue = PollingsQueue.getInstance(null);
if (queue != null) {
queue.clear();
}
}
private String getTimeString(long time) {
if (time <= 0) {
time = System.currentTimeMillis();
}
String timeString = TimeMigrationUtils.formatMillisWithFixedFormat(time);
return String.format("%s.%s", timeString, time % 1000);
}
private static final int MSG_CHECK_DISCOVERY = 1;
private static final int MSG_NEW_CONTACT_ADDED = 2;
private static final int MSG_SERVICE_STATUS_CHANGED = 3;
private static final int MSG_SETTINGS_CHANGED = 4;
private static final int MSG_PUBLISH_STATE_CHANGED = 5;
private static final int MSG_SIM_LOADED = 6;
private static final int MSG_PROVISION_STATE_CHANGED = 7;
private static final int MSG_VERIFY_POLLING_RESULT = 8;
public void enqueueDiscovery(int type) {
mDiscoveryHandler.removeMessages(MSG_CHECK_DISCOVERY);
mDiscoveryHandler.obtainMessage(MSG_CHECK_DISCOVERY, type, -1).sendToTarget();
}
public void enqueueNewContact(String number) {
mDiscoveryHandler.obtainMessage(MSG_NEW_CONTACT_ADDED, number).sendToTarget();
}
private void enqueueServiceStatusChanged(boolean enabled) {
mDiscoveryHandler.removeMessages(MSG_SERVICE_STATUS_CHANGED);
mDiscoveryHandler.obtainMessage(MSG_SERVICE_STATUS_CHANGED,
enabled ? 1 : 0, -1).sendToTarget();
}
private void enqueuePublishStateChanged(int state) {
mDiscoveryHandler.removeMessages(MSG_PUBLISH_STATE_CHANGED);
mDiscoveryHandler.obtainMessage(MSG_PUBLISH_STATE_CHANGED,
state, -1).sendToTarget();
}
public void enqueueSettingsChanged() {
mDiscoveryHandler.removeMessages(MSG_SETTINGS_CHANGED);
mDiscoveryHandler.obtainMessage(MSG_SETTINGS_CHANGED).sendToTarget();
}
private void enqueueSimLoaded() {
mDiscoveryHandler.removeMessages(MSG_SIM_LOADED);
mDiscoveryHandler.obtainMessage(MSG_SIM_LOADED).sendToTarget();
}
private void enqueueProvisionStateChanged() {
mDiscoveryHandler.removeMessages(MSG_PROVISION_STATE_CHANGED);
mDiscoveryHandler.obtainMessage(MSG_PROVISION_STATE_CHANGED).sendToTarget();
}
public void enqueueVerifyPollingResult(int counts) {
mDiscoveryHandler.removeMessages(MSG_VERIFY_POLLING_RESULT);
mDiscoveryHandler.obtainMessage(MSG_VERIFY_POLLING_RESULT, counts, -1).sendToTarget();
}
private Handler.Callback mDiscoveryCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
if (msg.what == MSG_CHECK_DISCOVERY) {
doCapabilityDiscovery(msg.arg1);
} else if (msg.what == MSG_NEW_CONTACT_ADDED) {
newContactAdded((String)msg.obj);
} else if (msg.what == MSG_SERVICE_STATUS_CHANGED) {
serviceStatusChanged(msg.arg1 == 1);
} else if (msg.what == MSG_PUBLISH_STATE_CHANGED) {
publishStateChanged(msg.arg1);
} else if (msg.what == MSG_SETTINGS_CHANGED) {
settingsChanged();
} else if(msg.what == MSG_SIM_LOADED) {
onSimLoaded();
} else if(msg.what == MSG_PROVISION_STATE_CHANGED) {
provisionStateChanged();
} else if(msg.what == MSG_VERIFY_POLLING_RESULT) {
verifyPollingResult(msg.arg1);
} else {
}
return true;
}
};
private void onSimLoaded() {
PresencePreferences pref = PresencePreferences.getInstance();
if (pref == null) {
return;
}
String mdn_old = pref.getLine1Number();
if (TextUtils.isEmpty(mdn_old)) {
return;
}
String subscriberId_old = pref.getSubscriberId();
if (TextUtils.isEmpty(subscriberId_old)) {
return;
}
String mdn = getLine1Number();
String subscriberId = getSubscriberId();
if (TextUtils.isEmpty(mdn) && TextUtils.isEmpty(subscriberId)) {
return;
}
boolean mdnMatched = false;
if (TextUtils.isEmpty(mdn) || PhoneNumberUtils.compare(mdn_old, mdn)) {
mdnMatched = true;
}
boolean subscriberIdMatched = false;
if (TextUtils.isEmpty(subscriberId) || subscriberId.equals(subscriberId_old)) {
subscriberIdMatched = true;
}
if (mdnMatched && subscriberIdMatched) {
return;
}
logger.print("Remove presence cache for Sim card changed!");
pref.setLine1Number("");
pref.setSubscriberId("");
if (mEABContactManager != null) {
mEABContactManager.updateAllCapabilityToUnknown();
}
}
private static final int DEFAULT_SUBSCRIPTION = 1;
private String getLine1Number() {
if (mContext == null) {
return null;
}
TelephonyManager telephony = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (telephony == null) {
return null;
}
String mdn = null;
if (TelephonyManager.getDefault().isMultiSimEnabled()) {
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
subId = DEFAULT_SUBSCRIPTION;
}
mdn = telephony.getLine1Number(subId);
} else {
mdn = telephony.getLine1Number();
}
if ((mdn == null) || (mdn.length() == 0) || mdn.startsWith("00000")) {
return null;
}
logger.print("getLine1Number: " + mdn);
return mdn;
}
private String getSubscriberId() {
if (mContext == null) {
return null;
}
TelephonyManager telephony = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (telephony == null) {
return null;
}
String subscriberId = null;
if (TelephonyManager.getDefault().isMultiSimEnabled()) {
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
subId = DEFAULT_SUBSCRIPTION;
}
subscriberId = telephony.getSubscriberId(subId);
} else {
subscriberId = telephony.getSubscriberId();
}
logger.print("getSubscriberId: " + subscriberId);
return subscriberId;
}
}