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.legacyblocking;
18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context;
20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.database.ContentObserver;
21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Handler;
22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.provider.CallLog;
23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull;
24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil;
259779f967ebb9512e5b19090b071572c9c4f0f2a6Eric Erfanianimport com.android.dialer.common.concurrent.AsyncTaskExecutor;
269779f967ebb9512e5b19090b071572c9c4f0f2a6Eric Erfanianimport com.android.dialer.common.concurrent.AsyncTaskExecutors;
27c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanianimport com.android.dialer.util.PermissionsUtil;
28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Objects;
29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/**
31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Observes the {@link CallLog} to delete the CallLog entry for a blocked call after it is added.
32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Automatically de-registers itself {@link #TIMEOUT_MS} ms after registration or if the entry is
33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * found and deleted.
34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class BlockedNumberContentObserver extends ContentObserver
36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    implements DeleteBlockedCallTask.Listener {
37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * The time after which a {@link BlockedNumberContentObserver} will be automatically unregistered.
40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public static final int TIMEOUT_MS = 5000;
42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @NonNull private final Context context;
44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @NonNull private final Handler handler;
45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final String number;
46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final long timeAddedMillis;
47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final Runnable timeoutRunnable =
48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      new Runnable() {
49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        @Override
50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        public void run() {
51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          unregister();
52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        }
53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      };
54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final AsyncTaskExecutor asyncTaskExecutor = AsyncTaskExecutors.createThreadPoolExecutor();
56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Creates the BlockedNumberContentObserver to delete the new {@link CallLog} entry from the given
59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * blocked number.
60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param number The blocked number.
62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param timeAddedMillis The time at which the call from the blocked number was placed.
63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public BlockedNumberContentObserver(
65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      @NonNull Context context, @NonNull Handler handler, String number, long timeAddedMillis) {
66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super(handler);
67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    this.context = Objects.requireNonNull(context, "context").getApplicationContext();
68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    this.handler = Objects.requireNonNull(handler);
69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    this.number = number;
70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    this.timeAddedMillis = timeAddedMillis;
71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onChange(boolean selfChange) {
75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i(
76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        "BlockedNumberContentObserver.onChange",
77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        "attempting to remove call log entry from blocked number");
78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    asyncTaskExecutor.submit(
79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        DeleteBlockedCallTask.IDENTIFIER,
80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new DeleteBlockedCallTask(context, this, number, timeAddedMillis));
81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onDeleteBlockedCallTaskComplete(boolean didFindEntry) {
85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (didFindEntry) {
86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      unregister();
87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Registers this {@link ContentObserver} to listen for changes to the {@link CallLog}. If the
92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * CallLog entry is not found before {@link #TIMEOUT_MS}, this ContentObserver automatically
93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * un-registers itself.
94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void register() {
96ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("BlockedNumberContentObserver.register", null);
97c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian    if (PermissionsUtil.hasCallLogReadPermissions(context)
98c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian        && PermissionsUtil.hasCallLogWritePermissions(context)) {
99c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian      context.getContentResolver().registerContentObserver(CallLog.CONTENT_URI, true, this);
100c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian      handler.postDelayed(timeoutRunnable, TIMEOUT_MS);
101c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian    } else {
102c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian      LogUtil.w("BlockedNumberContentObserver.register", "no call log read/write permissions.");
103c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian    }
104ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
105ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
106ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void unregister() {
107ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("BlockedNumberContentObserver.unregister", null);
108ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    handler.removeCallbacks(timeoutRunnable);
109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    context.getContentResolver().unregisterContentObserver(this);
110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian}
112