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.dialer.app.calllog;
18 
19 import android.app.KeyguardManager;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.database.ContentObserver;
23 import android.media.AudioManager;
24 import android.os.Bundle;
25 import android.provider.CallLog;
26 import android.provider.VoicemailContract;
27 import android.support.annotation.VisibleForTesting;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import com.android.dialer.app.R;
32 import com.android.dialer.app.voicemail.VoicemailAudioManager;
33 import com.android.dialer.app.voicemail.VoicemailErrorManager;
34 import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter;
35 import com.android.dialer.common.FragmentUtils;
36 import com.android.dialer.common.LogUtil;
37 import com.android.dialer.common.concurrent.DialerExecutor;
38 import com.android.dialer.common.concurrent.DialerExecutorComponent;
39 import com.android.dialer.logging.DialerImpression;
40 import com.android.dialer.logging.Logger;
41 import com.android.dialer.util.PermissionsUtil;
42 import com.android.dialer.voicemail.listui.error.VoicemailErrorMessageCreator;
43 import com.android.dialer.voicemail.listui.error.VoicemailStatus;
44 import com.android.dialer.voicemail.listui.error.VoicemailStatusWorker;
45 import com.android.dialer.widget.EmptyContentView;
46 import java.util.List;
47 
48 public class VisualVoicemailCallLogFragment extends CallLogFragment {
49 
50   private final ContentObserver voicemailStatusObserver = new CustomContentObserver();
51   private VoicemailPlaybackPresenter voicemailPlaybackPresenter;
52   private DialerExecutor<Context> preSyncVoicemailStatusCheckExecutor;
53 
54   private VoicemailErrorManager voicemailErrorManager;
55 
VisualVoicemailCallLogFragment()56   public VisualVoicemailCallLogFragment() {
57     super(CallLog.Calls.VOICEMAIL_TYPE);
58   }
59 
60   @Override
getVoicemailPlaybackPresenter()61   protected VoicemailPlaybackPresenter getVoicemailPlaybackPresenter() {
62     return voicemailPlaybackPresenter;
63   }
64 
65   @Override
onActivityCreated(Bundle savedInstanceState)66   public void onActivityCreated(Bundle savedInstanceState) {
67     voicemailPlaybackPresenter =
68         VoicemailPlaybackPresenter.getInstance(getActivity(), savedInstanceState);
69     if (PermissionsUtil.hasReadVoicemailPermissions(getContext())
70         && PermissionsUtil.hasAddVoicemailPermissions(getContext())) {
71       getActivity()
72           .getContentResolver()
73           .registerContentObserver(
74               VoicemailContract.Status.CONTENT_URI, true, voicemailStatusObserver);
75     } else {
76       LogUtil.w(
77           "VisualVoicemailCallLogFragment.onActivityCreated",
78           "read voicemail permission unavailable.");
79     }
80     super.onActivityCreated(savedInstanceState);
81 
82     preSyncVoicemailStatusCheckExecutor =
83         DialerExecutorComponent.get(getContext())
84             .dialerExecutorFactory()
85             .createUiTaskBuilder(
86                 getActivity().getFragmentManager(),
87                 "fetchVoicemailStatus",
88                 new VoicemailStatusWorker())
89             .onSuccess(this::onPreSyncVoicemailStatusChecked)
90             .build();
91 
92     voicemailErrorManager =
93         new VoicemailErrorManager(getContext(), getAdapter().getAlertManager(), modalAlertManager);
94 
95     if (PermissionsUtil.hasReadVoicemailPermissions(getContext())
96         && PermissionsUtil.hasAddVoicemailPermissions(getContext())) {
97       getActivity()
98           .getContentResolver()
99           .registerContentObserver(
100               VoicemailContract.Status.CONTENT_URI,
101               true,
102               voicemailErrorManager.getContentObserver());
103     } else {
104       LogUtil.w(
105           "VisualVoicemailCallLogFragment.onActivityCreated",
106           "read voicemail permission unavailable.");
107     }
108   }
109 
110   @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState)111   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
112     View view = inflater.inflate(R.layout.call_log_fragment, container, false);
113     setupView(view);
114     EmptyContentView emptyContentView = view.findViewById(R.id.empty_list_view);
115     emptyContentView.setImage(R.drawable.quantum_ic_voicemail_vd_theme_24);
116     return view;
117   }
118 
119   @Override
onResume()120   public void onResume() {
121     super.onResume();
122     voicemailPlaybackPresenter.onResume();
123     voicemailErrorManager.onResume();
124   }
125 
126   @Override
onPause()127   public void onPause() {
128     voicemailPlaybackPresenter.onPause();
129     voicemailErrorManager.onPause();
130     // Necessary to reset the speaker when leaving otherwise the platform will still remain in
131     // speaker mode
132     AudioManager audioManager = getContext().getSystemService(AudioManager.class);
133     if (audioManager.isSpeakerphoneOn()) {
134       audioManager.setSpeakerphoneOn(false);
135     }
136     super.onPause();
137   }
138 
139   @Override
onDestroy()140   public void onDestroy() {
141     if (isAdded()) {
142       getActivity()
143           .getContentResolver()
144           .unregisterContentObserver(voicemailErrorManager.getContentObserver());
145       voicemailPlaybackPresenter.onDestroy();
146       voicemailErrorManager.onDestroy();
147       getActivity().getContentResolver().unregisterContentObserver(voicemailStatusObserver);
148     }
149     super.onDestroy();
150   }
151 
152   @Override
onSaveInstanceState(Bundle outState)153   public void onSaveInstanceState(Bundle outState) {
154     super.onSaveInstanceState(outState);
155     if (voicemailPlaybackPresenter != null) {
156       voicemailPlaybackPresenter.onSaveInstanceState(outState);
157     }
158   }
159 
160   @Override
fetchCalls()161   public void fetchCalls() {
162     super.fetchCalls();
163     if (FragmentUtils.getParent(this, CallLogFragmentListener.class) != null) {
164       FragmentUtils.getParentUnsafe(this, CallLogFragmentListener.class).updateTabUnreadCounts();
165     }
166   }
167 
168   @Override
onVisible()169   public void onVisible() {
170     LogUtil.enterBlock("VisualVoicemailCallLogFragment.onVisible");
171     super.onVisible();
172     if (getActivity() != null && preSyncVoicemailStatusCheckExecutor != null) {
173       preSyncVoicemailStatusCheckExecutor.executeParallel(getActivity());
174       Logger.get(getActivity()).logImpression(DialerImpression.Type.VVM_TAB_VIEWED);
175       getActivity().setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM);
176     }
177   }
178 
onPreSyncVoicemailStatusChecked(List<VoicemailStatus> statuses)179   private void onPreSyncVoicemailStatusChecked(List<VoicemailStatus> statuses) {
180     if (!shouldAutoSync(new VoicemailErrorMessageCreator(), statuses)) {
181       return;
182     }
183 
184     Intent intent = new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL);
185     intent.setPackage(getActivity().getPackageName());
186     getActivity().sendBroadcast(intent);
187   }
188 
189   @VisibleForTesting
shouldAutoSync( VoicemailErrorMessageCreator errorMessageCreator, List<VoicemailStatus> statuses)190   boolean shouldAutoSync(
191       VoicemailErrorMessageCreator errorMessageCreator, List<VoicemailStatus> statuses) {
192     for (VoicemailStatus status : statuses) {
193       if (!status.isActive(getContext())) {
194         continue;
195       }
196       if (errorMessageCreator.isSyncBlockingError(status)) {
197         LogUtil.i(
198             "VisualVoicemailCallLogFragment.shouldAutoSync", "auto-sync blocked due to " + status);
199         return false;
200       }
201     }
202     return true;
203   }
204 
205   @Override
onNotVisible()206   public void onNotVisible() {
207     LogUtil.enterBlock("VisualVoicemailCallLogFragment.onNotVisible");
208     super.onNotVisible();
209     if (getActivity() != null) {
210       getActivity().setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
211       // onNotVisible will be called in the lock screen when the call ends
212       if (!getActivity().getSystemService(KeyguardManager.class).inKeyguardRestrictedInputMode()) {
213         LogUtil.i("VisualVoicemailCallLogFragment.onNotVisible", "clearing all new voicemails");
214         CallLogNotificationsService.markAllNewVoicemailsAsOld(getActivity());
215       }
216     }
217   }
218 }
219