/*
 * 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;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import com.android.ims.IRcsPresenceListener;
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 com.android.ims.internal.uce.common.CapInfo;
import com.android.ims.internal.uce.common.StatusCode;
import com.android.ims.internal.uce.common.UceLong;
import com.android.ims.internal.uce.presence.IPresenceService;
import com.android.ims.internal.uce.presence.PresCapInfo;
import com.android.ims.internal.uce.uceservice.IUceService;
import com.android.ims.internal.uce.uceservice.ImsUceManager;
import com.android.service.ims.presence.AlarmBroadcastReceiver;
import com.android.service.ims.presence.PresenceInfoParser;
import com.android.service.ims.presence.PresencePublication;
import com.android.service.ims.presence.StackListener;

public class RcsStackAdaptor{
    private static final boolean DEBUG = true;

    private static final String PERSIST_SERVICE_NAME =
            "com.android.service.ims.presence.PersistService";
    private static final String PERSIST_SERVICE_PACKAGE = "com.android.service.ims.presence";

    // The logger
    private Logger logger = Logger.getLogger(this.getClass().getName());

    private static final int PRESENCE_INIT_IMS_UCE_SERVICE = 1;

    private Context mContext = null;

    // true when the stack presence service got available. (Called IQPresListener_ServiceAvailable)
    private volatile boolean mImsEnableState = false;

    // provision status can be set by both subscribe and pubilish
    // for unprovisioned for 403 or 404
    private volatile int mPublishingState = PublishState.PUBLISH_STATE_NOT_PUBLISHED;

    // It is initializing the stack presence service.
    private volatile boolean mIsIniting = false;

    // The time which the stack presence service got initialized.
    private volatile long mLastInitSubService = -1; //last time which inited the sub service

    // Used for synchronizing
    private final Object mSyncObj = new Object();

    // We need wait RCS stack become unavailable before close RCS service.
    static private boolean sInPowerDown = false;

    // This could happen when the stack first launch or modem panic.
    private static final int PRESENCE_INIT_TYPE_RCS_SERVICE_AVAILABLE =1;

    // The initialization was triggered by retry.
    private static final int PRESENCE_INIT_TYPE_RETRY = 2;

    // The initialization was triggered by retry.
    private static final int PRESENCE_INIT_TYPE_IMS_REGISTERED = 3;

    // The maximum retry count for initializing the stack service.
    private static final int MAX_RETRY_COUNT = 6;//Maximum time is 64s

    public boolean isImsEnableState() {
        synchronized (mSyncObj) {
            return mImsEnableState;
        }
    }

    public void setImsEnableState(boolean imsEnableState) {
        synchronized (mSyncObj) {
            logger.debug("imsEnableState=" + imsEnableState);
            mImsEnableState = imsEnableState;
        }
    }

    // The UCE manager for RCS stack.
    private ImsUceManager mImsUceManager = null;

    // The stack RCS Service instance.
    private IUceService mStackService = null;

    // The stack presence service
    private IPresenceService mStackPresService = null;

    // The stack Presence Service handle.
    private int  mStackPresenceServiceHandle;

    // The listener which listen to the response for presence service.
    private StackListener mListenerHandler = null;

    // The handler of the listener.
    private UceLong mListenerHandle = new UceLong();

    // The singleton.
    private static RcsStackAdaptor sInstance = null;

    // Constructor
    private RcsStackAdaptor(Context context) {
        mContext = context;

        init();
    }

    public static synchronized RcsStackAdaptor getInstance(Context context) {
        if ((sInstance == null) && (context != null)) {
            sInstance = new RcsStackAdaptor(context);
        }

        return sInstance;
    }

    private Handler mMsgHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            logger.debug( "Thread=" + Thread.currentThread().getName() + " received "
                    + msg);
            if(msg == null){
                logger.error("msg=null");
                return;
           }

            switch (msg.what) {
                case PRESENCE_INIT_IMS_UCE_SERVICE:
                    logger.debug("handleMessage  msg=PRESENCE_INIT_IMS_UCE_SERVICE" );
                    doInitImsUceService();
                break;

                default:
                    logger.debug("handleMessage unknown msg=" + msg.what);
            }
        }
    };

    public StackListener getListener(){
        return mListenerHandler;
    }

    public int checkStackAndPublish(){
        if (!RcsSettingUtils.getCapabilityDiscoveryEnabled(mContext)) {
            logger.error("getCapabilityDiscoveryEnabled = false");
            return ResultCode.ERROR_SERVICE_NOT_ENABLED;
        }

        int ret = checkStackStatus();
        if (ret != ResultCode.SUCCESS) {
            logger.error("checkStackAndPublish ret=" + ret);
            return ret;
        }

        if (!isPublished()) {
            logger.error(
                    "checkStackAndPublish ERROR_SERVICE_NOT_PUBLISHED");
            return ResultCode.ERROR_SERVICE_NOT_PUBLISHED;
        }

        return ResultCode.SUCCESS;
    }

    private boolean isPublished(){
        if(getPublishState() != PublishState.PUBLISH_STATE_200_OK){
            logger.error("Didnt' publish properly");
            return false;
        }

        return true;
    }

    public void setPublishState(int publishState) {
        synchronized (mSyncObj) {
            logger.print("mPublishingState=" + mPublishingState + " publishState=" + publishState);
            if (mPublishingState != publishState) {
                // save it for recovery when PresenceService crash.
                SystemProperties.set("rcs.publish.status",
                        String.valueOf(publishState));

                Intent publishIntent = new Intent(RcsPresence.ACTION_PUBLISH_STATE_CHANGED);
                publishIntent.putExtra(RcsPresence.EXTRA_PUBLISH_STATE, publishState);
                // Start PersistService and broadcast to other receivers that are listening
                // dynamically.
                mContext.sendStickyBroadcast(publishIntent);
                launchPersistService(publishIntent);
            }

            mPublishingState = publishState;
        }
    }

    public int getPublishState(){
        synchronized (mSyncObj) {
            return mPublishingState;
        }
    }

    public int checkStackStatus(){
        synchronized (mSyncObj) {
            if (!RcsSettingUtils.isEabProvisioned(mContext)) {
                logger.error("Didn't get EAB provisioned by DM");
                return ResultCode.ERROR_SERVICE_NOT_ENABLED;
            }

            // Don't send request to RCS stack when it is under powering off.
            // RCS stack is sending UNPUBLISH. It could get race PUBLISH trigger under the case.
            if (sInPowerDown) {
                logger.error("checkStackStatus: under powering off");
                return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
            }

            if (mStackService == null) {
                logger.error("checkStackStatus: mStackService == null");
                return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
            }

            if (mStackPresService == null) {
                logger.error("Didn't init sub rcs service.");
                return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
            }

            if (!mImsEnableState) {
                logger.error("mImsEnableState = false");
                return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
            }
        }

        return ResultCode.SUCCESS;
    }

    public int requestCapability(String[] formatedContacts, int taskId){
        logger.print("requestCapability formatedContacts=" + formatedContacts);

        int ret = ResultCode.SUCCESS;
        try {
            synchronized (mSyncObj) {
                StatusCode retCode;
                if (formatedContacts.length == 1) {
                    retCode = mStackPresService.getContactCap(
                            mStackPresenceServiceHandle, formatedContacts[0], taskId);
                } else {
                    retCode = mStackPresService.getContactListCap(
                            mStackPresenceServiceHandle, formatedContacts, taskId);
                }

                logger.print("GetContactListCap retCode=" + retCode);

                ret = RcsUtils.statusCodeToResultCode(retCode.getStatusCode());
            }

            logger.debug("requestCapability ret=" + ret);
        }catch(Exception e){
            logger.error("requestCapability exception", e);
            ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
        }

        return  ret;
    }

    public int requestAvailability(String formatedContact, int taskId){
        logger.debug("requestAvailability ...");

        int ret = ResultCode.SUCCESS;
        try{
            synchronized (mSyncObj) {
                StatusCode retCode = mStackPresService.getContactCap(
                        mStackPresenceServiceHandle, formatedContact, taskId);
                logger.print("getContactCap retCode=" + retCode);

                ret = RcsUtils.statusCodeToResultCode(retCode.getStatusCode());
            }
            logger.debug("requestAvailability ret=" + ret);
        }catch(Exception e){
            logger.error("requestAvailability exception", e);
            ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
        }

        return  ret;
    }

    public int requestPublication(RcsPresenceInfo presenceInfo, IRcsPresenceListener listener) {
        logger.debug("requestPublication ...");

         // Don't use checkStackAndPublish()
         // since it will check publish status which in dead loop.
         int ret = checkStackStatus();
         if(ret != ResultCode.SUCCESS){
             logger.error("requestPublication ret=" + ret);
             return ret;
         }

        TelephonyManager teleMgr = (TelephonyManager) mContext.getSystemService(
            Context.TELEPHONY_SERVICE);
        if(teleMgr == null){
            logger.error("teleMgr = null");
            return PresencePublication.PUBLISH_GENIRIC_FAILURE;
        }

        String myNumUri = null;
        String myDomain = teleMgr.getIsimDomain();
        logger.debug("myDomain=" + myDomain);
        if(myDomain != null && myDomain.length() !=0){
            String[] impu = teleMgr.getIsimImpu();

            if(impu !=null){
                for(int i=0; i<impu.length; i++){
                    logger.debug("impu[" + i + "]=" + impu[i]);
                    if(impu[i] != null && impu[i].startsWith("sip:") &&
                            impu[i].endsWith(myDomain)){
                        myNumUri = impu[i];
                        break;
                    }
                }
            }
        }

        String myNumber = PresenceInfoParser.getPhoneFromUri(myNumUri);

        if(myNumber == null){
            myNumber = ContactNumberUtils.getDefault().format(teleMgr.getLine1Number());
            if(myDomain != null && myDomain.length() !=0){
                myNumUri = "sip:" + myNumber + "@" + myDomain;
            }else{
                myNumUri = "tel:" + myNumber;
            }
        }

        logger.print("myNumUri=" + myNumUri + " myNumber=" + myNumber);
        if(myNumUri == null || myNumber == null){
            logger.error("Didn't find number or impu.");
            return PresencePublication.PUBLISH_GENIRIC_FAILURE;
        }

        int taskId = TaskManager.getDefault().addPublishTask(myNumber, listener);
        try{
            PresCapInfo pMyCapInfo = new PresCapInfo();
            // Fill cap info
            pMyCapInfo.setContactUri(myNumUri);

            CapInfo capInfo = new CapInfo();
            capInfo.setIpVoiceSupported(presenceInfo.getServiceState(
                    RcsPresenceInfo.ServiceType.VOLTE_CALL)
                    == RcsPresenceInfo.ServiceState.ONLINE);
            capInfo.setIpVideoSupported(presenceInfo.getServiceState(
                    RcsPresenceInfo.ServiceType.VT_CALL)
                    == RcsPresenceInfo.ServiceState.ONLINE);
            capInfo.setCdViaPresenceSupported(true);

            capInfo.setFtSupported(false); // TODO: support FT
            capInfo.setImSupported(false);//TODO: support chat
            capInfo.setFullSnFGroupChatSupported(false); //TODO: support chat

            pMyCapInfo.setCapInfo(capInfo);

            logger.print( "myNumUri = " + myNumUri
                    + " audioSupported =  " + capInfo.isIpVoiceSupported()
                    + " videoSupported=  " + capInfo.isIpVideoSupported()
                    );


            synchronized (mSyncObj) {
                StatusCode status = mStackPresService.publishMyCap(
                        mStackPresenceServiceHandle, pMyCapInfo, taskId);
                logger.print("PublishMyCap status=" + status.getStatusCode());
                ret = RcsUtils.statusCodeToResultCode(status.getStatusCode());
            }

            logger.debug("requestPublication ret=" + ret);
            if(ret != ResultCode.SUCCESS){
                logger.error("requestPublication remove taskId=" + taskId);
                TaskManager.getDefault().removeTask(taskId);
                return ret;
            }
        }catch(RemoteException e){
            e.printStackTrace();
            logger.error("Exception when call mStackPresService.getContactCap");
            logger.error("requestPublication remove taskId=" + taskId);
            TaskManager.getDefault().removeTask(taskId);

            return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
        }

        return  ResultCode.SUCCESS;
    }

    private void launchPersistService(Intent intent) {
        ComponentName component = new ComponentName(PERSIST_SERVICE_PACKAGE,
                PERSIST_SERVICE_NAME);
        intent.setComponent(component);
        mContext.startService(intent);
    }

    private void createListeningThread() {
        HandlerThread listenerThread = new HandlerThread("Listener",
                android.os.Process.THREAD_PRIORITY_BACKGROUND);

        listenerThread.start();
        Looper listenerLooper = listenerThread.getLooper();
        mListenerHandler = new StackListener(mContext, listenerLooper);
    }

    private void initImsUceService(){
        // Send message to avoid ANR
        Message reinitMessage = mMsgHandler.obtainMessage(
                PRESENCE_INIT_IMS_UCE_SERVICE, null);
        mMsgHandler.sendMessage(reinitMessage);
    }

    private void doInitImsUceService(){
        synchronized (mSyncObj) {
            logger.debug("doInitImsUceService");

            if (mStackService != null) {
                logger.debug("doInitImsUceService mStackService != null");
                return;
            }

            IntentFilter filter = new IntentFilter();
            filter.addAction(ImsUceManager.ACTION_UCE_SERVICE_UP);
            filter.addAction(ImsUceManager.ACTION_UCE_SERVICE_DOWN);

            mRcsServiceReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    // do something based on the intent's action
                    logger.print("onReceive intent " + intent);
                    String action = intent.getAction();
                    if (ImsUceManager.ACTION_UCE_SERVICE_UP.equals(action)) {
                        startInitPresenceTimer(0, PRESENCE_INIT_TYPE_RCS_SERVICE_AVAILABLE);
                    } else if (ImsUceManager.ACTION_UCE_SERVICE_DOWN.equals(action)) {
                        clearImsUceService();
                    } else {
                        logger.debug("unknown intent " + intent);
                    }
                }
            };

            mContext.registerReceiver(mRcsServiceReceiver, filter);

            if (mImsUceManager == null) {
                mImsUceManager = ImsUceManager.getInstance(mContext,
                        SubscriptionManager.from(mContext).getDefaultDataPhoneId());
                if (mImsUceManager == null) {
                    logger.error("Can't init mImsUceManager");
                    return;
                }
            }

            mImsUceManager.createUceService(false);
            mStackService = mImsUceManager.getUceServiceInstance();
            logger.debug("doInitImsUceService mStackService=" + mStackService);

            // Do not connect to vendor UCE stack until ACTION_UCE_SERVICE_UP is called.
            // The intent is sticky, so if we crash, we will get the UCE_SERVICE_UP intent again.
        }
    }

    private PendingIntent mRetryAlarmIntent = null;
    private AlarmManager mAlarmManager = null;
    private BroadcastReceiver mRcsServiceReceiver = null;

    /*
     * Init All Sub service of RCS
     */
    int initAllSubRcsServices(IUceService uceService, int currentRetry) {
        int ret = -1;
        synchronized (mSyncObj) {
            // we could receive useless retry since we could fail to cancel the retry timer.
            // We need to ignore such retry if the sub service had been initialized already.
            if(mStackPresService != null && currentRetry>0){
                logger.debug("mStackPresService != null and currentRetry=" + currentRetry +
                        " ignore it");
                return 0;
            }

            logger.debug("Init All Services Under RCS uceService=" + uceService);
            if(uceService == null){
                logger.error("initAllServices : uceService is NULL  ");
                mIsIniting = false;
                mLastInitSubService = -1;
                return ret;
            }

            try {
                if(mStackPresService != null){
                    logger.print("RemoveListener and QRCSDestroyPresService");
                    mStackPresService.removeListener(mStackPresenceServiceHandle,
                            mListenerHandle);
                    uceService.destroyPresenceService(mStackPresenceServiceHandle);

                    mStackPresService = null;
                }

                boolean serviceStatus = false;
                serviceStatus = uceService.getServiceStatus();
                //init only once and ensure connection to UCE  service is available.
                if (true == serviceStatus && mStackPresService == null && mStackService != null) {
                    logger.print("initAllService : serviceStatus =  true ");
                    logger.debug("Create PresService");
                    mStackPresenceServiceHandle = mStackService.createPresenceService(
                            mListenerHandler.mPresenceListener, mListenerHandle);
                    // If the service handle is -1, then creating the service failed somehow.
                    // schedule a retry.
                    if (mStackPresenceServiceHandle < 0) {
                        logger.error("initAllService : service handle < 0, retrying...");
                        mIsIniting = false;
                        mLastInitSubService = -1;
                        return ret;
                    }
                    mStackPresService = mStackService.getPresenceService();
                    ret = 0;
                 } else {
                    logger.error("initAllService : serviceStatus =  false - serviceStatus: "
                            + serviceStatus + ", mStackPresService: " + mStackPresService
                            + ", mStackService: " + mStackService);
                }
            } catch (RemoteException e) {
                logger.error("initAllServices :  DeadObjectException dialog  ");
                e.printStackTrace();
            }
            mIsIniting = false;
        }
        return ret;
    }

    public void startInitThread(int times){
        final int currentRetry = times;
        Thread thread = new Thread(() -> {
            synchronized (mSyncObj) {
                if (currentRetry >= 0 && currentRetry <= MAX_RETRY_COUNT) {
                    refreshUceService();

                    if (initAllSubRcsServices(mStackService, currentRetry) >= 0) {
                        logger.debug("init sub rcs service successfully.");
                        if (mRetryAlarmIntent != null) {
                            mAlarmManager.cancel(mRetryAlarmIntent);
                        }
                    } else {
                        startInitPresenceTimer(currentRetry + 1, PRESENCE_INIT_TYPE_RETRY);
                    }
                } else {
                    logger.debug("Retry times=" + currentRetry);
                    if (mRetryAlarmIntent != null) {
                        mAlarmManager.cancel(mRetryAlarmIntent);
                    }
                }
            }
        }, "initAllSubRcsServices thread");

        thread.start();
    }

    private void init() {
        createListeningThread();
        logger.debug("after createListeningThread");

        if(mAlarmManager == null){
            mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        }

        initImsUceService();

        setInPowerDown(false);
        logger.debug("init finished");
    }

    private void startInitPresenceTimer(int times, int initType){
        synchronized (mSyncObj) {
            logger.print("set the retry alarm, times=" + times + " initType=" + initType +
                    " mIsIniting=" + mIsIniting);
            if(mIsIniting){
                //initing is on going in 5 seconds, discard this one.
                if(mLastInitSubService != -1 &&
                        System.currentTimeMillis() - mLastInitSubService < 5000){
                    logger.print("already in initing. ignore it");
                    return;
                }//else suppose the init has problem. so continue
            }

            mIsIniting = true;

            Intent intent = new Intent(AlarmBroadcastReceiver.ACTION_RETRY_ALARM);
            intent.putExtra("times", times);
            intent.setClass(mContext, AlarmBroadcastReceiver.class);
            mRetryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent,
                    PendingIntent.FLAG_UPDATE_CURRENT);

            // Wait for 1s to ignore duplicate init request as possible as we can.
            long timeSkip = 1000;
            if(times < 0 || times >= MAX_RETRY_COUNT){
                times = MAX_RETRY_COUNT;
            }

            //Could failed to cancel a timer in 1s. So use exponential retry to make sure it
            //will be stopped for non-VoLte SIM.
            timeSkip = (timeSkip << times);
            logger.debug("timeSkip = " + timeSkip);

            mLastInitSubService = System.currentTimeMillis();

            //the timer intent could have a longer delay. call directly at first time
            if(times == 0) {
                startInitThread(0);
            } else {
                mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() + timeSkip, mRetryAlarmIntent);
            }
        }
    }

    private void refreshUceService() {
        synchronized (mSyncObj) {
            logger.debug("refreshUceService mImsUceManager=" + mImsUceManager +
                    " mStackService=" + mStackService);

            if (mImsUceManager == null) {
                mImsUceManager = ImsUceManager.getInstance(mContext,
                        SubscriptionManager.from(mContext).getDefaultDataPhoneId());
                if (mImsUceManager == null) {
                    logger.error("Can't init mImsUceManager");
                    return;
                }
            }

            if (mStackService == null) {
                mImsUceManager.createUceService(false);
                mStackService = mImsUceManager.getUceServiceInstance();
            }

            logger.debug("refreshUceService mStackService=" + mStackService);
        }
    }

    private void clearImsUceService() {
        synchronized (mSyncObj) {
            try {
                logger.info("clearImsUceService: removing listener and presence service.");
                if (mStackPresService != null) {
                    mStackPresService.removeListener(mStackPresenceServiceHandle,
                            mListenerHandle);
                }
                if (mStackService != null) {
                    mStackService.destroyPresenceService(mStackPresenceServiceHandle);
                }
            } catch (RemoteException e) {
                logger.warn("clearImsUceService: Couldn't clean up stack service");
            }
            mImsUceManager = null;
            mStackService = null;
            mStackPresService = null;
        }
    }

    public void finish() {
        if(mRetryAlarmIntent != null){
            mAlarmManager.cancel(mRetryAlarmIntent);
            mRetryAlarmIntent = null;
        }

        if (mRcsServiceReceiver != null) {
            mContext.unregisterReceiver(mRcsServiceReceiver);
            mRcsServiceReceiver = null;
        }

        clearImsUceService();
    }

    protected void finalize() throws Throwable {
        super.finalize();
        finish();
    }

    static public boolean isInPowerDown() {
        return sInPowerDown;
    }

    static void setInPowerDown(boolean inPowerDown) {
        sInPowerDown = inPowerDown;
    }
}

