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.incallui.spam;
18 
19 import android.app.NotificationManager;
20 import android.app.Service;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.IBinder;
24 import android.provider.CallLog;
25 import android.support.annotation.Nullable;
26 import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
27 import com.android.dialer.common.LogUtil;
28 import com.android.dialer.location.GeoUtil;
29 import com.android.dialer.logging.ContactLookupResult;
30 import com.android.dialer.logging.DialerImpression;
31 import com.android.dialer.logging.Logger;
32 import com.android.dialer.logging.ReportingLocation;
33 import com.android.dialer.spam.Spam;
34 import com.android.incallui.call.DialerCall;
35 
36 /**
37  * This service determines if the device is locked/unlocked and takes an action based on the state.
38  * A service is used to to determine this, as opposed to an activity, because the user must unlock
39  * the device before a notification can start an activity. This is not the case for a service, and
40  * intents can be sent to this service even from the lock screen. This allows users to quickly
41  * report a number as spam or not spam from their lock screen.
42  */
43 public class SpamNotificationService extends Service {
44 
45   private static final String TAG = "SpamNotificationSvc";
46 
47   private static final String EXTRA_PHONE_NUMBER = "service_phone_number";
48   private static final String EXTRA_CALL_ID = "service_call_id";
49   private static final String EXTRA_CALL_START_TIME_MILLIS = "service_call_start_time_millis";
50   private static final String EXTRA_NOTIFICATION_ID = "service_notification_id";
51   private static final String EXTRA_CONTACT_LOOKUP_RESULT_TYPE =
52       "service_contact_lookup_result_type";
53   /** Creates an intent to start this service. */
createServiceIntent( Context context, DialerCall call, String action, int notificationId)54   public static Intent createServiceIntent(
55       Context context, DialerCall call, String action, int notificationId) {
56     Intent intent = new Intent(context, SpamNotificationService.class);
57     intent.setAction(action);
58     intent.putExtra(EXTRA_PHONE_NUMBER, call.getNumber());
59     intent.putExtra(EXTRA_CALL_ID, call.getUniqueCallId());
60     intent.putExtra(EXTRA_CALL_START_TIME_MILLIS, call.getTimeAddedMs());
61     intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
62     intent.putExtra(EXTRA_CONTACT_LOOKUP_RESULT_TYPE, call.getLogState().contactLookupResult);
63     return intent;
64   }
65 
66   @Nullable
67   @Override
onBind(Intent intent)68   public IBinder onBind(Intent intent) {
69     // Return null because clients cannot bind to this service
70     return null;
71   }
72 
73   @Override
onStartCommand(Intent intent, int flags, int startId)74   public int onStartCommand(Intent intent, int flags, int startId) {
75     LogUtil.d(TAG, "onStartCommand");
76     if (intent == null) {
77       LogUtil.d(TAG, "Null intent");
78       stopSelf();
79       // Return {@link #START_NOT_STICKY} so service is not restarted.
80       return START_NOT_STICKY;
81     }
82     String number = intent.getStringExtra(EXTRA_PHONE_NUMBER);
83     int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, 1);
84     String countryIso = GeoUtil.getCurrentCountryIso(this);
85     ContactLookupResult.Type contactLookupResultType =
86         ContactLookupResult.Type.forNumber(intent.getIntExtra(EXTRA_CONTACT_LOOKUP_RESULT_TYPE, 0));
87 
88     ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
89         .cancel(number, notificationId);
90 
91     switch (intent.getAction()) {
92       case SpamNotificationActivity.ACTION_MARK_NUMBER_AS_SPAM:
93         logCallImpression(
94             intent, DialerImpression.Type.SPAM_NOTIFICATION_SERVICE_ACTION_MARK_NUMBER_AS_SPAM);
95         Spam.get(this)
96             .reportSpamFromAfterCallNotification(
97                 number,
98                 countryIso,
99                 CallLog.Calls.INCOMING_TYPE,
100                 ReportingLocation.Type.FEEDBACK_PROMPT,
101                 contactLookupResultType);
102         new FilteredNumberAsyncQueryHandler(this).blockNumber(null, number, countryIso);
103         break;
104       case SpamNotificationActivity.ACTION_MARK_NUMBER_AS_NOT_SPAM:
105         logCallImpression(
106             intent, DialerImpression.Type.SPAM_NOTIFICATION_SERVICE_ACTION_MARK_NUMBER_AS_NOT_SPAM);
107         Spam.get(this)
108             .reportNotSpamFromAfterCallNotification(
109                 number,
110                 countryIso,
111                 CallLog.Calls.INCOMING_TYPE,
112                 ReportingLocation.Type.FEEDBACK_PROMPT,
113                 contactLookupResultType);
114         break;
115       default: // fall out
116     }
117     // TODO: call stopSelf() after async tasks complete (b/28441936)
118     stopSelf();
119     return START_NOT_STICKY;
120   }
121 
122   @Override
onDestroy()123   public void onDestroy() {
124     super.onDestroy();
125     LogUtil.d(TAG, "onDestroy");
126   }
127 
logCallImpression(Intent intent, DialerImpression.Type impression)128   private void logCallImpression(Intent intent, DialerImpression.Type impression) {
129     Logger.get(this)
130         .logCallImpression(
131             impression,
132             intent.getStringExtra(EXTRA_CALL_ID),
133             intent.getLongExtra(EXTRA_CALL_START_TIME_MILLIS, 0));
134   }
135 }
136