1 /* 2 * Copyright (c) 2015, Motorola Mobility LLC 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * - Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * - Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * - Neither the name of Motorola Mobility nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 * DAMAGE. 27 */ 28 29 package com.android.service.ims; 30 31 import java.util.List; 32 import java.util.concurrent.Semaphore; 33 import java.util.concurrent.TimeUnit; 34 35 import android.content.BroadcastReceiver; 36 import android.content.ComponentName; 37 import android.content.pm.PackageManager; 38 import android.content.pm.ResolveInfo; 39 import android.content.pm.ServiceInfo; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.app.PendingIntent; 43 import android.content.IntentFilter; 44 import android.content.ServiceConnection; 45 import android.os.Handler; 46 import android.os.HandlerThread; 47 import android.os.IBinder; 48 import android.os.Looper; 49 import android.os.Message; 50 import android.os.RemoteException; 51 import android.telephony.TelephonyManager; 52 import android.app.AlarmManager; 53 import android.os.SystemClock; 54 import android.os.SystemProperties; 55 import com.android.ims.ImsConfig; 56 import com.android.ims.ImsManager; 57 import com.android.ims.ImsException; 58 import android.telephony.SubscriptionManager; 59 60 import com.android.ims.IRcsPresenceListener; 61 import com.android.ims.RcsPresence; 62 import com.android.ims.RcsManager.ResultCode; 63 import com.android.ims.RcsPresence.PublishState; 64 65 import com.android.ims.internal.Logger; 66 import com.android.ims.internal.ContactNumberUtils; 67 import com.android.service.ims.presence.PresencePublication; 68 import com.android.service.ims.R; 69 70 import com.android.ims.internal.uce.presence.IPresenceService; 71 import com.android.ims.internal.uce.presence.PresCapInfo; 72 import com.android.ims.internal.uce.common.CapInfo; 73 import com.android.ims.internal.uce.uceservice.IUceService; 74 import com.android.ims.internal.uce.uceservice.ImsUceManager; 75 import com.android.ims.internal.uce.common.UceLong; 76 import com.android.ims.internal.uce.common.StatusCode; 77 78 import com.android.ims.IRcsPresenceListener; 79 import com.android.ims.RcsPresenceInfo; 80 81 import com.android.service.ims.presence.StackListener; 82 import com.android.service.ims.presence.PresenceInfoParser; 83 import com.android.service.ims.presence.AlarmBroadcastReceiver; 84 85 public class RcsStackAdaptor{ 86 private static final boolean DEBUG = true; 87 88 private static final String PERSIST_SERVICE_NAME = 89 "com.android.service.ims.presence.PersistService"; 90 private static final String PERSIST_SERVICE_PACKAGE = "com.android.service.ims.presence"; 91 92 // The logger 93 private Logger logger = Logger.getLogger(this.getClass().getName()); 94 95 private static final int PRESENCE_INIT_IMS_UCE_SERVICE = 1; 96 97 private Context mContext = null; 98 99 // true when the stack presence service got available. (Called IQPresListener_ServiceAvailable) 100 private volatile boolean mImsEnableState = false; 101 102 // provision status can be set by both subscribe and pubilish 103 // for unprovisioned for 403 or 404 104 private volatile int mPublishingState = PublishState.PUBLISH_STATE_NOT_PUBLISHED; 105 106 // It is initializing the stack presence service. 107 private volatile boolean mIsIniting = false; 108 109 // The time which the stack presence service got initialized. 110 private volatile long mLastInitSubService = -1; //last time which inited the sub service 111 112 // Used for synchronizing 113 private final Object mSyncObj = new Object(); 114 115 // We need wait RCS stack become unavailable before close RCS service. 116 static private boolean sInPowerDown = false; 117 118 // This could happen when the stack first launch or modem panic. 119 private static final int PRESENCE_INIT_TYPE_RCS_SERVICE_AVAILABLE =1; 120 121 // The initialization was triggered by retry. 122 private static final int PRESENCE_INIT_TYPE_RETRY = 2; 123 124 // The initialization was triggered by retry. 125 private static final int PRESENCE_INIT_TYPE_IMS_REGISTERED = 3; 126 127 // The maximum retry count for initializing the stack service. 128 private static final int MAX_RETRY_COUNT = 6;//Maximum time is 64s 129 isImsEnableState()130 public boolean isImsEnableState() { 131 synchronized (mSyncObj) { 132 return mImsEnableState; 133 } 134 } 135 setImsEnableState(boolean imsEnableState)136 public void setImsEnableState(boolean imsEnableState) { 137 synchronized (mSyncObj) { 138 logger.debug("imsEnableState=" + imsEnableState); 139 mImsEnableState = imsEnableState; 140 } 141 } 142 143 // The UCE manager for RCS stack. 144 private ImsUceManager mImsUceManager = null; 145 146 // The stack RCS Service instance. 147 private IUceService mStackService = null; 148 149 // The stack presence service 150 private IPresenceService mStackPresService = null; 151 152 // The stack Presence Service handle. 153 private int mStackPresenceServiceHandle; 154 155 // The listener which listen to the response for presence service. 156 private StackListener mListenerHandler = null; 157 158 // The handler of the listener. 159 private UceLong mListenerHandle = new UceLong(); 160 161 // The singleton. 162 private static RcsStackAdaptor sInstance = null; 163 164 // Constructor RcsStackAdaptor(Context context)165 private RcsStackAdaptor(Context context) { 166 mContext = context; 167 168 init(); 169 } 170 getInstance(Context context)171 public static synchronized RcsStackAdaptor getInstance(Context context) { 172 if ((sInstance == null) && (context != null)) { 173 sInstance = new RcsStackAdaptor(context); 174 } 175 176 return sInstance; 177 } 178 179 private Handler mMsgHandler = new Handler() { 180 @Override 181 public void handleMessage(Message msg) { 182 super.handleMessage(msg); 183 184 logger.debug( "Thread=" + Thread.currentThread().getName() + " received " 185 + msg); 186 if(msg == null){ 187 logger.error("msg=null"); 188 return; 189 } 190 191 switch (msg.what) { 192 case PRESENCE_INIT_IMS_UCE_SERVICE: 193 logger.debug("handleMessage msg=PRESENCE_INIT_IMS_UCE_SERVICE" ); 194 doInitImsUceService(); 195 break; 196 197 default: 198 logger.debug("handleMessage unknown msg=" + msg.what); 199 } 200 } 201 }; 202 getListener()203 public StackListener getListener(){ 204 return mListenerHandler; 205 } 206 checkStackAndPublish()207 public int checkStackAndPublish(){ 208 if (!RcsSettingUtils.getCapabilityDiscoveryEnabled(mContext)) { 209 logger.error("getCapabilityDiscoveryEnabled = false"); 210 return ResultCode.ERROR_SERVICE_NOT_ENABLED; 211 } 212 213 int ret = checkStackStatus(); 214 if (ret != ResultCode.SUCCESS) { 215 logger.error("checkStackAndPublish ret=" + ret); 216 return ret; 217 } 218 219 if (!isPublished()) { 220 logger.error( 221 "checkStackAndPublish ERROR_SERVICE_NOT_PUBLISHED"); 222 return ResultCode.ERROR_SERVICE_NOT_PUBLISHED; 223 } 224 225 return ResultCode.SUCCESS; 226 } 227 isPublished()228 private boolean isPublished(){ 229 if(getPublishState() != PublishState.PUBLISH_STATE_200_OK){ 230 logger.error("Didnt' publish properly"); 231 return false; 232 } 233 234 return true; 235 } 236 setPublishState(int publishState)237 public void setPublishState(int publishState) { 238 synchronized (mSyncObj) { 239 logger.print("mPublishingState=" + mPublishingState + " publishState=" + publishState); 240 if (mPublishingState != publishState) { 241 // save it for recovery when PresenceService crash. 242 SystemProperties.set("rcs.publish.status", 243 String.valueOf(publishState)); 244 245 Intent publishIntent = new Intent(RcsPresence.ACTION_PUBLISH_STATE_CHANGED); 246 publishIntent.putExtra(RcsPresence.EXTRA_PUBLISH_STATE, publishState); 247 // Start PersistService and broadcast to other receivers that are listening 248 // dynamically. 249 mContext.sendStickyBroadcast(publishIntent); 250 launchPersistService(publishIntent); 251 } 252 253 mPublishingState = publishState; 254 } 255 } 256 getPublishState()257 public int getPublishState(){ 258 synchronized (mSyncObj) { 259 return mPublishingState; 260 } 261 } 262 checkStackStatus()263 public int checkStackStatus(){ 264 synchronized (mSyncObj) { 265 if (!RcsSettingUtils.isEabProvisioned(mContext)) { 266 logger.error("Didn't get EAB provisioned by DM"); 267 return ResultCode.ERROR_SERVICE_NOT_ENABLED; 268 } 269 270 // Don't send request to RCS stack when it is under powering off. 271 // RCS stack is sending UNPUBLISH. It could get race PUBLISH trigger under the case. 272 if (sInPowerDown) { 273 logger.error("checkStackStatus: under powering off"); 274 return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 275 } 276 277 if (mStackService == null) { 278 logger.error("checkStackStatus: mStackService == null"); 279 return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 280 } 281 282 if (mStackPresService == null) { 283 logger.error("Didn't init sub rcs service."); 284 return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 285 } 286 287 if (!mImsEnableState) { 288 logger.error("mImsEnableState = false"); 289 return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 290 } 291 } 292 293 return ResultCode.SUCCESS; 294 } 295 requestCapability(String[] formatedContacts, int taskId)296 public int requestCapability(String[] formatedContacts, int taskId){ 297 logger.print("requestCapability formatedContacts=" + formatedContacts); 298 299 int ret = ResultCode.SUCCESS; 300 try { 301 synchronized (mSyncObj) { 302 StatusCode retCode; 303 if (formatedContacts.length == 1) { 304 retCode = mStackPresService.getContactCap( 305 mStackPresenceServiceHandle, formatedContacts[0], taskId); 306 } else { 307 retCode = mStackPresService.getContactListCap( 308 mStackPresenceServiceHandle, formatedContacts, taskId); 309 } 310 311 logger.print("GetContactListCap retCode=" + retCode); 312 313 ret = RcsUtils.statusCodeToResultCode(retCode.getStatusCode()); 314 } 315 316 logger.debug("requestCapability ret=" + ret); 317 }catch(Exception e){ 318 logger.error("requestCapability exception", e); 319 ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 320 } 321 322 return ret; 323 } 324 requestAvailability(String formatedContact, int taskId)325 public int requestAvailability(String formatedContact, int taskId){ 326 logger.debug("requestAvailability ..."); 327 328 int ret = ResultCode.SUCCESS; 329 try{ 330 synchronized (mSyncObj) { 331 StatusCode retCode = mStackPresService.getContactCap( 332 mStackPresenceServiceHandle, formatedContact, taskId); 333 logger.print("getContactCap retCode=" + retCode); 334 335 ret = RcsUtils.statusCodeToResultCode(retCode.getStatusCode()); 336 } 337 logger.debug("requestAvailability ret=" + ret); 338 }catch(Exception e){ 339 logger.error("requestAvailability exception", e); 340 ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 341 } 342 343 return ret; 344 } 345 requestPublication(RcsPresenceInfo presenceInfo, IRcsPresenceListener listener)346 public int requestPublication(RcsPresenceInfo presenceInfo, IRcsPresenceListener listener) { 347 logger.debug("requestPublication ..."); 348 349 // Don't use checkStackAndPublish() 350 // since it will check publish status which in dead loop. 351 int ret = checkStackStatus(); 352 if(ret != ResultCode.SUCCESS){ 353 logger.error("requestPublication ret=" + ret); 354 return ret; 355 } 356 357 TelephonyManager teleMgr = (TelephonyManager) mContext.getSystemService( 358 Context.TELEPHONY_SERVICE); 359 if(teleMgr == null){ 360 logger.error("teleMgr = null"); 361 return PresencePublication.PUBLISH_GENIRIC_FAILURE; 362 } 363 364 String myNumUri = null; 365 String myDomain = teleMgr.getIsimDomain(); 366 logger.debug("myDomain=" + myDomain); 367 if(myDomain != null && myDomain.length() !=0){ 368 String[] impu = teleMgr.getIsimImpu(); 369 370 if(impu !=null){ 371 for(int i=0; i<impu.length; i++){ 372 logger.debug("impu[" + i + "]=" + impu[i]); 373 if(impu[i] != null && impu[i].startsWith("sip:") && 374 impu[i].endsWith(myDomain)){ 375 myNumUri = impu[i]; 376 break; 377 } 378 } 379 } 380 } 381 382 String myNumber = PresenceInfoParser.getPhoneFromUri(myNumUri); 383 384 if(myNumber == null){ 385 myNumber = ContactNumberUtils.getDefault().format(teleMgr.getLine1Number()); 386 if(myDomain != null && myDomain.length() !=0){ 387 myNumUri = "sip:" + myNumber + "@" + myDomain; 388 }else{ 389 myNumUri = "tel:" + myNumber; 390 } 391 } 392 393 logger.print("myNumUri=" + myNumUri + " myNumber=" + myNumber); 394 if(myNumUri == null || myNumber == null){ 395 logger.error("Didn't find number or impu."); 396 return PresencePublication.PUBLISH_GENIRIC_FAILURE; 397 } 398 399 int taskId = TaskManager.getDefault().addPublishTask(myNumber, listener); 400 try{ 401 PresCapInfo pMyCapInfo = new PresCapInfo(); 402 // Fill cap info 403 pMyCapInfo.setContactUri(myNumUri); 404 405 CapInfo capInfo = new CapInfo(); 406 capInfo.setIpVoiceSupported(presenceInfo.getServiceState( 407 RcsPresenceInfo.ServiceType.VOLTE_CALL) 408 == RcsPresenceInfo.ServiceState.ONLINE); 409 capInfo.setIpVideoSupported(presenceInfo.getServiceState( 410 RcsPresenceInfo.ServiceType.VT_CALL) 411 == RcsPresenceInfo.ServiceState.ONLINE); 412 capInfo.setCdViaPresenceSupported(true); 413 414 capInfo.setFtSupported(false); // TODO: support FT 415 capInfo.setImSupported(false);//TODO: support chat 416 capInfo.setFullSnFGroupChatSupported(false); //TODO: support chat 417 418 pMyCapInfo.setCapInfo(capInfo); 419 420 logger.print( "myNumUri = " + myNumUri 421 + " audioSupported = " + capInfo.isIpVoiceSupported() 422 + " videoSupported= " + capInfo.isIpVideoSupported() 423 ); 424 425 426 synchronized (mSyncObj) { 427 StatusCode status = mStackPresService.publishMyCap( 428 mStackPresenceServiceHandle, pMyCapInfo, taskId); 429 logger.print("PublishMyCap status=" + status.getStatusCode()); 430 ret = RcsUtils.statusCodeToResultCode(status.getStatusCode()); 431 } 432 433 logger.debug("requestPublication ret=" + ret); 434 if(ret != ResultCode.SUCCESS){ 435 logger.error("requestPublication remove taskId=" + taskId); 436 TaskManager.getDefault().removeTask(taskId); 437 return ret; 438 } 439 }catch(RemoteException e){ 440 e.printStackTrace(); 441 logger.error("Exception when call mStackPresService.getContactCap"); 442 logger.error("requestPublication remove taskId=" + taskId); 443 TaskManager.getDefault().removeTask(taskId); 444 445 return ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 446 } 447 448 return ResultCode.SUCCESS; 449 } 450 launchPersistService(Intent intent)451 private void launchPersistService(Intent intent) { 452 ComponentName component = new ComponentName(PERSIST_SERVICE_PACKAGE, 453 PERSIST_SERVICE_NAME); 454 intent.setComponent(component); 455 mContext.startService(intent); 456 } 457 createListeningThread()458 private void createListeningThread() { 459 HandlerThread listenerThread = new HandlerThread("Listener", 460 android.os.Process.THREAD_PRIORITY_BACKGROUND); 461 462 listenerThread.start(); 463 Looper listenerLooper = listenerThread.getLooper(); 464 mListenerHandler = new StackListener(mContext, listenerLooper); 465 } 466 initImsUceService()467 private void initImsUceService(){ 468 // Send message to avoid ANR 469 Message reinitMessage = mMsgHandler.obtainMessage( 470 PRESENCE_INIT_IMS_UCE_SERVICE, null); 471 mMsgHandler.sendMessage(reinitMessage); 472 } 473 doInitImsUceService()474 private void doInitImsUceService(){ 475 synchronized (mSyncObj) { 476 logger.debug("doInitImsUceService"); 477 478 if (mStackService != null) { 479 logger.debug("doInitImsUceService mStackService != null"); 480 return; 481 } 482 483 IntentFilter filter = new IntentFilter(); 484 filter.addAction(ImsUceManager.ACTION_UCE_SERVICE_UP); 485 filter.addAction(ImsUceManager.ACTION_UCE_SERVICE_DOWN); 486 487 mRcsServiceReceiver = new BroadcastReceiver() { 488 @Override 489 public void onReceive(Context context, Intent intent) { 490 // do something based on the intent's action 491 logger.print("onReceive intent " + intent); 492 String action = intent.getAction(); 493 if (ImsUceManager.ACTION_UCE_SERVICE_UP.equals(action)) { 494 startInitPresenceTimer(0, PRESENCE_INIT_TYPE_RCS_SERVICE_AVAILABLE); 495 } else if (ImsUceManager.ACTION_UCE_SERVICE_DOWN.equals(action)) { 496 clearImsUceService(); 497 } else { 498 logger.debug("unknown intent " + intent); 499 } 500 } 501 }; 502 503 mContext.registerReceiver(mRcsServiceReceiver, filter); 504 505 if (mImsUceManager == null) { 506 mImsUceManager = ImsUceManager.getInstance(mContext, 507 SubscriptionManager.from(mContext).getDefaultDataPhoneId()); 508 if (mImsUceManager == null) { 509 logger.error("Can't init mImsUceManager"); 510 return; 511 } 512 } 513 514 mImsUceManager.createUceService(false); 515 mStackService = mImsUceManager.getUceServiceInstance(); 516 logger.debug("doInitImsUceService mStackService=" + mStackService); 517 518 if (mStackService != null) { 519 startInitPresenceTimer(0, PRESENCE_INIT_TYPE_RCS_SERVICE_AVAILABLE); 520 } 521 } 522 } 523 524 private PendingIntent mRetryAlarmIntent = null; 525 public static final String ACTION_RETRY_ALARM = "com.android.service.ims.presence.retry"; 526 private AlarmManager mAlarmManager = null; 527 private BroadcastReceiver mRcsServiceReceiver = null; 528 529 /* 530 * Init All Sub service of RCS 531 */ initAllSubRcsServices(IUceService uceService, int currentRetry)532 int initAllSubRcsServices(IUceService uceService, int currentRetry) { 533 int ret = -1; 534 synchronized (mSyncObj) { 535 // we could receive useless retry since we could fail to cancel the retry timer. 536 // We need to ignore such retry if the sub service had been initialized already. 537 if(mStackPresService != null && currentRetry>0){ 538 logger.debug("mStackPresService != null and currentRetry=" + currentRetry + 539 " ignore it"); 540 return 0; 541 } 542 543 logger.debug("Init All Services Under RCS uceService=" + uceService); 544 if(uceService == null){ 545 logger.error("initAllServices : uceService is NULL "); 546 mIsIniting = false; 547 mLastInitSubService = -1; 548 return ret; 549 } 550 551 try { 552 if(mStackPresService != null){ 553 logger.print("RemoveListener and QRCSDestroyPresService"); 554 mStackPresService.removeListener(mStackPresenceServiceHandle, 555 mListenerHandle); 556 uceService.destroyPresenceService(mStackPresenceServiceHandle); 557 558 mStackPresService = null; 559 } 560 561 boolean serviceStatus = false; 562 serviceStatus = uceService.getServiceStatus(); 563 if (true == serviceStatus && mStackPresService == null) {//init only once. 564 logger.print("initAllService : serviceStatus = true "); 565 logger.debug("Create PresService"); 566 mStackPresenceServiceHandle = mStackService.createPresenceService( 567 mListenerHandler.mPresenceListener, mListenerHandle); 568 mStackPresService = mStackService.getPresenceService(); 569 ret = 0; 570 } else { 571 logger.error("initAllService : serviceStatus = false "); 572 } 573 } catch (RemoteException e) { 574 logger.error("initAllServices : DeadObjectException dialog "); 575 e.printStackTrace(); 576 } 577 mIsIniting = false; 578 } 579 return ret; 580 } 581 582 // Init sub service when IMS get registered. checkSubService()583 public void checkSubService() { 584 logger.debug("checkSubService"); 585 synchronized (mSyncObj) { 586 if (mStackPresService == null) { 587 // Cancel the retry timer. 588 if (mIsIniting) { 589 if (mRetryAlarmIntent != null) { 590 mAlarmManager.cancel(mRetryAlarmIntent); 591 mRetryAlarmIntent = null; 592 } 593 mIsIniting = false; 594 } 595 596 // force to init imediately. 597 startInitPresenceTimer(0, PRESENCE_INIT_TYPE_IMS_REGISTERED); 598 } 599 } 600 } 601 startInitThread(int times)602 public void startInitThread(int times){ 603 final int currentRetry = times; 604 Thread thread = new Thread(() -> { 605 synchronized (mSyncObj) { 606 if (currentRetry >= 0 && currentRetry <= MAX_RETRY_COUNT) { 607 refreshUceService(); 608 609 if (initAllSubRcsServices(mStackService, currentRetry) >= 0) { 610 logger.debug("init sub rcs service successfully."); 611 if (mRetryAlarmIntent != null) { 612 mAlarmManager.cancel(mRetryAlarmIntent); 613 } 614 } else { 615 startInitPresenceTimer(currentRetry + 1, PRESENCE_INIT_TYPE_RETRY); 616 } 617 } else { 618 logger.debug("Retry times=" + currentRetry); 619 if (mRetryAlarmIntent != null) { 620 mAlarmManager.cancel(mRetryAlarmIntent); 621 } 622 } 623 } 624 }, "initAllSubRcsServices thread"); 625 626 thread.start(); 627 } 628 init()629 private void init() { 630 createListeningThread(); 631 logger.debug("after createListeningThread"); 632 633 if(mAlarmManager == null){ 634 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 635 } 636 637 initImsUceService(); 638 639 setInPowerDown(false); 640 logger.debug("init finished"); 641 } 642 startInitPresenceTimer(int times, int initType)643 private void startInitPresenceTimer(int times, int initType){ 644 synchronized (mSyncObj) { 645 logger.print("set the retry alarm, times=" + times + " initType=" + initType + 646 " mIsIniting=" + mIsIniting); 647 if(mIsIniting){ 648 //initing is on going in 5 seconds, discard this one. 649 if(mLastInitSubService != -1 && 650 System.currentTimeMillis() - mLastInitSubService < 5000){ 651 logger.print("already in initing. ignore it"); 652 return; 653 }//else suppose the init has problem. so continue 654 } 655 656 mIsIniting = true; 657 658 Intent intent = new Intent(ACTION_RETRY_ALARM); 659 intent.putExtra("times", times); 660 intent.setClass(mContext, AlarmBroadcastReceiver.class); 661 mRetryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, 662 PendingIntent.FLAG_UPDATE_CURRENT); 663 664 // Wait for 1s to ignore duplicate init request as possible as we can. 665 long timeSkip = 1000; 666 if(times < 0 || times >= MAX_RETRY_COUNT){ 667 times = MAX_RETRY_COUNT; 668 } 669 670 //Could failed to cancel a timer in 1s. So use exponential retry to make sure it 671 //will be stopped for non-VoLte SIM. 672 timeSkip = (timeSkip << times); 673 logger.debug("timeSkip = " + timeSkip); 674 675 mLastInitSubService = System.currentTimeMillis(); 676 677 //the timer intent could have a longer delay. call directly at first time 678 if(times == 0) { 679 startInitThread(0); 680 } else { 681 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 682 SystemClock.elapsedRealtime() + timeSkip, mRetryAlarmIntent); 683 } 684 } 685 } 686 refreshUceService()687 private void refreshUceService() { 688 synchronized (mSyncObj) { 689 logger.debug("refreshUceService mImsUceManager=" + mImsUceManager + 690 " mStackService=" + mStackService); 691 692 if (mImsUceManager == null) { 693 mImsUceManager = ImsUceManager.getInstance(mContext, 694 SubscriptionManager.from(mContext).getDefaultDataPhoneId()); 695 if (mImsUceManager == null) { 696 logger.error("Can't init mImsUceManager"); 697 return; 698 } 699 } 700 701 if (mStackService == null) { 702 mImsUceManager.createUceService(false); 703 mStackService = mImsUceManager.getUceServiceInstance(); 704 } 705 706 logger.debug("refreshUceService mStackService=" + mStackService); 707 } 708 } 709 clearImsUceService()710 private void clearImsUceService() { 711 synchronized (mSyncObj) { 712 try { 713 logger.info("clearImsUceService: removing listener and presence service."); 714 if (mStackPresService != null) { 715 mStackPresService.removeListener(mStackPresenceServiceHandle, 716 mListenerHandle); 717 } 718 if (mStackService != null) { 719 mStackService.destroyPresenceService(mStackPresenceServiceHandle); 720 } 721 } catch (RemoteException e) { 722 logger.warn("clearImsUceService: Couldn't clean up stack service"); 723 } 724 mImsUceManager = null; 725 mStackService = null; 726 mStackPresService = null; 727 } 728 } 729 finish()730 public void finish() { 731 if(mRetryAlarmIntent != null){ 732 mAlarmManager.cancel(mRetryAlarmIntent); 733 mRetryAlarmIntent = null; 734 } 735 736 if (mRcsServiceReceiver != null) { 737 mContext.unregisterReceiver(mRcsServiceReceiver); 738 mRcsServiceReceiver = null; 739 } 740 741 clearImsUceService(); 742 } 743 finalize()744 protected void finalize() throws Throwable { 745 super.finalize(); 746 finish(); 747 } 748 isInPowerDown()749 static public boolean isInPowerDown() { 750 return sInPowerDown; 751 } 752 setInPowerDown(boolean inPowerDown)753 static void setInPowerDown(boolean inPowerDown) { 754 sInPowerDown = inPowerDown; 755 } 756 } 757 758