SmsApplication.java revision ac9c712e8ac929fec2f91f738d85148919ceeebe
1/*
2 * Copyright (C) 2013 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.internal.telephony;
18
19import android.Manifest.permission;
20import android.app.AppOpsManager;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.content.pm.ActivityInfo;
26import android.content.pm.PackageInfo;
27import android.content.pm.PackageManager;
28import android.content.pm.ResolveInfo;
29import android.content.pm.ServiceInfo;
30import android.content.pm.PackageManager.NameNotFoundException;
31import android.content.res.Resources;
32import android.net.Uri;
33import android.provider.Settings;
34import android.provider.Telephony.Sms.Intents;
35import android.telephony.Rlog;
36import android.telephony.TelephonyManager;
37import com.android.internal.content.PackageMonitor;
38
39import java.util.Collection;
40import java.util.HashMap;
41import java.util.List;
42
43/**
44 * Class for managing the primary application that we will deliver SMS/MMS messages to
45 *
46 * {@hide}
47 */
48public final class SmsApplication {
49    static final String LOG_TAG = "SmsApplication";
50    private static final String PHONE_PACKAGE_NAME = "com.android.phone";
51    private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
52
53    private static final String SCHEME_SMS = "sms";
54    private static final String SCHEME_SMSTO = "smsto";
55    private static final String SCHEME_MMS = "mms";
56    private static final String SCHEME_MMSTO = "mmsto";
57
58    private static SmsPackageMonitor sSmsPackageMonitor = null;
59
60    public static class SmsApplicationData {
61        /**
62         * Name of this SMS app for display.
63         */
64        public String mApplicationName;
65
66        /**
67         * Package name for this SMS app.
68         */
69        public String mPackageName;
70
71        /**
72         * The class name of the SMS_DELIVER_ACTION receiver in this app.
73         */
74        public String mSmsReceiverClass;
75
76        /**
77         * The class name of the WAP_PUSH_DELIVER_ACTION receiver in this app.
78         */
79        public String mMmsReceiverClass;
80
81        /**
82         * The class name of the ACTION_RESPOND_VIA_MESSAGE intent in this app.
83         */
84        public String mRespondViaMessageClass;
85
86        /**
87         * The class name of the ACTION_SENDTO intent in this app.
88         */
89        public String mSendToClass;
90
91        /**
92         * The user-id for this application
93         */
94        public int mUid;
95
96        /**
97         * Returns true if this SmsApplicationData is complete (all intents handled).
98         * @return
99         */
100        public boolean isComplete() {
101            return (mSmsReceiverClass != null && mMmsReceiverClass != null
102                    && mRespondViaMessageClass != null && mSendToClass != null);
103        }
104
105        public SmsApplicationData(String applicationName, String packageName, int uid) {
106            mApplicationName = applicationName;
107            mPackageName = packageName;
108            mUid = uid;
109        }
110    }
111
112    /**
113     * Returns the list of available SMS apps defined as apps that are registered for both the
114     * SMS_RECEIVED_ACTION (SMS) and WAP_PUSH_RECEIVED_ACTION (MMS) broadcasts (and their broadcast
115     * receivers are enabled)
116     *
117     * Requirements to be an SMS application:
118     * Implement SMS_DELIVER_ACTION broadcast receiver.
119     * Require BROADCAST_SMS permission.
120     *
121     * Implement WAP_PUSH_DELIVER_ACTION broadcast receiver.
122     * Require BROADCAST_WAP_PUSH permission.
123     *
124     * Implement RESPOND_VIA_MESSAGE intent.
125     * Support smsto Uri scheme.
126     * Require SEND_RESPOND_VIA_MESSAGE permission.
127     *
128     * Implement ACTION_SENDTO intent.
129     * Support smsto Uri scheme.
130     */
131    public static Collection<SmsApplicationData> getApplicationCollection(Context context) {
132        PackageManager packageManager = context.getPackageManager();
133
134        // Get the list of apps registered for SMS
135        Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
136        List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceivers(intent, 0);
137
138        HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
139
140        // Add one entry to the map for every sms receiver (ignoring duplicate sms receivers)
141        for (ResolveInfo resolveInfo : smsReceivers) {
142            final ActivityInfo activityInfo = resolveInfo.activityInfo;
143            if (activityInfo == null) {
144                continue;
145            }
146            if (!permission.BROADCAST_SMS.equals(activityInfo.permission)) {
147                continue;
148            }
149            final String packageName = activityInfo.packageName;
150            if (!receivers.containsKey(packageName)) {
151                final String applicationName = resolveInfo.loadLabel(packageManager).toString();
152                final SmsApplicationData smsApplicationData = new SmsApplicationData(
153                        applicationName, packageName, activityInfo.applicationInfo.uid);
154                smsApplicationData.mSmsReceiverClass = activityInfo.name;
155                receivers.put(packageName, smsApplicationData);
156            }
157        }
158
159        // Update any existing entries with mms receiver class
160        intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION);
161        intent.setDataAndType(null, "application/vnd.wap.mms-message");
162        List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceivers(intent, 0);
163        for (ResolveInfo resolveInfo : mmsReceivers) {
164            final ActivityInfo activityInfo = resolveInfo.activityInfo;
165            if (activityInfo == null) {
166                continue;
167            }
168            if (!permission.BROADCAST_WAP_PUSH.equals(activityInfo.permission)) {
169                continue;
170            }
171            final String packageName = activityInfo.packageName;
172            final SmsApplicationData smsApplicationData = receivers.get(packageName);
173            if (smsApplicationData != null) {
174                smsApplicationData.mMmsReceiverClass = activityInfo.name;
175            }
176        }
177
178        // Update any existing entries with respond via message intent class.
179        intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE,
180                Uri.fromParts(SCHEME_SMSTO, "", null));
181        List<ResolveInfo> respondServices = packageManager.queryIntentServices(intent, 0);
182        for (ResolveInfo resolveInfo : respondServices) {
183            final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
184            if (serviceInfo == null) {
185                continue;
186            }
187            if (!permission.SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
188                continue;
189            }
190            final String packageName = serviceInfo.packageName;
191            final SmsApplicationData smsApplicationData = receivers.get(packageName);
192            if (smsApplicationData != null) {
193                smsApplicationData.mRespondViaMessageClass = serviceInfo.name;
194            }
195        }
196
197        // Update any existing entries with supports send to.
198        intent = new Intent(Intent.ACTION_SENDTO,
199                Uri.fromParts(SCHEME_SMSTO, "", null));
200        List<ResolveInfo> sendToActivities = packageManager.queryIntentActivities(intent, 0);
201        for (ResolveInfo resolveInfo : sendToActivities) {
202            final ActivityInfo activityInfo = resolveInfo.activityInfo;
203            if (activityInfo == null) {
204                continue;
205            }
206            final String packageName = activityInfo.packageName;
207            final SmsApplicationData smsApplicationData = receivers.get(packageName);
208            if (smsApplicationData != null) {
209                smsApplicationData.mSendToClass = activityInfo.name;
210            }
211        }
212
213        // Remove any entries for which we did not find all required intents.
214        for (ResolveInfo resolveInfo : smsReceivers) {
215            final ActivityInfo activityInfo = resolveInfo.activityInfo;
216            if (activityInfo == null) {
217                continue;
218            }
219            final String packageName = activityInfo.packageName;
220            final SmsApplicationData smsApplicationData = receivers.get(packageName);
221            if (smsApplicationData != null) {
222                if (!smsApplicationData.isComplete()) {
223                    receivers.remove(packageName);
224                }
225            }
226        }
227        return receivers.values();
228    }
229
230    /**
231     * Checks to see if we have a valid installed SMS application for the specified package name
232     * @return Data for the specified package name or null if there isn't one
233     */
234    private static SmsApplicationData getApplicationForPackage(
235            Collection<SmsApplicationData> applications, String packageName) {
236        if (packageName == null) {
237            return null;
238        }
239        // Is there an entry in the application list for the specified package?
240        for (SmsApplicationData application : applications) {
241            if (application.mPackageName.contentEquals(packageName)) {
242                return application;
243            }
244        }
245        return null;
246    }
247
248    /**
249     * Get the application we will use for delivering SMS/MMS messages.
250     *
251     * We return the preferred sms application with the following order of preference:
252     * (1) User selected SMS app (if selected, and if still valid)
253     * (2) Android Messaging (if installed)
254     * (3) The currently configured highest priority broadcast receiver
255     * (4) Null
256     */
257    private static SmsApplicationData getApplication(Context context, boolean updateIfNeeded) {
258        TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
259        if (!tm.isSmsCapable()) {
260            // No phone, no SMS
261            return null;
262        }
263
264        Collection<SmsApplicationData> applications = getApplicationCollection(context);
265
266        // Determine which application receives the broadcast
267        String defaultApplication = Settings.Secure.getString(context.getContentResolver(),
268                Settings.Secure.SMS_DEFAULT_APPLICATION);
269
270        SmsApplicationData applicationData = null;
271        if (defaultApplication != null) {
272            applicationData = getApplicationForPackage(applications, defaultApplication);
273        }
274        // Picking a new SMS app requires AppOps and Settings.Secure permissions, so we only do
275        // this if the caller asked us to.
276        if (updateIfNeeded && applicationData == null) {
277            // Try to find the default SMS package for this device
278            Resources r = context.getResources();
279            String defaultPackage =
280                    r.getString(com.android.internal.R.string.default_sms_application);
281            applicationData = getApplicationForPackage(applications, defaultPackage);
282
283            if (applicationData == null) {
284                // Are there any applications?
285                if (applications.size() != 0) {
286                    applicationData = (SmsApplicationData)applications.toArray()[0];
287                }
288            }
289
290            // If we found a new default app, update the setting
291            if (applicationData != null) {
292                setDefaultApplication(applicationData.mPackageName, context);
293            }
294        }
295
296        // If we found a package, make sure AppOps permissions are set up correctly
297        if (applicationData != null) {
298            AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
299
300            // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
301            // are checking is for our current uid. Doing this check from the unprivileged current
302            // SMS app allows us to tell the current SMS app that it is not in a good state and
303            // needs to ask to be the current SMS app again to work properly.
304            if (updateIfNeeded || applicationData.mUid == android.os.Process.myUid()) {
305                // Verify that the SMS app has permissions
306                int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
307                        applicationData.mPackageName);
308                if (mode != AppOpsManager.MODE_ALLOWED) {
309                    Rlog.e(LOG_TAG, applicationData.mPackageName + " lost OP_WRITE_SMS: " +
310                            (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
311                    if (updateIfNeeded) {
312                        appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
313                                applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
314                    } else {
315                        // We can not return a package if permissions are not set up correctly
316                        applicationData = null;
317                    }
318                }
319            }
320
321            // We can only verify the phone and BT app's permissions from a privileged caller
322            if (updateIfNeeded) {
323                // Ensure this component is still configured as the preferred activity. Usually the
324                // current SMS app will already be the preferred activity - but checking whether or
325                // not this is true is just as expensive as reconfiguring the preferred activity so
326                // we just reconfigure every time.
327                PackageManager packageManager = context.getPackageManager();
328                configurePreferredActivity(packageManager, new ComponentName(
329                        applicationData.mPackageName, applicationData.mSendToClass));
330
331                // Verify that the phone and BT app has permissions
332                try {
333                    PackageInfo info = packageManager.getPackageInfo(PHONE_PACKAGE_NAME, 0);
334                    int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
335                            PHONE_PACKAGE_NAME);
336                    if (mode != AppOpsManager.MODE_ALLOWED) {
337                        Rlog.e(LOG_TAG, PHONE_PACKAGE_NAME + " lost OP_WRITE_SMS:  (fixing)");
338                        appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
339                                PHONE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
340                    }
341                } catch (NameNotFoundException e) {
342                    // No phone app on this device (unexpected, even for non-phone devices)
343                    Rlog.e(LOG_TAG, "Phone package not found: " + PHONE_PACKAGE_NAME);
344                    applicationData = null;
345                }
346
347                try {
348                    PackageInfo info = packageManager.getPackageInfo(BLUETOOTH_PACKAGE_NAME, 0);
349                    int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
350                            BLUETOOTH_PACKAGE_NAME);
351                    if (mode != AppOpsManager.MODE_ALLOWED) {
352                        Rlog.e(LOG_TAG, BLUETOOTH_PACKAGE_NAME + " lost OP_WRITE_SMS:  (fixing)");
353                        appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
354                                BLUETOOTH_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
355                    }
356                } catch (NameNotFoundException e) {
357                    // No BT app on this device
358                    Rlog.e(LOG_TAG, "Bluetooth package not found: " + BLUETOOTH_PACKAGE_NAME);
359                }
360            }
361        }
362        return applicationData;
363    }
364
365    /**
366     * Sets the specified package as the default SMS/MMS application. The caller of this method
367     * needs to have permission to set AppOps and write to secure settings.
368     */
369    public static void setDefaultApplication(String packageName, Context context) {
370        TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
371        if (!tm.isSmsCapable()) {
372            // No phone, no SMS
373            return;
374        }
375
376        // Get old package name
377        String oldPackageName = Settings.Secure.getString(context.getContentResolver(),
378                Settings.Secure.SMS_DEFAULT_APPLICATION);
379
380        if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
381            // No change
382            return;
383        }
384
385        // We only make the change if the new package is valid
386        PackageManager packageManager = context.getPackageManager();
387        Collection<SmsApplicationData> applications = getApplicationCollection(context);
388        SmsApplicationData applicationData = getApplicationForPackage(applications, packageName);
389        if (applicationData != null) {
390            // Ignore OP_WRITE_SMS for the previously configured default SMS app.
391            AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
392            if (oldPackageName != null) {
393                try {
394                    PackageInfo info = packageManager.getPackageInfo(oldPackageName,
395                            PackageManager.GET_UNINSTALLED_PACKAGES);
396                    appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
397                            oldPackageName, AppOpsManager.MODE_IGNORED);
398                } catch (NameNotFoundException e) {
399                    Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
400                }
401            }
402
403            // Update the secure setting.
404            Settings.Secure.putString(context.getContentResolver(),
405                    Settings.Secure.SMS_DEFAULT_APPLICATION, applicationData.mPackageName);
406
407            // Configure this as the preferred activity for SENDTO sms/mms intents
408            configurePreferredActivity(packageManager, new ComponentName(
409                    applicationData.mPackageName, applicationData.mSendToClass));
410
411            // Allow OP_WRITE_SMS for the newly configured default SMS app.
412            appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
413                    applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
414
415            // Phone needs to always have this permission to write to the sms database
416            try {
417                PackageInfo info = packageManager.getPackageInfo(PHONE_PACKAGE_NAME, 0);
418                appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
419                        PHONE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
420            } catch (NameNotFoundException e) {
421                // No phone app on this device (unexpected, even for non-phone devices)
422                Rlog.e(LOG_TAG, "Phone package not found: " + PHONE_PACKAGE_NAME);
423            }
424
425            // BT needs to always have this permission to write to the sms database
426            try {
427                PackageInfo info = packageManager.getPackageInfo(BLUETOOTH_PACKAGE_NAME, 0);
428                appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
429                        BLUETOOTH_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
430            } catch (NameNotFoundException e) {
431                // No BT app on this device
432                Rlog.e(LOG_TAG, "Bluetooth package not found: " + BLUETOOTH_PACKAGE_NAME);
433            }
434        }
435    }
436
437    /**
438     * Tracks package changes and ensures that the default SMS app is always configured to be the
439     * preferred activity for SENDTO sms/mms intents.
440     */
441    private static final class SmsPackageMonitor extends PackageMonitor {
442        final Context mContext;
443
444        public SmsPackageMonitor(Context context) {
445            super();
446            mContext = context;
447        }
448
449        @Override
450        public void onPackageDisappeared(String packageName, int reason) {
451            onPackageChanged(packageName);
452        }
453
454        @Override
455        public void onPackageAppeared(String packageName, int reason) {
456            onPackageChanged(packageName);
457        }
458
459        @Override
460        public void onPackageModified(String packageName) {
461            onPackageChanged(packageName);
462        }
463
464        private void onPackageChanged(String packageName) {
465            PackageManager packageManager = mContext.getPackageManager();
466            // Ensure this component is still configured as the preferred activity
467            ComponentName componentName = getDefaultSendToApplication(mContext, true);
468            if (componentName != null) {
469                configurePreferredActivity(packageManager, componentName);
470            }
471        }
472    }
473
474    public static void initSmsPackageMonitor(Context context) {
475        sSmsPackageMonitor = new SmsPackageMonitor(context);
476        sSmsPackageMonitor.register(context, context.getMainLooper(), false);
477    }
478
479    private static void configurePreferredActivity(PackageManager packageManager,
480            ComponentName componentName) {
481        // Add the four activity preferences we want to direct to this app.
482        replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
483        replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
484        replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
485        replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
486    }
487
488    /**
489     * Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
490     */
491    private static void replacePreferredActivity(PackageManager packageManager,
492            ComponentName componentName, String scheme) {
493        // Build the set of existing activities that handle this scheme
494        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
495        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
496                intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
497
498        // Build the set of ComponentNames for these activities
499        final int n = resolveInfoList.size();
500        ComponentName[] set = new ComponentName[n];
501        for (int i = 0; i < n; i++) {
502            ResolveInfo info = resolveInfoList.get(i);
503            set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
504        }
505
506        // Update the preferred SENDTO activity for the specified scheme
507        IntentFilter intentFilter = new IntentFilter();
508        intentFilter.addAction(Intent.ACTION_SENDTO);
509        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
510        intentFilter.addDataScheme(scheme);
511        packageManager.replacePreferredActivity(intentFilter,
512                IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
513                set, componentName);
514    }
515
516    /**
517     * Returns SmsApplicationData for this package if this package is capable of being set as the
518     * default SMS application.
519     */
520    public static SmsApplicationData getSmsApplicationData(String packageName, Context context) {
521        Collection<SmsApplicationData> applications = getApplicationCollection(context);
522        return getApplicationForPackage(applications, packageName);
523    }
524
525    /**
526     * Gets the default SMS application
527     * @param context context from the calling app
528     * @param updateIfNeeded update the default app if there is no valid default app configured.
529     * @return component name of the app and class to deliver SMS messages to
530     */
531    public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
532        ComponentName component = null;
533        SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded);
534        if (smsApplicationData != null) {
535            component = new ComponentName(smsApplicationData.mPackageName,
536                    smsApplicationData.mSmsReceiverClass);
537        }
538        return component;
539    }
540
541    /**
542     * Gets the default MMS application
543     * @param context context from the calling app
544     * @param updateIfNeeded update the default app if there is no valid default app configured.
545     * @return component name of the app and class to deliver MMS messages to
546     */
547    public static ComponentName getDefaultMmsApplication(Context context, boolean updateIfNeeded) {
548        ComponentName component = null;
549        SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded);
550        if (smsApplicationData != null) {
551            component = new ComponentName(smsApplicationData.mPackageName,
552                    smsApplicationData.mMmsReceiverClass);
553        }
554        return component;
555    }
556
557    /**
558     * Gets the default Respond Via Message application
559     * @param context context from the calling app
560     * @param updateIfNeeded update the default app if there is no valid default app configured.
561     * @return component name of the app and class to direct Respond Via Message intent to
562     */
563    public static ComponentName getDefaultRespondViaMessageApplication(Context context,
564            boolean updateIfNeeded) {
565        ComponentName component = null;
566        SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded);
567        if (smsApplicationData != null) {
568            component = new ComponentName(smsApplicationData.mPackageName,
569                    smsApplicationData.mRespondViaMessageClass);
570        }
571        return component;
572    }
573
574    /**
575     * Gets the default Send To (smsto) application
576     * @param context context from the calling app
577     * @param updateIfNeeded update the default app if there is no valid default app configured.
578     * @return component name of the app and class to direct SEND_TO (smsto) intent to
579     */
580    public static ComponentName getDefaultSendToApplication(Context context,
581            boolean updateIfNeeded) {
582        ComponentName component = null;
583        SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded);
584        if (smsApplicationData != null) {
585            component = new ComponentName(smsApplicationData.mPackageName,
586                    smsApplicationData.mSendToClass);
587        }
588        return component;
589    }
590
591    /**
592     * Returns whether need to write the SMS message to SMS database for this package.
593     */
594    public static boolean shouldWriteMessageForPackage(String packageName, Context context) {
595        if (packageName == null) return true;
596
597        String defaultSmsPackage = null;
598        ComponentName component = getDefaultSmsApplication(context, false);
599        if (component != null) {
600            defaultSmsPackage = component.getPackageName();
601        }
602
603        if ((defaultSmsPackage == null || !defaultSmsPackage.equals(packageName)) &&
604                !packageName.equals(BLUETOOTH_PACKAGE_NAME)) {
605            // To write the message for someone other than the default SMS and BT app
606            return true;
607        }
608
609        return false;
610    }
611}
612