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.server.telecom.settings; 18 19 import android.annotation.Nullable; 20 import android.app.ActionBar; 21 import android.app.AlertDialog; 22 import android.app.FragmentManager; 23 import android.app.ListActivity; 24 import android.app.LoaderManager; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.CursorLoader; 28 import android.content.DialogInterface; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.content.Loader; 32 import android.database.Cursor; 33 import android.os.Bundle; 34 import android.provider.BlockedNumberContract; 35 import android.telephony.PhoneNumberFormattingTextWatcher; 36 import android.telephony.PhoneNumberUtils; 37 import android.text.Editable; 38 import android.text.TextUtils; 39 import android.text.TextWatcher; 40 import android.view.LayoutInflater; 41 import android.view.MenuItem; 42 import android.view.View; 43 import android.view.inputmethod.InputMethodManager; 44 import android.widget.Button; 45 import android.widget.EditText; 46 import android.widget.LinearLayout; 47 import android.widget.ListView; 48 import android.widget.ProgressBar; 49 import android.widget.RelativeLayout; 50 import android.widget.TextView; 51 import android.widget.Toast; 52 53 import com.android.server.telecom.R; 54 55 /** 56 * Activity to manage blocked numbers using {@link BlockedNumberContract}. 57 */ 58 public class BlockedNumbersActivity extends ListActivity 59 implements LoaderManager.LoaderCallbacks<Cursor>, View.OnClickListener, TextWatcher, 60 BlockNumberTaskFragment.Listener { 61 private static final String ACTION_MANAGE_BLOCKED_NUMBERS = 62 "android.telecom.action.MANAGE_BLOCKED_NUMBERS"; 63 private static final String TAG_BLOCK_NUMBER_TASK_FRAGMENT = "block_number_task_fragment"; 64 private static final String TELECOM_PACKAGE = "com.android.server.telecom"; 65 private static final String[] PROJECTION = new String[] { 66 BlockedNumberContract.BlockedNumbers.COLUMN_ID, 67 BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER 68 }; 69 70 private static final String SELECTION = "((" + 71 BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER + " NOTNULL) AND (" + 72 BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER + " != '' ))"; 73 74 private BlockNumberTaskFragment mBlockNumberTaskFragment; 75 private BlockedNumbersAdapter mAdapter; 76 private TextView mAddButton; 77 private ProgressBar mProgressBar; 78 private RelativeLayout mButterBar; 79 @Nullable private Button mBlockButton; 80 private TextView mReEnableButton; 81 82 private BroadcastReceiver mBlockingStatusReceiver; 83 84 public static Intent getIntentForStartingActivity() { 85 Intent intent = new Intent(ACTION_MANAGE_BLOCKED_NUMBERS); 86 intent.setPackage(TELECOM_PACKAGE); 87 return intent; 88 } 89 90 @Override 91 public void onCreate(Bundle savedInstanceState) { 92 super.onCreate(savedInstanceState); 93 setContentView(R.xml.activity_blocked_numbers); 94 95 ActionBar actionBar = getActionBar(); 96 if (actionBar != null) { 97 actionBar.setDisplayHomeAsUpEnabled(true); 98 } 99 100 if (!BlockedNumberContract.canCurrentUserBlockNumbers(this)) { 101 TextView nonPrimaryUserText = (TextView) findViewById(R.id.non_primary_user); 102 nonPrimaryUserText.setVisibility(View.VISIBLE); 103 104 LinearLayout manageBlockedNumbersUi = 105 (LinearLayout) findViewById(R.id.manage_blocked_ui); 106 manageBlockedNumbersUi.setVisibility(View.GONE); 107 return; 108 } 109 110 FragmentManager fm = getFragmentManager(); 111 mBlockNumberTaskFragment = 112 (BlockNumberTaskFragment) fm.findFragmentByTag(TAG_BLOCK_NUMBER_TASK_FRAGMENT); 113 114 if (mBlockNumberTaskFragment == null) { 115 mBlockNumberTaskFragment = new BlockNumberTaskFragment(); 116 fm.beginTransaction() 117 .add(mBlockNumberTaskFragment, TAG_BLOCK_NUMBER_TASK_FRAGMENT).commit(); 118 } 119 120 mAddButton = (TextView) findViewById(R.id.add_blocked); 121 mAddButton.setOnClickListener(this); 122 123 mProgressBar = (ProgressBar) findViewById(R.id.progress_bar); 124 String[] fromColumns = {BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER}; 125 int[] toViews = {R.id.blocked_number}; 126 mAdapter = new BlockedNumbersAdapter(this, R.xml.layout_blocked_number, null, fromColumns, 127 toViews, 0); 128 129 ListView listView = getListView(); 130 listView.setAdapter(mAdapter); 131 listView.setDivider(null); 132 listView.setDividerHeight(0); 133 134 mButterBar = (RelativeLayout) findViewById(R.id.butter_bar); 135 mReEnableButton = (TextView) mButterBar.findViewById(R.id.reenable_button); 136 mReEnableButton.setOnClickListener(this); 137 138 updateButterBar(); 139 140 mBlockingStatusReceiver = new BroadcastReceiver() { 141 @Override 142 public void onReceive(Context context, Intent intent) { 143 updateButterBar(); 144 } 145 }; 146 registerReceiver(mBlockingStatusReceiver, new IntentFilter( 147 BlockedNumberContract.SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED)); 148 149 getLoaderManager().initLoader(0, null, this); 150 } 151 152 @Override 153 protected void onDestroy() { 154 if (mBlockingStatusReceiver != null) { 155 unregisterReceiver(mBlockingStatusReceiver); 156 } 157 super.onDestroy(); 158 } 159 160 @Override 161 public boolean onOptionsItemSelected(MenuItem item) { 162 switch (item.getItemId()) { 163 case android.R.id.home: 164 this.finish(); 165 return true; 166 default: 167 return super.onOptionsItemSelected(item); 168 } 169 } 170 171 private void updateButterBar() { 172 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(this).isSuppressed) { 173 mButterBar.setVisibility(View.VISIBLE); 174 } else { 175 mButterBar.setVisibility(View.GONE); 176 } 177 } 178 179 @Override 180 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 181 return new CursorLoader(this, BlockedNumberContract.BlockedNumbers.CONTENT_URI, 182 PROJECTION, SELECTION, null, 183 BlockedNumberContract.BlockedNumbers.COLUMN_ID + " DESC"); 184 } 185 186 @Override 187 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 188 mAdapter.swapCursor(data); 189 mProgressBar.setVisibility(View.GONE); 190 } 191 192 @Override 193 public void onLoaderReset(Loader<Cursor> loader) { 194 mAdapter.swapCursor(null); 195 mProgressBar.setVisibility(View.VISIBLE); 196 } 197 198 @Override 199 public void onClick(View view) { 200 if (view == mAddButton) { 201 showAddBlockedNumberDialog(); 202 } else if (view == mReEnableButton) { 203 BlockedNumberContract.SystemContract.endBlockSuppression(this); 204 mButterBar.setVisibility(View.GONE); 205 } 206 } 207 208 private void showAddBlockedNumberDialog() { 209 LayoutInflater inflater = this.getLayoutInflater(); 210 View dialogView = inflater.inflate(R.xml.add_blocked_number_dialog, null); 211 final EditText editText = (EditText) dialogView.findViewById(R.id.add_blocked_number); 212 editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher()); 213 editText.addTextChangedListener(this); 214 AlertDialog dialog = new AlertDialog.Builder(this) 215 .setView(dialogView) 216 .setPositiveButton(R.string.block_button, new DialogInterface.OnClickListener() { 217 public void onClick(DialogInterface dialog, int id) { 218 addBlockedNumber(PhoneNumberUtils.stripSeparators( 219 editText.getText().toString())); 220 } 221 }) 222 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 223 public void onClick(DialogInterface dialog, int id) { 224 dialog.dismiss(); 225 } 226 }) 227 .create(); 228 dialog.setOnShowListener(new AlertDialog.OnShowListener() { 229 @Override 230 public void onShow(DialogInterface dialog) { 231 mBlockButton = ((AlertDialog) dialog) 232 .getButton(AlertDialog.BUTTON_POSITIVE); 233 mBlockButton.setEnabled(false); 234 // show keyboard 235 InputMethodManager inputMethodManager = 236 (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 237 inputMethodManager.showSoftInput(editText, 238 InputMethodManager.SHOW_IMPLICIT); 239 240 } 241 }); 242 dialog.show(); 243 } 244 245 /** 246 * Add blocked number if it does not exist. 247 */ 248 private void addBlockedNumber(String number) { 249 if (PhoneNumberUtils.isEmergencyNumber(number)) { 250 Toast.makeText( 251 this, 252 getString(R.string.blocked_numbers_block_emergency_number_message), 253 Toast.LENGTH_SHORT).show(); 254 } else { 255 // We disable the add button, to prevent the user from adding other numbers until the 256 // current number is added. 257 mAddButton.setEnabled(false); 258 mBlockNumberTaskFragment.blockIfNotAlreadyBlocked(number, this); 259 } 260 } 261 262 @Override 263 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 264 // no-op 265 } 266 267 @Override 268 public void onTextChanged(CharSequence text, int start, int before, int count) { 269 if (mBlockButton != null) { 270 mBlockButton.setEnabled( 271 !TextUtils.isEmpty(PhoneNumberUtils.stripSeparators(text.toString()))); 272 } 273 } 274 275 @Override 276 public void afterTextChanged(Editable s) { 277 // no-op 278 } 279 280 @Override 281 public void onBlocked(String number, boolean alreadyBlocked) { 282 if (alreadyBlocked) { 283 BlockedNumbersUtil.showToastWithFormattedNumber(this, 284 R.string.blocked_numbers_number_already_blocked_message, number); 285 } else { 286 BlockedNumbersUtil.showToastWithFormattedNumber(this, 287 R.string.blocked_numbers_number_blocked_message, number); 288 } 289 mAddButton.setEnabled(true); 290 } 291 } 292