1 /* 2 * Copyright (C) 2011 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.nfc; 18 19 import com.android.nfc.beam.SendUi; 20 21 import android.app.NotificationManager; 22 import android.content.Context; 23 import android.content.res.Configuration; 24 import android.os.Vibrator; 25 26 /** 27 * Manages vibration, sound and animation for P2P events. 28 */ 29 public class P2pEventManager implements P2pEventListener, SendUi.Callback { 30 static final String TAG = "NfcP2pEventManager"; 31 static final boolean DBG = true; 32 33 static final long[] VIBRATION_PATTERN = {0, 100, 10000}; 34 35 final Context mContext; 36 final NfcService mNfcService; 37 final P2pEventListener.Callback mCallback; 38 final Vibrator mVibrator; 39 final NotificationManager mNotificationManager; 40 final SendUi mSendUi; 41 42 // only used on UI thread 43 boolean mSending; 44 boolean mNdefSent; 45 boolean mNdefReceived; 46 boolean mInDebounce; 47 P2pEventManager(Context context, P2pEventListener.Callback callback)48 public P2pEventManager(Context context, P2pEventListener.Callback callback) { 49 mNfcService = NfcService.getInstance(); 50 mContext = context; 51 mCallback = callback; 52 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 53 mNotificationManager = (NotificationManager) mContext.getSystemService( 54 Context.NOTIFICATION_SERVICE); 55 56 mSending = false; 57 final int uiModeType = mContext.getResources().getConfiguration().uiMode 58 & Configuration.UI_MODE_TYPE_MASK; 59 if (uiModeType == Configuration.UI_MODE_TYPE_APPLIANCE) { 60 // "Appliances" don't intrinsically have a way of confirming this, so we 61 // don't use the UI and just autoconfirm where necessary. 62 // Don't instantiate SendUi or else we'll use memory and never reclaim it. 63 mSendUi = null; 64 } else { 65 mSendUi = new SendUi(context, this); 66 } 67 } 68 69 @Override onP2pInRange()70 public void onP2pInRange() { 71 mNdefSent = false; 72 mNdefReceived = false; 73 mInDebounce = false; 74 75 if (mSendUi != null) { 76 mSendUi.takeScreenshot(); 77 } 78 } 79 80 @Override onP2pNfcTapRequested()81 public void onP2pNfcTapRequested() { 82 mNfcService.playSound(NfcService.SOUND_START); 83 mNdefSent = false; 84 mNdefReceived = false; 85 mInDebounce = false; 86 87 mVibrator.vibrate(VIBRATION_PATTERN, -1); 88 if (mSendUi != null) { 89 mSendUi.takeScreenshot(); 90 mSendUi.showPreSend(true); 91 } 92 } 93 94 @Override onP2pTimeoutWaitingForLink()95 public void onP2pTimeoutWaitingForLink() { 96 if (mSendUi != null) { 97 mSendUi.finish(SendUi.FINISH_SCALE_UP); 98 } 99 } 100 101 @Override onP2pSendConfirmationRequested()102 public void onP2pSendConfirmationRequested() { 103 mNfcService.playSound(NfcService.SOUND_START); 104 mVibrator.vibrate(VIBRATION_PATTERN, -1); 105 if (mSendUi != null) { 106 mSendUi.showPreSend(false); 107 } else { 108 mCallback.onP2pSendConfirmed(); 109 } 110 } 111 112 @Override onP2pSendComplete()113 public void onP2pSendComplete() { 114 mNfcService.playSound(NfcService.SOUND_END); 115 mVibrator.vibrate(VIBRATION_PATTERN, -1); 116 if (mSendUi != null) { 117 mSendUi.finish(SendUi.FINISH_SEND_SUCCESS); 118 } 119 mSending = false; 120 mNdefSent = true; 121 } 122 123 @Override onP2pHandoverNotSupported()124 public void onP2pHandoverNotSupported() { 125 mNfcService.playSound(NfcService.SOUND_ERROR); 126 mVibrator.vibrate(VIBRATION_PATTERN, -1); 127 mSendUi.finishAndToast(SendUi.FINISH_SCALE_UP, 128 mContext.getString(R.string.beam_handover_not_supported)); 129 mSending = false; 130 mNdefSent = false; 131 } 132 133 @Override onP2pHandoverBusy()134 public void onP2pHandoverBusy() { 135 mNfcService.playSound(NfcService.SOUND_ERROR); 136 mVibrator.vibrate(VIBRATION_PATTERN, -1); 137 mSendUi.finishAndToast(SendUi.FINISH_SCALE_UP, mContext.getString(R.string.beam_busy)); 138 mSending = false; 139 mNdefSent = false; 140 } 141 142 @Override onP2pReceiveComplete(boolean playSound)143 public void onP2pReceiveComplete(boolean playSound) { 144 mVibrator.vibrate(VIBRATION_PATTERN, -1); 145 if (playSound) mNfcService.playSound(NfcService.SOUND_END); 146 if (mSendUi != null) { 147 // TODO we still don't have a nice receive solution 148 // The sanest solution right now is just to scale back up what we had 149 // and start the new activity. It is not perfect, but at least it is 150 // consistent behavior. All other variants involve making the old 151 // activity screenshot disappear, and then removing the animation 152 // window hoping the new activity has started by then. This just goes 153 // wrong too often and can look weird. 154 mSendUi.finish(SendUi.FINISH_SCALE_UP); 155 } 156 mNdefReceived = true; 157 } 158 159 @Override onP2pOutOfRange()160 public void onP2pOutOfRange() { 161 if (mSending) { 162 mNfcService.playSound(NfcService.SOUND_ERROR); 163 mSending = false; 164 } 165 if (!mNdefSent && !mNdefReceived && mSendUi != null) { 166 mSendUi.finish(SendUi.FINISH_SCALE_UP); 167 } 168 mInDebounce = false; 169 } 170 171 @Override onSendConfirmed()172 public void onSendConfirmed() { 173 if (!mSending) { 174 if (mSendUi != null) { 175 mSendUi.showStartSend(); 176 } 177 mCallback.onP2pSendConfirmed(); 178 } 179 mSending = true; 180 181 } 182 183 @Override onCanceled()184 public void onCanceled() { 185 mSendUi.finish(SendUi.FINISH_SCALE_UP); 186 mCallback.onP2pCanceled(); 187 } 188 189 @Override onP2pSendDebounce()190 public void onP2pSendDebounce() { 191 mInDebounce = true; 192 mNfcService.playSound(NfcService.SOUND_ERROR); 193 if (mSendUi != null) { 194 mSendUi.showSendHint(); 195 } 196 } 197 198 @Override onP2pResumeSend()199 public void onP2pResumeSend() { 200 mVibrator.vibrate(VIBRATION_PATTERN, -1); 201 mNfcService.playSound(NfcService.SOUND_START); 202 if (mInDebounce) { 203 if (mSendUi != null) { 204 mSendUi.showStartSend(); 205 } 206 } 207 mInDebounce = false; 208 } 209 210 @Override isP2pIdle()211 public boolean isP2pIdle() { 212 if (mSendUi != null && !mSendUi.isSendUiInIdleState()) { 213 return false; 214 } 215 return true; 216 } 217 } 218