• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.ActivityManager;
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.res.Resources;
26 import android.database.ContentObserver;
27 import android.net.Uri;
28 import android.os.Handler;
29 import android.os.Looper;
30 import android.os.UserHandle;
31 import android.provider.Settings;
32 import android.telecom.DefaultDialerManager;
33 import android.telecom.Log;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.internal.util.IndentingPrintWriter;
37 
38 import java.util.Objects;
39 import java.util.concurrent.ConcurrentHashMap;
40 import java.util.concurrent.Executor;
41 import java.util.function.IntConsumer;
42 
43 public class DefaultDialerCache {
44     private static final String LOG_TAG = "DefaultDialerCache";
45     @VisibleForTesting
46     public final Handler mHandler = new Handler(Looper.getMainLooper());
47     private final Context mContext;
48     private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
49     private final ComponentName mSystemDialerComponentName;
50     private final RoleManagerAdapter mRoleManagerAdapter;
51     private final ConcurrentHashMap<Integer, String> mCurrentDefaultDialerPerUser =
52             new ConcurrentHashMap<>();
53     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
54         @Override
55         public void onReceive(Context context, Intent intent) {
56             mHandler.post(() -> {
57                 Log.startSession("DDC.oR");
58                 try {
59                     String packageName;
60                     if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
61                         packageName = null;
62                     } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
63                             && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
64                         packageName = intent.getData().getSchemeSpecificPart();
65                     } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
66                         packageName = null;
67                     } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
68                         packageName = null;
69                     } else {
70                         return;
71                     }
72 
73                     refreshCachesForUsersWithPackage(packageName);
74                 } finally {
75                     Log.endSession();
76                 }
77             });
78         }
79     };
80     private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
81         @Override
82         public void onReceive(Context context, Intent intent) {
83             if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
84                 int removedUser = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
85                         UserHandle.USER_NULL);
86                 if (removedUser == UserHandle.USER_NULL) {
87                     Log.w(LOG_TAG, "Expected EXTRA_USER_HANDLE with ACTION_USER_REMOVED");
88                 } else {
89                     removeUserFromCache(removedUser);
90                     Log.i(LOG_TAG, "Removing user %s", removedUser);
91                 }
92             }
93         }
94     };
95     private final ContentObserver mDefaultDialerObserver = new ContentObserver(mHandler) {
96         @Override
97         public void onChange(boolean selfChange) {
98             Log.startSession("DDC.oC");
99             try {
100                 // We don't get the user ID of the user that changed here, so we'll have to
101                 // refresh all of the users.
102                 refreshCachesForUsersWithPackage(null);
103             } finally {
104                 Log.endSession();
105             }
106         }
107 
108         @Override
109         public boolean deliverSelfNotifications() {
110             return true;
111         }
112     };
113     private ComponentName mOverrideSystemDialerComponentName;
114 
DefaultDialerCache(Context context, DefaultDialerManagerAdapter defaultDialerManagerAdapter, RoleManagerAdapter roleManagerAdapter, TelecomSystem.SyncRoot lock)115     public DefaultDialerCache(Context context,
116             DefaultDialerManagerAdapter defaultDialerManagerAdapter,
117             RoleManagerAdapter roleManagerAdapter,
118             TelecomSystem.SyncRoot lock) {
119         mContext = context;
120         mDefaultDialerManagerAdapter = defaultDialerManagerAdapter;
121         mRoleManagerAdapter = roleManagerAdapter;
122 
123         Resources resources = mContext.getResources();
124         mSystemDialerComponentName = new ComponentName(resources.getString(
125                 com.android.internal.R.string.config_defaultDialer),
126                 resources.getString(R.string.incall_default_class));
127 
128         IntentFilter packageIntentFilter = new IntentFilter();
129         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
130         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
131         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
132         packageIntentFilter.addDataScheme("package");
133         packageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
134         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, packageIntentFilter, null, null);
135 
136         IntentFilter bootIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
137         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, bootIntentFilter, null, null);
138 
139         IntentFilter userRemovedFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
140         context.registerReceiver(mUserRemovedReceiver, userRemovedFilter);
141 
142         Uri defaultDialerSetting =
143                 Settings.Secure.getUriFor(Settings.Secure.DIALER_DEFAULT_APPLICATION);
144         context.getContentResolver()
145                 .registerContentObserver(defaultDialerSetting, false, mDefaultDialerObserver,
146                         UserHandle.USER_ALL);
147     }
148 
getBTInCallServicePackages()149     public String[] getBTInCallServicePackages() {
150         return mRoleManagerAdapter.getBTInCallService();
151     }
152 
getDefaultDialerApplication(int userId)153     public String getDefaultDialerApplication(int userId) {
154         if (userId == UserHandle.USER_CURRENT) {
155             userId = ActivityManager.getCurrentUser();
156         }
157 
158         if (userId < 0) {
159             Log.w(LOG_TAG, "Attempting to get default dialer for a meta-user %d", userId);
160             return null;
161         }
162 
163         // TODO: Re-enable this when we are able to use the cache once more.  RoleManager does not
164         // provide a means for being informed when the role holder changes at the current time.
165         //
166         //synchronized (mLock) {
167         //    String defaultDialer = mCurrentDefaultDialerPerUser.get(userId);
168         //    if (!TextUtils.isEmpty(defaultDialer)) {
169         //        return defaultDialer;
170         //    }
171         //}
172         return refreshCacheForUser(userId);
173     }
174 
getDefaultDialerApplication()175     public String getDefaultDialerApplication() {
176         return getDefaultDialerApplication(mContext.getUserId());
177     }
178 
setSystemDialerComponentName(ComponentName testComponentName)179     public void setSystemDialerComponentName(ComponentName testComponentName) {
180         mOverrideSystemDialerComponentName = testComponentName;
181     }
182 
getSystemDialerApplication()183     public String getSystemDialerApplication() {
184         if (mOverrideSystemDialerComponentName != null) {
185             return mOverrideSystemDialerComponentName.getPackageName();
186         }
187         return mSystemDialerComponentName.getPackageName();
188     }
189 
getSystemDialerComponent()190     public ComponentName getSystemDialerComponent() {
191         if (mOverrideSystemDialerComponentName != null) return mOverrideSystemDialerComponentName;
192         return mSystemDialerComponentName;
193     }
194 
getDialtactsSystemDialerComponent()195     public ComponentName getDialtactsSystemDialerComponent() {
196         final Resources resources = mContext.getResources();
197         return new ComponentName(getSystemDialerApplication(),
198                 resources.getString(R.string.dialer_default_class));
199     }
200 
observeDefaultDialerApplication(Executor executor, IntConsumer observer)201     public void observeDefaultDialerApplication(Executor executor, IntConsumer observer) {
202         mRoleManagerAdapter.observeDefaultDialerApp(executor, observer);
203     }
204 
isDefaultOrSystemDialer(String packageName, int userId)205     public boolean isDefaultOrSystemDialer(String packageName, int userId) {
206         String defaultDialer = getDefaultDialerApplication(userId);
207         return Objects.equals(packageName, defaultDialer)
208                 || Objects.equals(packageName, getSystemDialerApplication());
209     }
210 
setDefaultDialer(String packageName, int userId)211     public boolean setDefaultDialer(String packageName, int userId) {
212         boolean isChanged = mDefaultDialerManagerAdapter.setDefaultDialerApplication(
213                 mContext, packageName, userId);
214         if (isChanged) {
215             // Update the cache synchronously so that there is no delay in cache update.
216             mCurrentDefaultDialerPerUser.put(userId, packageName == null ? "" : packageName);
217         }
218         return isChanged;
219     }
220 
refreshCacheForUser(int userId)221     private String refreshCacheForUser(int userId) {
222         String currentDefaultDialer =
223                 mRoleManagerAdapter.getDefaultDialerApp(userId);
224         mCurrentDefaultDialerPerUser.put(userId, currentDefaultDialer == null ? "" :
225                 currentDefaultDialer);
226         return currentDefaultDialer;
227     }
228 
229     /**
230      * Refreshes the cache for users that currently have packageName as their cached default dialer.
231      * If packageName is null, refresh all caches.
232      *
233      * @param packageName Name of the affected package.
234      */
refreshCachesForUsersWithPackage(String packageName)235     private void refreshCachesForUsersWithPackage(String packageName) {
236         mCurrentDefaultDialerPerUser.forEach((userId, currentName) -> {
237             if (packageName == null || Objects.equals(packageName, currentName)) {
238                 String newDefaultDialer = refreshCacheForUser(userId);
239                 Log.v(LOG_TAG, "Refreshing default dialer for user %d: now %s",
240                         userId, newDefaultDialer);
241             }
242         });
243     }
244 
dumpCache(IndentingPrintWriter pw)245     public void dumpCache(IndentingPrintWriter pw) {
246         mCurrentDefaultDialerPerUser.forEach((k, v) -> pw.printf("User %d: %s\n", k, v));
247     }
248 
removeUserFromCache(int userId)249     private void removeUserFromCache(int userId) {
250         mCurrentDefaultDialerPerUser.remove(userId);
251     }
252 
253     /**
254      * registerContentObserver is really hard to mock out, so here is a getter method for the
255      * content observer for testing instead.
256      *
257      * @return The content observer
258      */
259     @VisibleForTesting
getContentObserver()260     public ContentObserver getContentObserver() {
261         return mDefaultDialerObserver;
262     }
263 
getRoleManagerAdapter()264     public RoleManagerAdapter getRoleManagerAdapter() {
265         return mRoleManagerAdapter;
266     }
267 
268     public interface DefaultDialerManagerAdapter {
getDefaultDialerApplication(Context context)269         String getDefaultDialerApplication(Context context);
270 
getDefaultDialerApplication(Context context, int userId)271         String getDefaultDialerApplication(Context context, int userId);
272 
setDefaultDialerApplication(Context context, String packageName, int userId)273         boolean setDefaultDialerApplication(Context context, String packageName, int userId);
274     }
275 
276     static class DefaultDialerManagerAdapterImpl implements DefaultDialerManagerAdapter {
277         @Override
getDefaultDialerApplication(Context context)278         public String getDefaultDialerApplication(Context context) {
279             return DefaultDialerManager.getDefaultDialerApplication(context);
280         }
281 
282         @Override
getDefaultDialerApplication(Context context, int userId)283         public String getDefaultDialerApplication(Context context, int userId) {
284             return DefaultDialerManager.getDefaultDialerApplication(context, userId);
285         }
286 
287         @Override
setDefaultDialerApplication(Context context, String packageName, int userId)288         public boolean setDefaultDialerApplication(Context context, String packageName,
289                 int userId) {
290             return DefaultDialerManager.setDefaultDialerApplication(context, packageName, userId);
291         }
292     }
293 }
294