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.car.dialer.livedata;
18 
19 import static com.android.car.dialer.livedata.CallHistoryLiveData.CallType.CALL_TYPE_ALL;
20 
21 import android.content.Context;
22 import android.database.Cursor;
23 import android.net.Uri;
24 import android.provider.CallLog;
25 
26 import androidx.annotation.IntDef;
27 
28 import com.android.car.telephony.common.AsyncQueryLiveData;
29 import com.android.car.telephony.common.PhoneCallLog;
30 import com.android.car.telephony.common.QueryParam;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 
35 /**
36  * Live data which loads call history.
37  */
38 //TODO: Rename to PhoneCallLogLiveData
39 public class CallHistoryLiveData extends AsyncQueryLiveData<List<PhoneCallLog>> {
40     /** The default limit of loading call logs */
41     private final static int DEFAULT_CALL_LOG_LIMIT = 100;
42     private static final String[] EMPTY_STRING_ARRAY = new String[0];
43 
44     @IntDef({
45             CALL_TYPE_ALL,
46             CallType.INCOMING_TYPE,
47             CallType.OUTGOING_TYPE,
48             CallType.MISSED_TYPE,
49     })
50     public @interface CallType {
51         int CALL_TYPE_ALL = -1;
52         int INCOMING_TYPE = CallLog.Calls.INCOMING_TYPE;
53         int OUTGOING_TYPE = CallLog.Calls.OUTGOING_TYPE;
54         int MISSED_TYPE = CallLog.Calls.MISSED_TYPE;
55         int VOICEMAIL_TYPE = CallLog.Calls.VOICEMAIL_TYPE;
56     }
57 
58     /**
59      * Creates a new instance of call history live data which loads all types of call history
60      * with a limit of 100 logs.
61      */
newInstance(Context context)62     public static CallHistoryLiveData newInstance(Context context) {
63         return newInstance(context, CALL_TYPE_ALL, DEFAULT_CALL_LOG_LIMIT);
64     }
65 
66     /**
67      * Returns a new instance of last call live data.
68      */
newLastCallLiveData(Context context)69     public static CallHistoryLiveData newLastCallLiveData(Context context) {
70         return newInstance(context, CALL_TYPE_ALL, 1);
71     }
72 
newInstance(Context context, int callType, int limit)73     private static CallHistoryLiveData newInstance(Context context, int callType, int limit) {
74         StringBuilder where = new StringBuilder();
75         List<String> selectionArgs = new ArrayList<>();
76         limit = limit < 0 ? 0 : limit;
77 
78         if (callType != CALL_TYPE_ALL) {
79             // add a filter for call type
80             where.append(String.format("(%s = ?)", CallLog.Calls.TYPE));
81             selectionArgs.add(Integer.toString(callType));
82         }
83         String selection = where.length() > 0 ? where.toString() : null;
84 
85         Uri uri = CallLog.Calls.CONTENT_URI.buildUpon()
86                 .appendQueryParameter(CallLog.Calls.LIMIT_PARAM_KEY,
87                         Integer.toString(limit))
88                 .build();
89         QueryParam queryParam = new QueryParam(
90                 uri,
91                 null,
92                 selection,
93                 selectionArgs.toArray(EMPTY_STRING_ARRAY),
94                 CallLog.Calls.DEFAULT_SORT_ORDER);
95         return new CallHistoryLiveData(context, queryParam);
96     }
97 
98     private final Context mContext;
CallHistoryLiveData(Context context, QueryParam queryParam)99     private CallHistoryLiveData(Context context, QueryParam queryParam) {
100         super(context, QueryParam.of(queryParam));
101         mContext = context;
102     }
103 
104     @Override
convertToEntity(Cursor cursor)105     protected List<PhoneCallLog> convertToEntity(Cursor cursor) {
106         List<PhoneCallLog> resultList = new ArrayList<>();
107 
108         while (cursor.moveToNext()) {
109             PhoneCallLog phoneCallLog = PhoneCallLog.fromCursor(mContext, cursor);
110             PhoneCallLog previousCallLog = resultList.isEmpty() ? null : resultList.get(
111                     resultList.size() - 1);
112 
113             if (previousCallLog == null || !previousCallLog.merge(phoneCallLog)) {
114                 resultList.add(phoneCallLog);
115             }
116         }
117         return resultList;
118     }
119 }
120