1 /* 2 * Copyright (C) 2019 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.compatibility.common.util; 18 19 import static android.provider.BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER; 20 import static android.provider.BlockedNumberContract.BlockedNumbers.CONTENT_URI; 21 22 import android.app.IntentService; 23 import android.content.ContentResolver; 24 import android.content.ContentValues; 25 import android.content.Intent; 26 import android.database.ContentObserver; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.os.Handler; 30 import android.os.ResultReceiver; 31 import android.util.Log; 32 33 import java.util.concurrent.CountDownLatch; 34 import java.util.concurrent.TimeUnit; 35 36 /** 37 * A service to handle interactions with the BlockedNumberProvider. The BlockedNumberProvider 38 * can only be accessed by the primary user. This service can be run as a singleton service 39 * which will then be able to access the BlockedNumberProvider from a test running in a 40 * secondary user. 41 */ 42 public class BlockedNumberService extends IntentService { 43 44 static final String INSERT_ACTION = "android.telecom.cts.InsertBlockedNumber"; 45 static final String DELETE_ACTION = "android.telecom.cts.DeleteBlockedNumber"; 46 static final String PHONE_NUMBER_EXTRA = "number"; 47 static final String URI_EXTRA = "uri"; 48 static final String ROWS_EXTRA = "rows"; 49 static final String FAIL_EXTRA = "fail"; 50 static final String RESULT_RECEIVER_EXTRA = "resultReceiver"; 51 52 private static final String TAG = "CtsBlockNumberSvc"; 53 private static final int ASYNC_TIMEOUT = 10000; 54 55 private ContentResolver mContentResolver; 56 private Handler mHandler = new Handler(); 57 BlockedNumberService()58 public BlockedNumberService() { 59 super(BlockedNumberService.class.getName()); 60 } 61 62 @Override onHandleIntent(Intent intent)63 public void onHandleIntent(Intent intent) { 64 Log.i(TAG, "Starting BlockedNumberService service: " + intent); 65 if (intent == null) { 66 return; 67 } 68 Bundle bundle; 69 mContentResolver = getContentResolver(); 70 switch (intent.getAction()) { 71 case INSERT_ACTION: 72 bundle = insertBlockedNumber(intent.getStringExtra(PHONE_NUMBER_EXTRA)); 73 break; 74 case DELETE_ACTION: 75 bundle = deleteBlockedNumber(Uri.parse(intent.getStringExtra(URI_EXTRA))); 76 break; 77 default: 78 bundle = new Bundle(); 79 break; 80 } 81 ResultReceiver receiver = intent.getParcelableExtra(RESULT_RECEIVER_EXTRA); 82 receiver.send(0, bundle); 83 } 84 insertBlockedNumber(String number)85 private Bundle insertBlockedNumber(String number) { 86 Log.i(TAG, "insertBlockedNumber: " + number); 87 88 CountDownLatch blockedNumberLatch = getBlockedNumberLatch(); 89 ContentValues cv = new ContentValues(); 90 cv.put(COLUMN_ORIGINAL_NUMBER, number); 91 Uri uri = mContentResolver.insert(CONTENT_URI, cv); 92 Bundle bundle = new Bundle(); 93 bundle.putString(URI_EXTRA, uri.toString()); 94 95 // Wait for the content provider to be updated. 96 try { 97 if (!blockedNumberLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS)) { 98 Log.e(TAG, "Timed out waiting for blocked number update"); 99 bundle.putBoolean(FAIL_EXTRA, true); 100 } 101 } catch (InterruptedException e) { 102 Log.e(TAG, "Interrupted while waiting for blocked number update"); 103 bundle.putBoolean(FAIL_EXTRA, true); 104 } 105 return bundle; 106 } 107 getBlockedNumberLatch()108 private CountDownLatch getBlockedNumberLatch() { 109 CountDownLatch changeLatch = new CountDownLatch(1); 110 getContentResolver().registerContentObserver( 111 CONTENT_URI, true, 112 new ContentObserver(mHandler) { 113 @Override 114 public void onChange(boolean selfChange, Uri uri) { 115 getContentResolver().unregisterContentObserver(this); 116 changeLatch.countDown(); 117 super.onChange(selfChange); 118 } 119 }); 120 return changeLatch; 121 } 122 deleteBlockedNumber(Uri uri)123 private Bundle deleteBlockedNumber(Uri uri) { 124 Log.i(TAG, "deleteBlockedNumber: " + uri); 125 126 int rows = mContentResolver.delete(uri, null, null); 127 Bundle bundle = new Bundle(); 128 bundle.putInt(ROWS_EXTRA, rows); 129 return bundle; 130 } 131 } 132