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