Home | History | Annotate | Download | only in telecom
      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.content.BroadcastReceiver;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.content.ServiceConnection;
     25 import android.content.pm.PackageManagerInternal;
     26 import android.database.ContentObserver;
     27 import android.net.Uri;
     28 import android.os.Handler;
     29 import android.os.IBinder;
     30 import android.os.Looper;
     31 import android.os.RemoteException;
     32 import android.os.ServiceManager;
     33 import android.os.UserHandle;
     34 import android.provider.Settings;
     35 import android.telecom.DefaultDialerManager;
     36 import android.telecom.PhoneAccountHandle;
     37 import android.telecom.TelecomManager;
     38 import android.telephony.CarrierConfigManager;
     39 import android.util.IntArray;
     40 import android.util.Slog;
     41 
     42 import android.util.SparseBooleanArray;
     43 import com.android.internal.annotations.GuardedBy;
     44 import com.android.internal.telephony.SmsApplication;
     45 import com.android.server.LocalServices;
     46 import com.android.server.SystemService;
     47 import com.android.server.pm.UserManagerService;
     48 
     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  */
     54 public 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);
     69                 SmsApplication.getDefaultMmsApplication(mContext, false);
     70                 ServiceManager.addService(Context.TELECOM_SERVICE, service);
     71 
     72                 synchronized (mLock) {
     73                     if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null
     74                             || mDefaultSimCallManagerRequests != null) {
     75                         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                         }
    105                         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                         }
    122                     }
    123                 }
    124             } 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",
    137             "com.android.server.telecom.components.TelecomService");
    138 
    139     private static final String SERVICE_ACTION = "com.android.ITelecomService";
    140 
    141     private final Object mLock = new Object();
    142 
    143     @GuardedBy("mLock")
    144     private IntArray mDefaultSmsAppRequests;
    145 
    146     @GuardedBy("mLock")
    147     private IntArray mDefaultDialerAppRequests;
    148 
    149     @GuardedBy("mLock")
    150     private IntArray mDefaultSimCallManagerRequests;
    151 
    152     private final Context mContext;
    153 
    154     @GuardedBy("mLock")
    155     private TelecomServiceConnection mServiceConnection;
    156 
    157     public TelecomLoaderService(Context context) {
    158         super(context);
    159         mContext = context;
    160         registerDefaultAppProviders();
    161     }
    162 
    163     @Override
    164     public void onStart() {
    165     }
    166 
    167     @Override
    168     public void onBootPhase(int phase) {
    169         if (phase == PHASE_ACTIVITY_MANAGER_READY) {
    170             registerDefaultAppNotifier();
    171             registerCarrierConfigChangedReceiver();
    172             connectToTelecom();
    173         }
    174     }
    175 
    176     private void connectToTelecom() {
    177         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             }
    183 
    184             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;
    189 
    190             // Bind to Telecom and register the service
    191             if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
    192                 mServiceConnection = serviceConnection;
    193             }
    194         }
    195     }
    196 
    197 
    198     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) {
    207                 synchronized (mLock) {
    208                     if (mServiceConnection == null) {
    209                         if (mDefaultSmsAppRequests == null) {
    210                             mDefaultSmsAppRequests = new IntArray();
    211                         }
    212                         mDefaultSmsAppRequests.add(userId);
    213                         return null;
    214                     }
    215                 }
    216                 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) {
    230                 synchronized (mLock) {
    231                     if (mServiceConnection == null) {
    232                         if (mDefaultDialerAppRequests == null) {
    233                             mDefaultDialerAppRequests = new IntArray();
    234                         }
    235                         mDefaultDialerAppRequests.add(userId);
    236                         return null;
    237                     }
    238                 }
    239                 String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
    240                 if (packageName != null) {
    241                     return new String[]{packageName};
    242                 }
    243                 return null;
    244             }
    245         });
    246 
    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         });
    270     }
    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                     }
    300                     updateSimCallManagerPermissions(packageManagerInternal, userId);
    301                 }
    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     }
    310 
    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     }
    342 }
    343