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