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
29package com.android.service.ims.presence;
30
31import android.app.Service;
32import android.content.BroadcastReceiver;
33import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
36import android.telephony.CarrierConfigManager;
37import android.os.IBinder;
38import android.os.PersistableBundle;
39import android.os.ServiceManager;
40import android.os.SystemProperties;
41
42import com.android.ims.internal.Logger;
43import com.android.internal.annotations.VisibleForTesting;
44
45/**
46 * Manages the CapabilityPolling class. Starts capability polling when a SIM card is inserted that
47 * supports RCS Presence Capability Polling and stops the service otherwise.
48 */
49public class PollingService extends Service {
50
51    private Logger logger = Logger.getLogger(this.getClass().getName());
52
53    private CapabilityPolling mCapabilityPolling = null;
54
55    // not final for testing
56    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
57
58        @Override
59        public void onReceive(Context context, Intent intent) {
60            switch (intent.getAction()) {
61                case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED: {
62                    checkAndUpdateCapabilityPollStatus();
63                    break;
64                }
65            }
66        }
67    };
68
69    /**
70     * Constructor
71     */
72    public PollingService() {
73        logger.debug("PollingService()");
74    }
75
76    @Override
77    public void onCreate() {
78        logger.debug("onCreate()");
79
80        registerBroadcastReceiver();
81        // Check when the service starts in case the SIM info has already been loaded.
82        checkAndUpdateCapabilityPollStatus();
83    }
84
85    /**
86      * Cleans up when the service is destroyed
87      */
88    @Override
89    public void onDestroy() {
90        logger.debug("onDestroy()");
91
92        if (mCapabilityPolling != null) {
93            mCapabilityPolling.stop();
94            mCapabilityPolling = null;
95        }
96
97        unregisterReceiver(mReceiver);
98
99        super.onDestroy();
100    }
101
102    @Override
103    public IBinder onBind(Intent intent) {
104        logger.debug("onBind(), intent: " + intent);
105
106        if (!isRcsSupported(this)) {
107            return null;
108        }
109
110        logger.debug("onBind add services here");
111        return null;
112    }
113
114    @VisibleForTesting
115    public void setBroadcastReceiver(BroadcastReceiver r) {
116        mReceiver = r;
117    }
118
119    private void registerBroadcastReceiver() {
120        IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
121        registerReceiver(mReceiver, filter);
122    }
123
124    private void checkAndUpdateCapabilityPollStatus() {
125        // If the carrier doesn't support RCS Presence, stop polling.
126        if (!isRcsSupportedByCarrier(this)) {
127            logger.info("RCS not supported by carrier. Stopping CapabilityPolling");
128            if (mCapabilityPolling != null) {
129                mCapabilityPolling.stop();
130                mCapabilityPolling = null;
131            }
132            return;
133        }
134        // Carrier supports, so start the service if it hasn't already been started.
135        if (mCapabilityPolling == null) {
136            logger.info("Starting CapabilityPolling...");
137            mCapabilityPolling = CapabilityPolling.getInstance(this);
138            mCapabilityPolling.start();
139        }
140    }
141
142    static boolean isRcsSupported(Context context) {
143        return isRcsSupportedByDevice() && isRcsSupportedByCarrier(context);
144    }
145
146    private static boolean isRcsSupportedByCarrier(Context context) {
147        CarrierConfigManager configManager = context.getSystemService(CarrierConfigManager.class);
148        if (configManager != null) {
149            PersistableBundle b = configManager.getConfig();
150            if (b != null) {
151                return b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false);
152            }
153        }
154        return true;
155    }
156
157    public static boolean isRcsSupportedByDevice() {
158        String rcsSupported = SystemProperties.get("persist.rcs.supported");
159        return "1".equals(rcsSupported);
160    }
161}
162