• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package com.android.phone.vvm.omtp.sms;
17 
18 import android.content.BroadcastReceiver;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.provider.Telephony;
22 import android.provider.VoicemailContract;
23 import android.telecom.PhoneAccountHandle;
24 import android.telecom.Voicemail;
25 import android.telephony.SmsMessage;
26 import android.telephony.SubscriptionManager;
27 import android.util.Log;
28 
29 import com.android.internal.telephony.PhoneConstants;
30 import com.android.phone.PhoneGlobals;
31 import com.android.phone.PhoneUtils;
32 import com.android.phone.settings.VisualVoicemailSettingsUtil;
33 import com.android.phone.vvm.omtp.LocalLogHelper;
34 import com.android.phone.vvm.omtp.OmtpConstants;
35 import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
36 import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService;
37 import com.android.phone.vvm.omtp.sync.VoicemailsQueryHelper;
38 
39 /**
40  * Receive SMS messages and send for processing by the OMTP visual voicemail source.
41  */
42 public class OmtpMessageReceiver extends BroadcastReceiver {
43     private static final String TAG = "OmtpMessageReceiver";
44 
45     private Context mContext;
46     private PhoneAccountHandle mPhoneAccount;
47 
48     @Override
onReceive(Context context, Intent intent)49     public void onReceive(Context context, Intent intent) {
50         mContext = context;
51         mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
52                 intent.getExtras().getInt(PhoneConstants.PHONE_KEY));
53 
54         if (mPhoneAccount == null) {
55             Log.w(TAG, "Received message for null phone account");
56             return;
57         }
58 
59         if (!VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(mContext, mPhoneAccount)) {
60             Log.v(TAG, "Received vvm message for disabled vvm source.");
61             return;
62         }
63 
64         SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
65         StringBuilder messageBody = new StringBuilder();
66 
67         for (int i = 0; i < messages.length; i++) {
68             if (messages[i].mWrappedSmsMessage != null) {
69                 messageBody.append(messages[i].getMessageBody());
70             }
71         }
72 
73         WrappedMessageData messageData = OmtpSmsParser.parse(messageBody.toString());
74         if (messageData != null) {
75             if (messageData.getPrefix() == OmtpConstants.SYNC_SMS_PREFIX) {
76                 SyncMessage message = new SyncMessage(messageData);
77 
78                 Log.v(TAG, "Received SYNC sms for " + mPhoneAccount.getId() +
79                         " with event" + message.getSyncTriggerEvent());
80                 LocalLogHelper.log(TAG, "Received SYNC sms for " + mPhoneAccount.getId() +
81                         " with event" + message.getSyncTriggerEvent());
82                 processSync(message);
83             } else if (messageData.getPrefix() == OmtpConstants.STATUS_SMS_PREFIX) {
84                 Log.v(TAG, "Received STATUS sms for " + mPhoneAccount.getId());
85                 LocalLogHelper.log(TAG, "Received Status sms for " + mPhoneAccount.getId());
86                 StatusMessage message = new StatusMessage(messageData);
87                 updateSource(message);
88             } else {
89                 Log.e(TAG, "This should never have happened");
90             }
91         }
92         // Let this fall through: this is not a message we're interested in.
93     }
94 
95     /**
96      * A sync message has two purposes: to signal a new voicemail message, and to indicate the
97      * voicemails on the server have changed remotely (usually through the TUI). Save the new
98      * message to the voicemail provider if it is the former case and perform a full sync in the
99      * latter case.
100      *
101      * @param message The sync message to extract data from.
102      */
processSync(SyncMessage message)103     private void processSync(SyncMessage message) {
104         switch (message.getSyncTriggerEvent()) {
105             case OmtpConstants.NEW_MESSAGE:
106                 Voicemail voicemail = Voicemail.createForInsertion(
107                         message.getTimestampMillis(), message.getSender())
108                         .setPhoneAccount(mPhoneAccount)
109                         .setSourceData(message.getId())
110                         .setDuration(message.getLength())
111                         .setSourcePackage(mContext.getPackageName())
112                         .build();
113                 VoicemailsQueryHelper queryHelper = new VoicemailsQueryHelper(mContext);
114                 queryHelper.insertIfUnique(voicemail);
115                 break;
116             case OmtpConstants.MAILBOX_UPDATE:
117                 Intent serviceIntent = OmtpVvmSyncService.getSyncIntent(
118                         mContext, OmtpVvmSyncService.SYNC_DOWNLOAD_ONLY, mPhoneAccount,
119                         true /* firstAttempt */);
120                 mContext.startService(serviceIntent);
121                 break;
122             case OmtpConstants.GREETINGS_UPDATE:
123                 // Not implemented in V1
124                 break;
125            default:
126                Log.e(TAG, "Unrecognized sync trigger event: " + message.getSyncTriggerEvent());
127                break;
128         }
129     }
130 
updateSource(StatusMessage message)131     private void updateSource(StatusMessage message) {
132         OmtpVvmSourceManager vvmSourceManager =
133                 OmtpVvmSourceManager.getInstance(mContext);
134 
135         if (OmtpConstants.SUCCESS.equals(message.getReturnCode())) {
136             VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
137                     VoicemailContract.Status.CONFIGURATION_STATE_OK,
138                     VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
139                     VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
140 
141             // Save the IMAP credentials in preferences so they are persistent and can be retrieved.
142             VisualVoicemailSettingsUtil.setVisualVoicemailCredentialsFromStatusMessage(
143                     mContext,
144                     mPhoneAccount,
145                     message);
146 
147             // Add the source to indicate that it is active.
148             vvmSourceManager.addSource(mPhoneAccount);
149 
150             Intent serviceIntent = OmtpVvmSyncService.getSyncIntent(
151                     mContext, OmtpVvmSyncService.SYNC_FULL_SYNC, mPhoneAccount,
152                     true /* firstAttempt */);
153             mContext.startService(serviceIntent);
154 
155             PhoneGlobals.getInstance().clearMwiIndicator(
156                     PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount));
157         } else {
158             Log.w(TAG, "Visual voicemail not available for subscriber.");
159             // Override default isEnabled setting to false since visual voicemail is unable to
160             // be accessed for some reason.
161             VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(mContext, mPhoneAccount,
162                     /* isEnabled */ false, /* isUserSet */ true);
163         }
164     }
165 }