blob: 6c5452a3cb2eee828396f994b4c202e284cb7a55 [file] [log] [blame]
Santos Cordon5d2c1e62014-11-21 15:20:15 -08001/*
2 * Copyright (C) 2014 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.server.telecom;
18
Sailesh Nepalcf855622015-07-28 19:22:14 -070019import android.content.BroadcastReceiver;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080020import android.content.ComponentName;
21import android.content.Context;
22import android.content.Intent;
Sailesh Nepalcf855622015-07-28 19:22:14 -070023import android.content.IntentFilter;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080024import android.content.ServiceConnection;
Svetoslavcdfd2302015-06-25 19:07:31 -070025import android.content.pm.PackageManagerInternal;
26import android.database.ContentObserver;
27import android.net.Uri;
28import android.os.Handler;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080029import android.os.IBinder;
Svetoslavcdfd2302015-06-25 19:07:31 -070030import android.os.Looper;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080031import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.UserHandle;
Svetoslavcdfd2302015-06-25 19:07:31 -070034import android.provider.Settings;
35import android.telecom.DefaultDialerManager;
Sailesh Nepalcf855622015-07-28 19:22:14 -070036import android.telecom.PhoneAccountHandle;
37import android.telecom.TelecomManager;
38import android.telephony.CarrierConfigManager;
Svetoslava5a0d942015-07-01 19:49:58 -070039import android.util.IntArray;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080040import android.util.Slog;
41
Svetoslava5a0d942015-07-01 19:49:58 -070042import android.util.SparseBooleanArray;
43import com.android.internal.annotations.GuardedBy;
Svetoslavcdfd2302015-06-25 19:07:31 -070044import com.android.internal.telephony.SmsApplication;
45import com.android.server.LocalServices;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080046import com.android.server.SystemService;
Sailesh Nepalcf855622015-07-28 19:22:14 -070047import com.android.server.pm.UserManagerService;
Santos Cordon5d2c1e62014-11-21 15:20:15 -080048
49/**
50 * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
51 * to run in the system-server process so once it is loaded into memory it will stay running.
52 * @hide
53 */
54public class TelecomLoaderService extends SystemService {
55 private static final String TAG = "TelecomLoaderService";
56
57 private class TelecomServiceConnection implements ServiceConnection {
58 @Override
59 public void onServiceConnected(ComponentName name, IBinder service) {
60 // Normally, we would listen for death here, but since telecom runs in the same process
61 // as this loader (process="system") thats redundant here.
62 try {
63 service.linkToDeath(new IBinder.DeathRecipient() {
64 @Override
65 public void binderDied() {
66 connectToTelecom();
67 }
68 }, 0);
Svetoslavcdfd2302015-06-25 19:07:31 -070069 SmsApplication.getDefaultMmsApplication(mContext, false);
Santos Cordon5d2c1e62014-11-21 15:20:15 -080070 ServiceManager.addService(Context.TELECOM_SERVICE, service);
Svetoslava5a0d942015-07-01 19:49:58 -070071
72 synchronized (mLock) {
Sailesh Nepalcf855622015-07-28 19:22:14 -070073 if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null
74 || mDefaultSimCallManagerRequests != null) {
Svetoslava5a0d942015-07-01 19:49:58 -070075 final PackageManagerInternal packageManagerInternal = LocalServices
76 .getService(PackageManagerInternal.class);
77
78 if (mDefaultSmsAppRequests != null) {
79 ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
80 mContext, true);
81 if (smsComponent != null) {
82 final int requestCount = mDefaultSmsAppRequests.size();
83 for (int i = requestCount - 1; i >= 0; i--) {
84 final int userid = mDefaultSmsAppRequests.get(i);
85 mDefaultSmsAppRequests.remove(i);
86 packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
87 smsComponent.getPackageName(), userid);
88 }
89 }
90 }
91
92 if (mDefaultDialerAppRequests != null) {
93 String packageName = DefaultDialerManager.getDefaultDialerApplication(
94 mContext);
95 if (packageName != null) {
96 final int requestCount = mDefaultDialerAppRequests.size();
97 for (int i = requestCount - 1; i >= 0; i--) {
98 final int userId = mDefaultDialerAppRequests.get(i);
99 mDefaultDialerAppRequests.remove(i);
100 packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
101 packageName, userId);
102 }
103 }
104 }
Sailesh Nepalcf855622015-07-28 19:22:14 -0700105 if (mDefaultSimCallManagerRequests != null) {
106 TelecomManager telecomManager =
107 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
108 PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager();
109 if (phoneAccount != null) {
110 final int requestCount = mDefaultSimCallManagerRequests.size();
111 final String packageName =
112 phoneAccount.getComponentName().getPackageName();
113 for (int i = requestCount - 1; i >= 0; i--) {
114 final int userId = mDefaultSimCallManagerRequests.get(i);
115 mDefaultSimCallManagerRequests.remove(i);
116 packageManagerInternal
117 .grantDefaultPermissionsToDefaultSimCallManager(
118 packageName, userId);
119 }
120 }
121 }
Svetoslava5a0d942015-07-01 19:49:58 -0700122 }
123 }
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800124 } catch (RemoteException e) {
125 Slog.w(TAG, "Failed linking to death.");
126 }
127 }
128
129 @Override
130 public void onServiceDisconnected(ComponentName name) {
131 connectToTelecom();
132 }
133 }
134
135 private static final ComponentName SERVICE_COMPONENT = new ComponentName(
136 "com.android.server.telecom",
Ihab Awadc4959ab2015-02-06 17:01:49 -0800137 "com.android.server.telecom.components.TelecomService");
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800138
139 private static final String SERVICE_ACTION = "com.android.ITelecomService";
140
Svetoslava5a0d942015-07-01 19:49:58 -0700141 private final Object mLock = new Object();
142
143 @GuardedBy("mLock")
144 private IntArray mDefaultSmsAppRequests;
145
146 @GuardedBy("mLock")
147 private IntArray mDefaultDialerAppRequests;
148
Sailesh Nepalcf855622015-07-28 19:22:14 -0700149 @GuardedBy("mLock")
150 private IntArray mDefaultSimCallManagerRequests;
151
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800152 private final Context mContext;
Svetoslava5a0d942015-07-01 19:49:58 -0700153
154 @GuardedBy("mLock")
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800155 private TelecomServiceConnection mServiceConnection;
156
157 public TelecomLoaderService(Context context) {
158 super(context);
159 mContext = context;
Svetoslavcdfd2302015-06-25 19:07:31 -0700160 registerDefaultAppProviders();
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800161 }
162
163 @Override
164 public void onStart() {
165 }
166
167 @Override
168 public void onBootPhase(int phase) {
169 if (phase == PHASE_ACTIVITY_MANAGER_READY) {
Svetoslavcdfd2302015-06-25 19:07:31 -0700170 registerDefaultAppNotifier();
Sailesh Nepalcf855622015-07-28 19:22:14 -0700171 registerCarrierConfigChangedReceiver();
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800172 connectToTelecom();
173 }
174 }
175
176 private void connectToTelecom() {
Svetoslava5a0d942015-07-01 19:49:58 -0700177 synchronized (mLock) {
178 if (mServiceConnection != null) {
179 // TODO: Is unbinding worth doing or wait for system to rebind?
180 mContext.unbindService(mServiceConnection);
181 mServiceConnection = null;
182 }
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800183
Svetoslava5a0d942015-07-01 19:49:58 -0700184 TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
185 Intent intent = new Intent(SERVICE_ACTION);
186 intent.setComponent(SERVICE_COMPONENT);
187 int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
188 | Context.BIND_AUTO_CREATE;
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800189
Svetoslava5a0d942015-07-01 19:49:58 -0700190 // Bind to Telecom and register the service
Xiaohui Chene4de5a02015-09-22 15:33:31 -0700191 if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
Svetoslava5a0d942015-07-01 19:49:58 -0700192 mServiceConnection = serviceConnection;
193 }
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800194 }
195 }
Svetoslavcdfd2302015-06-25 19:07:31 -0700196
Svetoslava5a0d942015-07-01 19:49:58 -0700197
Svetoslavcdfd2302015-06-25 19:07:31 -0700198 private void registerDefaultAppProviders() {
199 final PackageManagerInternal packageManagerInternal = LocalServices.getService(
200 PackageManagerInternal.class);
201
202 // Set a callback for the package manager to query the default sms app.
203 packageManagerInternal.setSmsAppPackagesProvider(
204 new PackageManagerInternal.PackagesProvider() {
205 @Override
206 public String[] getPackages(int userId) {
Svetoslava5a0d942015-07-01 19:49:58 -0700207 synchronized (mLock) {
208 if (mServiceConnection == null) {
209 if (mDefaultSmsAppRequests == null) {
210 mDefaultSmsAppRequests = new IntArray();
211 }
212 mDefaultSmsAppRequests.add(userId);
213 return null;
214 }
215 }
Svetoslavcdfd2302015-06-25 19:07:31 -0700216 ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
217 mContext, true);
218 if (smsComponent != null) {
219 return new String[]{smsComponent.getPackageName()};
220 }
221 return null;
222 }
223 });
224
225 // Set a callback for the package manager to query the default dialer app.
226 packageManagerInternal.setDialerAppPackagesProvider(
227 new PackageManagerInternal.PackagesProvider() {
228 @Override
229 public String[] getPackages(int userId) {
Svetoslava5a0d942015-07-01 19:49:58 -0700230 synchronized (mLock) {
231 if (mServiceConnection == null) {
232 if (mDefaultDialerAppRequests == null) {
233 mDefaultDialerAppRequests = new IntArray();
234 }
235 mDefaultDialerAppRequests.add(userId);
236 return null;
237 }
238 }
Svetoslavcdfd2302015-06-25 19:07:31 -0700239 String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
240 if (packageName != null) {
241 return new String[]{packageName};
242 }
243 return null;
244 }
245 });
Sailesh Nepalcf855622015-07-28 19:22:14 -0700246
247 // Set a callback for the package manager to query the default sim call manager.
248 packageManagerInternal.setSimCallManagerPackagesProvider(
249 new PackageManagerInternal.PackagesProvider() {
250 @Override
251 public String[] getPackages(int userId) {
252 synchronized (mLock) {
253 if (mServiceConnection == null) {
254 if (mDefaultSimCallManagerRequests == null) {
255 mDefaultSimCallManagerRequests = new IntArray();
256 }
257 mDefaultSimCallManagerRequests.add(userId);
258 return null;
259 }
260 }
261 TelecomManager telecomManager =
262 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
263 PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
264 if (phoneAccount != null) {
265 return new String[]{phoneAccount.getComponentName().getPackageName()};
266 }
267 return null;
268 }
269 });
Svetoslavcdfd2302015-06-25 19:07:31 -0700270 }
271
272 private void registerDefaultAppNotifier() {
273 final PackageManagerInternal packageManagerInternal = LocalServices.getService(
274 PackageManagerInternal.class);
275
276 // Notify the package manager on default app changes
277 final Uri defaultSmsAppUri = Settings.Secure.getUriFor(
278 Settings.Secure.SMS_DEFAULT_APPLICATION);
279 final Uri defaultDialerAppUri = Settings.Secure.getUriFor(
280 Settings.Secure.DIALER_DEFAULT_APPLICATION);
281
282 ContentObserver contentObserver = new ContentObserver(
283 new Handler(Looper.getMainLooper())) {
284 @Override
285 public void onChange(boolean selfChange, Uri uri, int userId) {
286 if (defaultSmsAppUri.equals(uri)) {
287 ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
288 mContext, true);
289 if (smsComponent != null) {
290 packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
291 smsComponent.getPackageName(), userId);
292 }
293 } else if (defaultDialerAppUri.equals(uri)) {
294 String packageName = DefaultDialerManager.getDefaultDialerApplication(
295 mContext);
296 if (packageName != null) {
297 packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
298 packageName, userId);
299 }
Sailesh Nepalcf855622015-07-28 19:22:14 -0700300 updateSimCallManagerPermissions(packageManagerInternal, userId);
Svetoslavcdfd2302015-06-25 19:07:31 -0700301 }
302 }
303 };
304
305 mContext.getContentResolver().registerContentObserver(defaultSmsAppUri,
306 false, contentObserver, UserHandle.USER_ALL);
307 mContext.getContentResolver().registerContentObserver(defaultDialerAppUri,
308 false, contentObserver, UserHandle.USER_ALL);
309 }
Sailesh Nepalcf855622015-07-28 19:22:14 -0700310
311
312 private void registerCarrierConfigChangedReceiver() {
313 final PackageManagerInternal packageManagerInternal = LocalServices.getService(
314 PackageManagerInternal.class);
315 BroadcastReceiver receiver = new BroadcastReceiver() {
316 @Override
317 public void onReceive(Context context, Intent intent) {
318 if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
319 for (int userId : UserManagerService.getInstance().getUserIds()) {
320 updateSimCallManagerPermissions(packageManagerInternal, userId);
321 }
322 }
323 }
324 };
325
326 mContext.registerReceiverAsUser(receiver, UserHandle.ALL,
327 new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED), null, null);
328 }
329
330 private void updateSimCallManagerPermissions(PackageManagerInternal packageManagerInternal,
331 int userId) {
332 TelecomManager telecomManager =
333 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
334 PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
335 if (phoneAccount != null) {
336 Slog.i(TAG, "updating sim call manager permissions for userId:" + userId);
337 String packageName = phoneAccount.getComponentName().getPackageName();
338 packageManagerInternal.grantDefaultPermissionsToDefaultSimCallManager(
339 packageName, userId);
340 }
341 }
Santos Cordon5d2c1e62014-11-21 15:20:15 -0800342}