1 /*
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 
17 package com.android.server.telecom;
18 
19 import android.app.role.RoleManager;
20 import android.content.BroadcastReceiver;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.ServiceConnection;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 import android.os.ServiceManager;
29 import android.os.UserHandle;
30 import android.telecom.DefaultDialerManager;
31 import android.telecom.PhoneAccountHandle;
32 import android.telecom.TelecomManager;
33 import android.telephony.CarrierConfigManager;
34 import android.util.IntArray;
35 import android.util.Slog;
36 
37 import com.android.internal.annotations.GuardedBy;
38 import com.android.internal.telephony.SmsApplication;
39 import com.android.server.LocalServices;
40 import com.android.server.SystemService;
41 import com.android.server.pm.UserManagerService;
42 import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
43 import com.android.server.pm.permission.PermissionManagerServiceInternal;
44 
45 /**
46  * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
47  * to run in the system-server process so once it is loaded into memory it will stay running.
48  * @hide
49  */
50 public class TelecomLoaderService extends SystemService {
51     private static final String TAG = "TelecomLoaderService";
52 
53     private class TelecomServiceConnection implements ServiceConnection {
54         @Override
onServiceConnected(ComponentName name, IBinder service)55         public void onServiceConnected(ComponentName name, IBinder service) {
56             // Normally, we would listen for death here, but since telecom runs in the same process
57             // as this loader (process="system") thats redundant here.
58             try {
59                 service.linkToDeath(new IBinder.DeathRecipient() {
60                     @Override
61                     public void binderDied() {
62                         connectToTelecom();
63                     }
64                 }, 0);
65                 SmsApplication.getDefaultMmsApplication(mContext, false);
66                 ServiceManager.addService(Context.TELECOM_SERVICE, service);
67 
68                 synchronized (mLock) {
69                     if (mDefaultSimCallManagerRequests != null) {
70                         final DefaultPermissionGrantPolicy permissionPolicy =
71                                 getDefaultPermissionGrantPolicy();
72                         if (mDefaultSimCallManagerRequests != null) {
73                             TelecomManager telecomManager =
74                                 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
75                             PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager();
76                             if (phoneAccount != null) {
77                                 final int requestCount = mDefaultSimCallManagerRequests.size();
78                                 final String packageName =
79                                     phoneAccount.getComponentName().getPackageName();
80                                 for (int i = requestCount - 1; i >= 0; i--) {
81                                     final int userId = mDefaultSimCallManagerRequests.get(i);
82                                     mDefaultSimCallManagerRequests.remove(i);
83                                     permissionPolicy
84                                             .grantDefaultPermissionsToDefaultSimCallManager(
85                                                     packageName, userId);
86                                 }
87                             }
88                         }
89                     }
90                 }
91             } catch (RemoteException e) {
92                 Slog.w(TAG, "Failed linking to death.");
93             }
94         }
95 
96         @Override
onServiceDisconnected(ComponentName name)97         public void onServiceDisconnected(ComponentName name) {
98             connectToTelecom();
99         }
100     }
101 
getDefaultPermissionGrantPolicy()102     private DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
103         return LocalServices.getService(PermissionManagerServiceInternal.class)
104                 .getDefaultPermissionGrantPolicy();
105     }
106 
107     private static final ComponentName SERVICE_COMPONENT = new ComponentName(
108             "com.android.server.telecom",
109             "com.android.server.telecom.components.TelecomService");
110 
111     private static final String SERVICE_ACTION = "com.android.ITelecomService";
112 
113     private final Object mLock = new Object();
114 
115     @GuardedBy("mLock")
116     private IntArray mDefaultSimCallManagerRequests;
117 
118     private final Context mContext;
119 
120     @GuardedBy("mLock")
121     private TelecomServiceConnection mServiceConnection;
122 
TelecomLoaderService(Context context)123     public TelecomLoaderService(Context context) {
124         super(context);
125         mContext = context;
126         registerDefaultAppProviders();
127     }
128 
129     @Override
onStart()130     public void onStart() {
131     }
132 
133     @Override
onBootPhase(int phase)134     public void onBootPhase(int phase) {
135         if (phase == PHASE_ACTIVITY_MANAGER_READY) {
136             registerDefaultAppNotifier();
137             registerCarrierConfigChangedReceiver();
138             connectToTelecom();
139         }
140     }
141 
connectToTelecom()142     private void connectToTelecom() {
143         synchronized (mLock) {
144             if (mServiceConnection != null) {
145                 // TODO: Is unbinding worth doing or wait for system to rebind?
146                 mContext.unbindService(mServiceConnection);
147                 mServiceConnection = null;
148             }
149 
150             TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
151             Intent intent = new Intent(SERVICE_ACTION);
152             intent.setComponent(SERVICE_COMPONENT);
153             int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
154                     | Context.BIND_AUTO_CREATE;
155 
156             // Bind to Telecom and register the service
157             if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
158                 mServiceConnection = serviceConnection;
159             }
160         }
161     }
162 
163 
registerDefaultAppProviders()164     private void registerDefaultAppProviders() {
165         final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
166 
167         // Set a callback for the permission grant policy to query the default sms app.
168         permissionPolicy.setSmsAppPackagesProvider(userId -> {
169             synchronized (mLock) {
170                 if (mServiceConnection == null) {
171                     return null;
172                 }
173             }
174             ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
175                     mContext, true);
176             if (smsComponent != null) {
177                 return new String[]{smsComponent.getPackageName()};
178             }
179             return null;
180         });
181 
182         // Set a callback for the permission grant policy to query the default dialer app.
183         permissionPolicy.setDialerAppPackagesProvider(userId -> {
184             synchronized (mLock) {
185                 if (mServiceConnection == null) {
186                     return null;
187                 }
188             }
189             String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
190             if (packageName != null) {
191                 return new String[]{packageName};
192             }
193             return null;
194         });
195 
196         // Set a callback for the permission grant policy to query the default sim call manager.
197         permissionPolicy.setSimCallManagerPackagesProvider(userId -> {
198             synchronized (mLock) {
199                 if (mServiceConnection == null) {
200                     if (mDefaultSimCallManagerRequests == null) {
201                         mDefaultSimCallManagerRequests = new IntArray();
202                     }
203                     mDefaultSimCallManagerRequests.add(userId);
204                     return null;
205                 }
206             }
207             TelecomManager telecomManager =
208                     (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
209             PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
210             if (phoneAccount != null) {
211                 return new String[]{phoneAccount.getComponentName().getPackageName()};
212             }
213             return null;
214         });
215     }
216 
registerDefaultAppNotifier()217     private void registerDefaultAppNotifier() {
218         final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
219         // Notify the package manager on default app changes
220         final RoleManager roleManager = mContext.getSystemService(RoleManager.class);
221         roleManager.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(),
222                 (roleName, user) -> updateSimCallManagerPermissions(permissionPolicy,
223                         user.getIdentifier()), UserHandle.ALL);
224     }
225 
226 
registerCarrierConfigChangedReceiver()227     private void registerCarrierConfigChangedReceiver() {
228         BroadcastReceiver receiver = new BroadcastReceiver() {
229             @Override
230             public void onReceive(Context context, Intent intent) {
231                 if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
232                     for (int userId : UserManagerService.getInstance().getUserIds()) {
233                         updateSimCallManagerPermissions(getDefaultPermissionGrantPolicy(), userId);
234                     }
235                 }
236             }
237         };
238 
239         mContext.registerReceiverAsUser(receiver, UserHandle.ALL,
240             new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED), null, null);
241     }
242 
updateSimCallManagerPermissions( DefaultPermissionGrantPolicy permissionGrantPolicy, int userId)243     private void updateSimCallManagerPermissions(
244             DefaultPermissionGrantPolicy permissionGrantPolicy, int userId) {
245         TelecomManager telecomManager =
246             (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
247         PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
248         if (phoneAccount != null) {
249             Slog.i(TAG, "updating sim call manager permissions for userId:" + userId);
250             String packageName = phoneAccount.getComponentName().getPackageName();
251             permissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager(
252                 packageName, userId);
253         }
254     }
255 }
256