1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/*
2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2016 The Android Open Source Project
3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License");
5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License.
6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at
7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *      http://www.apache.org/licenses/LICENSE-2.0
9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software
11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS,
12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and
14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License
15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.incallui.spam;
18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.NotificationManager;
20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.Service;
21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context;
22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Intent;
23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.IBinder;
24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.provider.CallLog;
25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.Nullable;
26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil;
2810b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanianimport com.android.dialer.location.GeoUtil;
298369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanianimport com.android.dialer.logging.ContactLookupResult;
308369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanianimport com.android.dialer.logging.DialerImpression;
31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.logging.Logger;
328369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanianimport com.android.dialer.logging.ReportingLocation;
33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.spam.Spam;
34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.DialerCall;
35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/**
37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * This service determines if the device is locked/unlocked and takes an action based on the state.
38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * A service is used to to determine this, as opposed to an activity, because the user must unlock
39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * the device before a notification can start an activity. This is not the case for a service, and
40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * intents can be sent to this service even from the lock screen. This allows users to quickly
41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * report a number as spam or not spam from their lock screen.
42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class SpamNotificationService extends Service {
44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final String TAG = "SpamNotificationSvc";
46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final String EXTRA_PHONE_NUMBER = "service_phone_number";
48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final String EXTRA_CALL_ID = "service_call_id";
49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final String EXTRA_CALL_START_TIME_MILLIS = "service_call_start_time_millis";
50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final String EXTRA_NOTIFICATION_ID = "service_notification_id";
51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final String EXTRA_CONTACT_LOOKUP_RESULT_TYPE =
52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      "service_contact_lookup_result_type";
53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Creates an intent to start this service. */
54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public static Intent createServiceIntent(
55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Context context, DialerCall call, String action, int notificationId) {
56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Intent intent = new Intent(context, SpamNotificationService.class);
57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    intent.setAction(action);
58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    intent.putExtra(EXTRA_PHONE_NUMBER, call.getNumber());
59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    intent.putExtra(EXTRA_CALL_ID, call.getUniqueCallId());
60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    intent.putExtra(EXTRA_CALL_START_TIME_MILLIS, call.getTimeAddedMs());
61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    intent.putExtra(EXTRA_CONTACT_LOOKUP_RESULT_TYPE, call.getLogState().contactLookupResult);
63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return intent;
64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Nullable
67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public IBinder onBind(Intent intent) {
69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Return null because clients cannot bind to this service
70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return null;
71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public int onStartCommand(Intent intent, int flags, int startId) {
75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.d(TAG, "onStartCommand");
76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (intent == null) {
77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      LogUtil.d(TAG, "Null intent");
78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      stopSelf();
79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Return {@link #START_NOT_STICKY} so service is not restarted.
80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return START_NOT_STICKY;
81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    String number = intent.getStringExtra(EXTRA_PHONE_NUMBER);
83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, 1);
84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    String countryIso = GeoUtil.getCurrentCountryIso(this);
858369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian    ContactLookupResult.Type contactLookupResultType =
868369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian        ContactLookupResult.Type.forNumber(intent.getIntExtra(EXTRA_CONTACT_LOOKUP_RESULT_TYPE, 0));
87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        .cancel(number, notificationId);
90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    switch (intent.getAction()) {
92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      case SpamNotificationActivity.ACTION_MARK_NUMBER_AS_SPAM:
93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        logCallImpression(
94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            intent, DialerImpression.Type.SPAM_NOTIFICATION_SERVICE_ACTION_MARK_NUMBER_AS_SPAM);
95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        Spam.get(this)
96ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            .reportSpamFromAfterCallNotification(
97ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                number,
98ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                countryIso,
99ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                CallLog.Calls.INCOMING_TYPE,
100ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                ReportingLocation.Type.FEEDBACK_PROMPT,
101ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                contactLookupResultType);
102ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new FilteredNumberAsyncQueryHandler(this).blockNumber(null, number, countryIso);
103ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        break;
104ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      case SpamNotificationActivity.ACTION_MARK_NUMBER_AS_NOT_SPAM:
105ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        logCallImpression(
106ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            intent, DialerImpression.Type.SPAM_NOTIFICATION_SERVICE_ACTION_MARK_NUMBER_AS_NOT_SPAM);
107ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        Spam.get(this)
108ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            .reportNotSpamFromAfterCallNotification(
109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                number,
110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                countryIso,
111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                CallLog.Calls.INCOMING_TYPE,
112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                ReportingLocation.Type.FEEDBACK_PROMPT,
113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                contactLookupResultType);
114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        break;
1158369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian      default: // fall out
116ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
117ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // TODO: call stopSelf() after async tasks complete (b/28441936)
118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    stopSelf();
119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return START_NOT_STICKY;
120ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
121ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
122ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
123ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onDestroy() {
124ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super.onDestroy();
125ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.d(TAG, "onDestroy");
126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
1288369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian  private void logCallImpression(Intent intent, DialerImpression.Type impression) {
129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Logger.get(this)
130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        .logCallImpression(
131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            impression,
132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            intent.getStringExtra(EXTRA_CALL_ID),
133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            intent.getLongExtra(EXTRA_CALL_START_TIME_MILLIS, 0));
134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian}
136