blob: 06d23677eff5f5b513c0c5040016e24fa1bc63c2 [file] [log] [blame]
James.cf Linaf3183c2019-10-24 00:59:00 +08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
19import android.content.Context;
20import android.net.Uri;
James.cf Lincad981c2019-12-10 20:37:56 +080021import android.os.Binder;
22import android.os.RemoteException;
James.cf Linaf3183c2019-10-24 00:59:00 +080023import android.os.ServiceManager;
James.cf Lincad981c2019-12-10 20:37:56 +080024import android.os.ServiceSpecificException;
25import android.telephony.ims.ImsException;
James.cf Linaf3183c2019-10-24 00:59:00 +080026import android.telephony.ims.aidl.IImsCapabilityCallback;
27import android.telephony.ims.aidl.IImsRcsController;
28import android.telephony.ims.aidl.IRcsUceControllerCallback;
29import android.telephony.ims.feature.RcsFeature;
James.cf Lincad981c2019-12-10 20:37:56 +080030import android.telephony.ims.stub.ImsRegistrationImplBase;
James.cf Linaf3183c2019-10-24 00:59:00 +080031import android.util.Log;
32
James.cf Lincad981c2019-12-10 20:37:56 +080033import com.android.ims.RcsFeatureManager;
34import com.android.internal.telephony.Phone;
35import com.android.internal.telephony.imsphone.ImsPhone;
36
James.cf Linaf3183c2019-10-24 00:59:00 +080037import java.util.List;
38
39/**
40 * Implementation of the IImsRcsController interface.
41 */
42public class ImsRcsController extends IImsRcsController.Stub {
43 private static final String TAG = "ImsRcsController";
44
45 /** The singleton instance. */
46 private static ImsRcsController sInstance;
47
48 private PhoneGlobals mApp;
49
50 /**
51 * Initialize the singleton ImsRcsController instance.
52 * This is only done once, at startup, from PhoneApp.onCreate().
53 */
54 static ImsRcsController init(PhoneGlobals app) {
55 synchronized (ImsRcsController.class) {
56 if (sInstance == null) {
57 sInstance = new ImsRcsController(app);
58 } else {
59 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
60 }
61 return sInstance;
62 }
63 }
64
65 /** Private constructor; @see init() */
66 private ImsRcsController(PhoneGlobals app) {
67 Log.i(TAG, "ImsRcsController");
68 mApp = app;
69 ServiceManager.addService(Context.TELEPHONY_IMS_SERVICE, this);
70 }
71
James.cf Lincad981c2019-12-10 20:37:56 +080072 /**
73 * Register a capability callback which will provide RCS availability updates for the
74 * subscription specified.
75 *
76 * @param subId the subscription ID
77 * @param callback The ImsCapabilityCallback to be registered.
78 */
James.cf Linaf3183c2019-10-24 00:59:00 +080079 @Override
James.cf Lincad981c2019-12-10 20:37:56 +080080 public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback)
81 throws RemoteException {
James.cf Linaf3183c2019-10-24 00:59:00 +080082 enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +080083 final long token = Binder.clearCallingIdentity();
84 try {
85 getRcsFeatureManager(subId).registerRcsAvailabilityCallback(callback);
86 } catch (com.android.ims.ImsException e) {
87 Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
88 throw new ServiceSpecificException(e.getCode());
89 } finally {
90 Binder.restoreCallingIdentity(token);
91 }
James.cf Linaf3183c2019-10-24 00:59:00 +080092 }
93
James.cf Lincad981c2019-12-10 20:37:56 +080094 /**
95 * Remove the registered capability callback.
96 *
97 * @param subId the subscription ID
98 * @param callback The ImsCapabilityCallback to be removed.
99 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800100 @Override
James.cf Lincad981c2019-12-10 20:37:56 +0800101 public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800102 enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
James.cf Lincad981c2019-12-10 20:37:56 +0800103 final long token = Binder.clearCallingIdentity();
104 try {
105 getRcsFeatureManager(subId).unregisterRcsAvailabilityCallback(callback);
106 } catch (com.android.ims.ImsException e) {
107 Log.e(TAG, "unregisterRcsAvailabilityCallback: sudId=" + subId + "," + e.getMessage());
108 } finally {
109 Binder.restoreCallingIdentity(token);
110 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800111 }
112
James.cf Lincad981c2019-12-10 20:37:56 +0800113 /**
114 * Query for the capability of an IMS RCS service
115 *
116 * @param subId the subscription ID
117 * @param capability the RCS capability to query.
118 * @param radioTech the radio tech that this capability failed for
119 * @return true if the RCS capability is capable for this subscription, false otherwise.
120 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800121 @Override
122 public boolean isCapable(int subId,
James.cf Lincad981c2019-12-10 20:37:56 +0800123 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
124 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
James.cf Linaf3183c2019-10-24 00:59:00 +0800125 enforceReadPrivilegedPermission("isCapable");
James.cf Lincad981c2019-12-10 20:37:56 +0800126 final long token = Binder.clearCallingIdentity();
127 try {
128 return getRcsFeatureManager(subId).isCapable(capability, radioTech);
129 } catch (com.android.ims.ImsException e) {
130 Log.e(TAG, "isCapable: sudId=" + subId
131 + ", capability=" + capability + ", " + e.getMessage());
132 return false;
133 } finally {
134 Binder.restoreCallingIdentity(token);
135 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800136 }
137
James.cf Lincad981c2019-12-10 20:37:56 +0800138 /**
139 * Query the availability of an IMS RCS capability.
140 *
141 * @param subId the subscription ID
142 * @param capability the RCS capability to query.
143 * @return true if the RCS capability is currently available for the associated subscription,
144 * false otherwise.
145 */
James.cf Linaf3183c2019-10-24 00:59:00 +0800146 @Override
147 public boolean isAvailable(int subId,
148 @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
149 enforceReadPrivilegedPermission("isAvailable");
James.cf Lincad981c2019-12-10 20:37:56 +0800150 final long token = Binder.clearCallingIdentity();
151 try {
152 return getRcsFeatureManager(subId).isAvailable(capability);
153 } catch (com.android.ims.ImsException e) {
154 Log.e(TAG, "isAvailable: sudId=" + subId
155 + ", capability=" + capability + ", " + e.getMessage());
156 return false;
157 } finally {
158 Binder.restoreCallingIdentity(token);
159 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800160 }
161
162 @Override
163 public void requestCapabilities(int subId, List<Uri> contactNumbers,
164 IRcsUceControllerCallback c) {
165 enforceReadPrivilegedPermission("requestCapabilities");
166 }
167
168 @Override
169 public int getUcePublishState(int subId) {
170 enforceReadPrivilegedPermission("getUcePublishState");
171 return -1;
172 }
173
174 @Override
175 public boolean isUceSettingEnabled(int subId) {
176 enforceReadPrivilegedPermission("isUceSettingEnabled");
177 return false;
178 }
179
180 @Override
181 public void setUceSettingEnabled(int subId, boolean isEnabled) {
182 enforceModifyPermission();
183 }
184
185 /**
186 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
187 *
188 * @throws SecurityException if the caller does not have the required permission
189 */
190 private void enforceReadPrivilegedPermission(String message) {
191 mApp.enforceCallingOrSelfPermission(
192 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
193 }
194
195 /**
196 * Make sure the caller has the MODIFY_PHONE_STATE permission.
197 *
198 * @throws SecurityException if the caller does not have the required permission
199 */
200 private void enforceModifyPermission() {
201 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
202 }
James.cf Lincad981c2019-12-10 20:37:56 +0800203
204 /**
205 * Retrieve RcsFeatureManager instance.
206 *
207 * @param subId the subscription ID
208 * @return The RcsFeatureManager instance
209 * @throws SecurityException if getting Phone or RcsFeatureManager instance failed.
210 */
211 private RcsFeatureManager getRcsFeatureManager(int subId) {
212 Phone phone = PhoneGlobals.getPhone(subId);
213 if (phone == null) {
214 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
215 "Invalid subscription Id: " + subId);
216 }
217 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
218 if (imsPhone == null) {
219 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
220 "Cannot find ImsPhone instance: " + subId);
221 }
222 RcsFeatureManager rcsFeatureManager = imsPhone.getRcsManager();
223 if (rcsFeatureManager == null) {
224 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
225 "Cannot find RcsFeatureManager instance: " + subId);
226 }
227 return rcsFeatureManager;
228 }
James.cf Linaf3183c2019-10-24 00:59:00 +0800229}