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