1 /*
2  * Copyright (C) 2018 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.main.impl.bottomnav;
18 
19 import android.Manifest;
20 import android.content.Context;
21 import android.database.ContentObserver;
22 import android.database.Cursor;
23 import android.provider.CallLog.Calls;
24 import android.support.annotation.RequiresPermission;
25 import com.android.dialer.common.concurrent.DialerExecutorComponent;
26 import com.android.dialer.common.concurrent.UiListener;
27 import com.android.dialer.main.impl.bottomnav.BottomNavBar.TabIndex;
28 import com.google.common.util.concurrent.ListenableFuture;
29 
30 /**
31  * Observes the call log and updates the badge count to show the number of unread missed calls.
32  *
33  * <p>Used only when the new call log fragment is enabled.
34  */
35 public final class MissedCallCountObserver extends ContentObserver {
36   private final Context appContext;
37   private final BottomNavBar bottomNavBar;
38   private final UiListener<Integer> uiListener;
39 
MissedCallCountObserver( Context appContext, BottomNavBar bottomNavBar, UiListener<Integer> uiListener)40   public MissedCallCountObserver(
41       Context appContext, BottomNavBar bottomNavBar, UiListener<Integer> uiListener) {
42     super(null);
43     this.appContext = appContext;
44     this.bottomNavBar = bottomNavBar;
45     this.uiListener = uiListener;
46   }
47 
48   @RequiresPermission(Manifest.permission.READ_CALL_LOG)
49   @Override
onChange(boolean selfChange)50   public void onChange(boolean selfChange) {
51     ListenableFuture<Integer> countFuture =
52         DialerExecutorComponent.get(appContext)
53             .backgroundExecutor()
54             .submit(
55                 () -> {
56                   try (Cursor cursor =
57                       appContext
58                           .getContentResolver()
59                           .query(
60                               Calls.CONTENT_URI,
61                               new String[] {Calls._ID},
62                               "("
63                                   + Calls.IS_READ
64                                   + " = ? OR "
65                                   + Calls.IS_READ
66                                   + " IS NULL) AND "
67                                   + Calls.TYPE
68                                   + " = ?",
69                               new String[] {"0", Integer.toString(Calls.MISSED_TYPE)},
70                               /* sortOrder= */ null)) {
71                     return cursor == null ? 0 : cursor.getCount();
72                   }
73                 });
74     uiListener.listen(
75         appContext,
76         countFuture,
77         count -> bottomNavBar.setNotificationCount(TabIndex.CALL_LOG, count == null ? 0 : count),
78         throwable -> {
79           throw new RuntimeException(throwable);
80         });
81   }
82 }
83