1 /* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.android.bluetooth.opp; 34 35 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 36 37 import android.bluetooth.AlertActivity; 38 import android.content.BroadcastReceiver; 39 import android.content.ContentValues; 40 import android.content.Context; 41 import android.content.DialogInterface; 42 import android.content.Intent; 43 import android.content.IntentFilter; 44 import android.net.Uri; 45 import android.os.Bundle; 46 import android.os.Handler; 47 import android.os.Message; 48 import android.text.format.Formatter; 49 import android.util.Log; 50 import android.view.KeyEvent; 51 import android.view.View; 52 import android.widget.TextView; 53 import android.widget.Toast; 54 55 import com.android.bluetooth.BluetoothMethodProxy; 56 import com.android.bluetooth.R; 57 import com.android.internal.annotations.VisibleForTesting; 58 59 /** 60 * This class is designed to ask user to confirm if accept incoming file; 61 */ 62 public class BluetoothOppIncomingFileConfirmActivity extends AlertActivity { 63 private static final String TAG = "BluetoothIncomingFileConfirmActivity"; 64 private static final boolean D = Constants.DEBUG; 65 private static final boolean V = Constants.VERBOSE; 66 67 @VisibleForTesting 68 static final int DISMISS_TIMEOUT_DIALOG = 0; 69 70 @VisibleForTesting 71 static final int DISMISS_TIMEOUT_DIALOG_VALUE = 2000; 72 73 private static final String PREFERENCE_USER_TIMEOUT = "user_timeout"; 74 75 private BluetoothOppTransferInfo mTransInfo; 76 77 private Uri mUri; 78 79 private ContentValues mUpdateValues; 80 81 private boolean mTimeout = false; 82 83 private BroadcastReceiver mReceiver = null; 84 85 @Override onCreate(Bundle savedInstanceState)86 protected void onCreate(Bundle savedInstanceState) { 87 setTheme(R.style.Theme_Material_Settings_Floating); 88 if (V) { 89 Log.d(TAG, "onCreate(): action = " + getIntent().getAction()); 90 } 91 super.onCreate(savedInstanceState); 92 93 getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 94 Intent intent = getIntent(); 95 mUri = intent.getData(); 96 mTransInfo = new BluetoothOppTransferInfo(); 97 mTransInfo = BluetoothOppUtility.queryRecord(this, mUri); 98 if (mTransInfo == null) { 99 if (V) { 100 Log.e(TAG, "Error: Can not get data from db"); 101 } 102 finish(); 103 return; 104 } 105 106 mAlertBuilder.setTitle(getString(R.string.incoming_file_confirm_content)); 107 mAlertBuilder.setView(createView()); 108 mAlertBuilder.setPositiveButton(R.string.incoming_file_confirm_ok, 109 (dialog, which) -> onIncomingFileConfirmOk()); 110 mAlertBuilder.setNegativeButton(R.string.incoming_file_confirm_cancel, 111 (dialog, which) -> onIncomingFileConfirmCancel()); 112 113 setupAlert(); 114 if (V) { 115 Log.v(TAG, "mTimeout: " + mTimeout); 116 } 117 if (mTimeout) { 118 onTimeout(); 119 } 120 121 if (V) { 122 Log.v(TAG, "BluetoothIncomingFileConfirmActivity: Got uri:" + mUri); 123 } 124 125 mReceiver = new BroadcastReceiver() { 126 @Override 127 public void onReceive(Context context, Intent intent) { 128 if (!BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION.equals(intent.getAction())) { 129 return; 130 } 131 onTimeout(); 132 } 133 }; 134 IntentFilter filter = new IntentFilter(BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION); 135 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 136 registerReceiver(mReceiver, filter); 137 } 138 createView()139 private View createView() { 140 View view = getLayoutInflater().inflate(R.layout.incoming_dialog, null); 141 142 ((TextView) view.findViewById(R.id.from_content)).setText(mTransInfo.mDeviceName); 143 String fileName = mTransInfo.mFileName; 144 if (fileName != null) { 145 fileName = fileName 146 .replace('\t', ' ') 147 .replace('\n', ' ') 148 .replace('\r', ' '); 149 } 150 ((TextView) view.findViewById(R.id.filename_content)).setText(fileName); 151 ((TextView) view.findViewById(R.id.size_content)).setText( 152 Formatter.formatFileSize(this, mTransInfo.mTotalBytes)); 153 154 return view; 155 } 156 onIncomingFileConfirmOk()157 private void onIncomingFileConfirmOk() { 158 if (!mTimeout) { 159 // Update database 160 mUpdateValues = new ContentValues(); 161 mUpdateValues.put(BluetoothShare.USER_CONFIRMATION, 162 BluetoothShare.USER_CONFIRMATION_CONFIRMED); 163 BluetoothMethodProxy.getInstance().contentResolverUpdate(this.getContentResolver(), 164 mUri, mUpdateValues, null, null); 165 166 Toast.makeText(this, getString(R.string.bt_toast_1), Toast.LENGTH_SHORT).show(); 167 } 168 } 169 onIncomingFileConfirmCancel()170 private void onIncomingFileConfirmCancel() { 171 // Update database 172 mUpdateValues = new ContentValues(); 173 mUpdateValues.put(BluetoothShare.USER_CONFIRMATION, 174 BluetoothShare.USER_CONFIRMATION_DENIED); 175 BluetoothMethodProxy.getInstance().contentResolverUpdate(this.getContentResolver(), 176 mUri, mUpdateValues, null, null); 177 } 178 179 @Override onKeyDown(int keyCode, KeyEvent event)180 public boolean onKeyDown(int keyCode, KeyEvent event) { 181 if (keyCode == KeyEvent.KEYCODE_BACK) { 182 if (D) { 183 Log.d(TAG, "onKeyDown() called; Key: back key"); 184 } 185 finish(); 186 return true; 187 } 188 return false; 189 } 190 191 @Override onDestroy()192 protected void onDestroy() { 193 super.onDestroy(); 194 if (mReceiver != null) { 195 unregisterReceiver(mReceiver); 196 } 197 } 198 199 @Override onRestoreInstanceState(Bundle savedInstanceState)200 protected void onRestoreInstanceState(Bundle savedInstanceState) { 201 super.onRestoreInstanceState(savedInstanceState); 202 mTimeout = savedInstanceState.getBoolean(PREFERENCE_USER_TIMEOUT); 203 if (V) { 204 Log.v(TAG, "onRestoreInstanceState() mTimeout: " + mTimeout); 205 } 206 if (mTimeout) { 207 onTimeout(); 208 } 209 } 210 211 @Override onSaveInstanceState(Bundle outState)212 protected void onSaveInstanceState(Bundle outState) { 213 super.onSaveInstanceState(outState); 214 if (V) { 215 Log.v(TAG, "onSaveInstanceState() mTimeout: " + mTimeout); 216 } 217 outState.putBoolean(PREFERENCE_USER_TIMEOUT, mTimeout); 218 } 219 onTimeout()220 private void onTimeout() { 221 mTimeout = true; 222 223 changeTitle(getString( 224 R.string.incoming_file_confirm_timeout_content, 225 mTransInfo.mDeviceName)); 226 changeButtonVisibility(DialogInterface.BUTTON_NEGATIVE, View.GONE); 227 changeButtonText( 228 DialogInterface.BUTTON_POSITIVE, 229 getString(R.string.incoming_file_confirm_timeout_ok)); 230 231 BluetoothMethodProxy.getInstance().handlerSendMessageDelayed(mTimeoutHandler, 232 DISMISS_TIMEOUT_DIALOG, DISMISS_TIMEOUT_DIALOG_VALUE); 233 } 234 235 private final Handler mTimeoutHandler = new Handler() { 236 @Override 237 public void handleMessage(Message msg) { 238 switch (msg.what) { 239 case DISMISS_TIMEOUT_DIALOG: 240 if (V) { 241 Log.v(TAG, "Received DISMISS_TIMEOUT_DIALOG msg."); 242 } 243 finish(); 244 break; 245 default: 246 break; 247 } 248 } 249 }; 250 } 251