• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.ndefpush;
18 
19 import com.android.internal.nfc.LlcpException;
20 import com.android.internal.nfc.LlcpSocket;
21 import com.android.nfc.NfcService;
22 
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.nfc.NdefMessage;
28 import android.nfc.NfcAdapter;
29 import android.os.AsyncTask;
30 import android.util.Log;
31 
32 import java.io.IOException;
33 import java.util.Arrays;
34 
35 /**
36  * Simple client to push the local NDEF message to a server on the remote side of an
37  * LLCP connection. The message is set via {@link NfcAdapter#setLocalNdefMessage}.
38  */
39 public class NdefPushClient extends BroadcastReceiver {
40     private static final String TAG = "NdefPushClient";
41     private static final int MIU = 128;
42     private static final boolean DBG = true;
43 
44     /** Locked on MyTagClient.class */
45     NdefMessage mForegroundMsg;
46 
NdefPushClient(Context context)47     public NdefPushClient(Context context) {
48         context.registerReceiver(this, new IntentFilter(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED));
49     }
50 
setForegroundMessage(NdefMessage msg)51     public boolean setForegroundMessage(NdefMessage msg) {
52         synchronized (this) {
53             boolean set = mForegroundMsg != null;
54             mForegroundMsg = msg;
55             return set;
56         }
57     }
58 
getForegroundMessage()59     public NdefMessage getForegroundMessage() {
60         synchronized (this) {
61             return mForegroundMsg;
62         }
63     }
64 
65     @Override
onReceive(Context context, Intent intent)66     public void onReceive(Context context, Intent intent) {
67         int linkState = intent.getIntExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
68                 NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
69         if (linkState != NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
70             // The link was torn down, ignore
71             return;
72         }
73 
74         if (DBG) Log.d(TAG, "LLCP connection up and running");
75 
76         NdefMessage foregroundMsg;
77         synchronized (this) {
78             foregroundMsg = mForegroundMsg;
79         }
80 
81         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(context);
82         NdefMessage myTag = adapter.getLocalNdefMessage();
83 
84         if (foregroundMsg != null && myTag != null) {
85             if (DBG) Log.d(TAG, "sending foreground and my tag");
86             new SendAsync().execute(foregroundMsg, myTag);
87         } else if (myTag != null) {
88             if (DBG) Log.d(TAG, "sending my tag");
89             new SendAsync().execute(myTag);
90         } else if (foregroundMsg != null) {
91             if (DBG) Log.d(TAG, "sending foreground");
92             new SendAsync().execute(foregroundMsg);
93         } else {
94             if (DBG) Log.d(TAG, "no tags set, bailing");
95             return;
96         }
97     }
98 
99     final class SendAsync extends AsyncTask<NdefMessage, Void, Void> {
100         @Override
doInBackground(NdefMessage... msgs)101         public Void doInBackground(NdefMessage... msgs) {
102             NfcService service = NfcService.getInstance();
103 
104             // We only handle a single immediate action for now
105             NdefPushProtocol msg = new NdefPushProtocol(msgs[0], NdefPushProtocol.ACTION_IMMEDIATE);
106             byte[] buffer = msg.toByteArray();
107             int offset = 0;
108             int remoteMiu;
109             LlcpSocket sock = null;
110             try {
111                 if (DBG) Log.d(TAG, "about to create socket");
112                 // Connect to the my tag server on the remote side
113                 sock = service.createLlcpSocket(0, MIU, 1, 1024);
114                 if (DBG) Log.d(TAG, "about to connect to service " + NdefPushServer.SERVICE_NAME);
115                 sock.connect(NdefPushServer.SERVICE_NAME);
116 
117                 remoteMiu = sock.getRemoteSocketMiu();
118                 if (DBG) Log.d(TAG, "about to send a " + buffer.length + " byte message");
119                 while (offset < buffer.length) {
120                     int length = Math.min(buffer.length - offset, remoteMiu);
121                     byte[] tmpBuffer = Arrays.copyOfRange(buffer, offset, offset+length);
122                     if (DBG) Log.d(TAG, "about to send a " + length + " byte packet");
123                     sock.send(tmpBuffer);
124                     offset += length;
125                 }
126             } catch (IOException e) {
127                 Log.e(TAG, "couldn't send tag");
128                 if (DBG) Log.d(TAG, "exception:", e);
129             } catch (LlcpException e) {
130                 // Most likely the other side doesn't support the my tag protocol
131                 Log.e(TAG, "couldn't send tag");
132                 if (DBG) Log.d(TAG, "exception:", e);
133             } finally {
134                 if (sock != null) {
135                     try {
136                         if (DBG) Log.d(TAG, "about to close");
137                         sock.close();
138                     } catch (IOException e) {
139                         // Ignore
140                     }
141                 }
142             }
143             return null;
144         }
145     }
146 }
147