WifiP2pService.java revision 86a5f5b9afa97a4ed6f5a2466fb9359ea131e2fb
155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync/*
255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * Copyright (C) 2011 The Android Open Source Project
355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *
455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * Licensed under the Apache License, Version 2.0 (the "License");
555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * you may not use this file except in compliance with the License.
655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * You may obtain a copy of the License at
755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *
855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *      http://www.apache.org/licenses/LICENSE-2.0
955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *
1055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * Unless required by applicable law or agreed to in writing, software
1155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * distributed under the License is distributed on an "AS IS" BASIS,
1255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * See the License for the specific language governing permissions and
1455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * limitations under the License.
1555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync */
1655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
17f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffpackage android.net.wifi.p2p;
1855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.app.AlertDialog;
20daf57e5ff495684f93d9ac2f5c5fc826a02f5f7aIrfan Sheriffimport android.app.Notification;
21daf57e5ff495684f93d9ac2f5c5fc826a02f5f7aIrfan Sheriffimport android.app.NotificationManager;
22daf57e5ff495684f93d9ac2f5c5fc826a02f5f7aIrfan Sheriffimport android.app.PendingIntent;
2355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.BroadcastReceiver;
2455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.Context;
2555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.DialogInterface;
2655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.DialogInterface.OnClickListener;
2755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.Intent;
2855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.IntentFilter;
2955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.pm.PackageManager;
3055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.res.Resources;
31aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.IConnectivityManager;
32aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.ConnectivityManager;
33aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.DhcpInfoInternal;
34aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.DhcpStateMachine;
35aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.InterfaceConfiguration;
36aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.LinkAddress;
37aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.LinkProperties;
38aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.NetworkInfo;
39aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.NetworkUtils;
4055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiManager;
4155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiMonitor;
4255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiNative;
4355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiStateMachine;
44651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriffimport android.net.wifi.WpsInfo;
4555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Binder;
4655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.IBinder;
47cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriffimport android.os.INetworkManagementService;
4855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Handler;
4955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.HandlerThread;
5055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Message;
51f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffimport android.os.Messenger;
527d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriffimport android.os.RemoteException;
53cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriffimport android.os.ServiceManager;
54cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriffimport android.os.SystemProperties;
559322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriffimport android.provider.Settings;
56618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriffimport android.text.TextUtils;
5755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.util.Slog;
5855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.LayoutInflater;
5955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.View;
60618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriffimport android.view.ViewGroup;
6155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.WindowManager;
6255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.widget.EditText;
63618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriffimport android.widget.TextView;
6455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
65f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffimport com.android.internal.R;
66616f3173e08ec6110cf5766c70f84c9e031fb7d7Irfan Sheriffimport com.android.internal.telephony.TelephonyIntents;
6755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.AsyncChannel;
6855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.Protocol;
6955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.State;
7055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.StateMachine;
7155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
72aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport java.io.FileDescriptor;
73aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport java.io.PrintWriter;
74aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport java.util.Collection;
75aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
7655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync/**
7755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications
7855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * communicate with this service to issue device discovery and connectivity requests
7955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * through the WifiP2pManager interface. The state machine communicates with the wifi
8055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * driver through wpa_supplicant and handles the event responses through WifiMonitor.
8155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *
8255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * Note that the term Wifi when used without a p2p suffix refers to the client mode
8355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * of Wifi operation
8455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * @hide
8555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync */
8655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncpublic class WifiP2pService extends IWifiP2pManager.Stub {
8755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final String TAG = "WifiP2pService";
887d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    private static final boolean DBG = false;
89aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private static final String NETWORKTYPE = "WIFI_P2P";
9055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
9155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private Context mContext;
92cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    private String mInterface;
93daf57e5ff495684f93d9ac2f5c5fc826a02f5f7aIrfan Sheriff    private Notification mNotification;
94cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
95cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    INetworkManagementService mNwService;
96aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private DhcpStateMachine mDhcpStateMachine;
9755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
9855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private P2pStateMachine mP2pStateMachine;
99ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private AsyncChannel mReplyChannel = new AsyncChannel();
10055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private AsyncChannel mWifiChannel;
10155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
102618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private static final Boolean JOIN_GROUP = true;
103618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private static final Boolean FORM_GROUP = false;
104618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
105ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /* Two minutes comes from the wpa_supplicant setting */
106618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000;
107618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private static int mGroupCreatingTimeoutIndex = 0;
108aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1097d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    /* Set a two minute discover timeout to avoid STA scans from being blocked */
1107d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    private static final int DISCOVER_TIMEOUT_S = 120;
1117d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff
112ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /**
113ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     * Delay between restarts upon failure to setup connection with supplicant
114ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     */
115ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
116ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
117ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /**
118ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     * Number of times we attempt to restart p2p
119ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     */
120ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int P2P_RESTART_TRIES = 5;
121ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
122ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int mP2pRestartCount = 0;
123ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
12455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
12555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
126618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    /* Delayed message to timeout group creation */
1277d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    public static final int GROUP_CREATING_TIMED_OUT        =   BASE + 1;
12855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
129618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    /* User accepted a peer request */
1307d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    private static final int PEER_CONNECTION_USER_ACCEPT    =   BASE + 2;
131618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    /* User rejected a peer request */
1327d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    private static final int PEER_CONNECTION_USER_REJECT    =   BASE + 3;
133295da73f051e1a1280284d94d800c57f163a3986Irfan Sheriff
13455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private final boolean mP2pSupported;
135651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
136651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private WifiP2pDevice mThisDevice = new WifiP2pDevice();
1374be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff
1384be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff    /* When a group has been explicitly created by an app, we persist the group
1394be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff     * even after all clients have been disconnected until an explicit remove
1404be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff     * is invoked */
1414be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff    private boolean mPersistGroup;
14255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
143aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private NetworkInfo mNetworkInfo;
144aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
145859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    /* Is chosen as a unique range to avoid conflict with
146859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff       the range defined in Tethering.java */
147859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
148859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String SERVER_ADDRESS = "192.168.49.1";
149859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
15055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public WifiP2pService(Context context) {
15155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext = context;
15255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1537d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff        //STOPSHIP: get this from native side
154fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mInterface = "p2p0";
155aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
156aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
157a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff        mP2pSupported = mContext.getPackageManager().hasSystemFeature(
158a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff                PackageManager.FEATURE_WIFI_DIRECT);
159a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff
160651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.primaryDeviceType = mContext.getResources().getString(
1619322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                com.android.internal.R.string.config_wifi_p2p_device_type);
162651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.deviceName = getDefaultDeviceName();
16355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
16455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
16555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine.start();
166aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
16755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
168cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    public void connectivityServiceReady() {
169cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
170cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        mNwService = INetworkManagementService.Stub.asInterface(b);
171cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    }
172cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
17355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceAccessPermission() {
17455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
17555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
17655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
17755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
17855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceChangePermission() {
17955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
18055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
18155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
18255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1839322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    /* We use the 4 digits of the ANDROID_ID to have a friendly
1849322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff     * default that has low likelihood of collision with a peer */
1859322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private String getDefaultDeviceName() {
1869322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        String id = Settings.Secure.getString(mContext.getContentResolver(),
1879322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Settings.Secure.ANDROID_ID);
1889322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        return "Android_" + id.substring(0,4);
1899322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
1909322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
19155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
19255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Get a reference to handler. This is used by a client to establish
19355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * an AsyncChannel communication with WifiP2pService
19455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
19555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public Messenger getMessenger() {
19655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceAccessPermission();
19755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceChangePermission();
19855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        return new Messenger(mP2pStateMachine.getHandler());
19955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
20055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
20155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    @Override
20255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
20355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
20455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                != PackageManager.PERMISSION_GRANTED) {
20555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pw.println("Permission Denial: can't dump WifiP2pService from from pid="
20655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + Binder.getCallingPid()
20755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + ", uid=" + Binder.getCallingUid());
20855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return;
20955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
21055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
21155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
21455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Handles interaction with WifiStateMachine
21555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
21655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class P2pStateMachine extends StateMachine {
21755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private DefaultState mDefaultState = new DefaultState();
21955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
22055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
22155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
22255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
22355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
22455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Inactive is when p2p is enabled with no connectivity
22555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private InactiveState mInactiveState = new InactiveState();
226618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private GroupCreatingState mGroupCreatingState = new GroupCreatingState();
227618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private UserAuthorizingInvitationState mUserAuthorizingInvitationState
228618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                = new UserAuthorizingInvitationState();
229618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState();
23055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
231618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
23255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
233618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
23455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
235fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        private WifiNative mWifiNative = new WifiNative(mInterface);
236fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
23755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
23855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
239ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
24055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mGroup;
24155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
242618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        // Saved WifiP2pConfig for a peer connection
243618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private WifiP2pConfig mSavedPeerConfig;
24455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pGroup from invitation request
24655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mSavedP2pGroup;
24755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        P2pStateMachine(String name, boolean p2pSupported) {
24955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            super(name);
25055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            addState(mDefaultState);
25255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pNotSupportedState, mDefaultState);
25355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisablingState, mDefaultState);
25455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisabledState, mDefaultState);
25555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnablingState, mDefaultState);
25655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnabledState, mDefaultState);
25755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mInactiveState, mP2pEnabledState);
258618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    addState(mGroupCreatingState, mP2pEnabledState);
259618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mUserAuthorizingInvitationState, mGroupCreatingState);
260618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mProvisionDiscoveryState, mGroupCreatingState);
261618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mGroupNegotiationState, mGroupCreatingState);
26255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupCreatedState, mP2pEnabledState);
263618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mUserAuthorizingJoinState, mGroupCreatedState);
26455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
26555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (p2pSupported) {
26655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pDisabledState);
26755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else {
26855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pNotSupportedState);
26955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
27055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
27155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
27255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class DefaultState extends State {
27355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
27455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
275ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
27655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
27755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
27855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
279ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("Full connection with WifiStateMachine established");
28055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = (AsyncChannel) message.obj;
28155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
282ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Full connection failure, error = " + message.arg1);
28355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = null;
28455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
28555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
28655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
28755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
28855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
289ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Send failed, client connection lost");
29055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
291ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Client connection lost with reason: " + message.arg1);
29255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
29355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel = null;
29455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
29555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
29655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
29755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    AsyncChannel ac = new AsyncChannel();
29855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    ac.connect(mContext, getHandler(), message.replyTo);
29955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
3014be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
3024be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
30355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3047d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
3057d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
3067d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                            WifiP2pManager.BUSY);
3077d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    break;
30855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
3094be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
3104be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
31155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
312651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
313651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
314651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            WifiP2pManager.BUSY);
315651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    break;
31655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
3174be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
3184be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
31955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
3214be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
3224be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
32355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_PEERS:
325ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
326ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
327ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REQUEST_CONNECTION_INFO:
328ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
32955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3304be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                case WifiP2pManager.REQUEST_GROUP_INFO:
3314be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
3324be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    break;
333295da73f051e1a1280284d94d800c57f163a3986Irfan Sheriff                    // Ignore
334618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
3357d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SCAN_RESULTS_EVENT:
3367d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUP_CONNECTION_EVENT:
3377d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
3387d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.NETWORK_CONNECTION_EVENT:
3397d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
3407d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
341618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
342618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
343618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case GROUP_CREATING_TIMED_OUT:
34455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
34555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
346ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    loge("Unhandled message " + message);
34755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
34855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
34955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
35055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
35155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
35255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
35355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pNotSupportedState extends State {
35455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
35555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
35655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
3577d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               case WifiP2pManager.DISCOVER_PEERS:
3587d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
35955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
36055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3617d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
3627d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
363ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
364ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
365ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.CONNECT:
366ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
367ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
368ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
369651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
370651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
371651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
372651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    break;
3737d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               case WifiP2pManager.CREATE_GROUP:
374ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
375ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
376ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
377ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REMOVE_GROUP:
378ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
379ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
380ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
381ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff               default:
38255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
38355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
38455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
38555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
38655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
38755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
38855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisablingState extends State {
38955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
39055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
391ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
39255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
39355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_DISCONNECTION_EVENT:
3947d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (DBG) logd("p2p socket connection lost");
39555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisabledState);
39655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3977d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
3987d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
399ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
400ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
40155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
40255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
40355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
40455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
40555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
40655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
40755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
40855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisabledState extends State {
40955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync       @Override
41055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
411ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
41255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
41355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
41455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
41555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
416ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
41755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
4187d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
419cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                    try {
4207d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        mNwService.setInterfaceUp(mInterface);
4217d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } catch (RemoteException re) {
4227d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        loge("Unable to change interface settings: " + re);
4237d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } catch (IllegalStateException ie) {
4247d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        loge("Unable to change interface settings: " + ie);
42555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
4267d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    mWifiMonitor.startMonitoring();
4277d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    transitionTo(mP2pEnablingState);
42855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
4297d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
4307d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    //Nothing to do
431ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
43255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
43355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
43455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
43555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
43655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
43755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
43855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
43955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnablingState extends State {
44055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
44155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
442ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
44355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
44455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
44555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
44655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
447ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
44855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
44955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_CONNECTION_EVENT:
4507d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (DBG) logd("P2p socket connection successful");
45155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
45255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
453ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
4547d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    loge("P2p socket connection failed");
455aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    transitionTo(mP2pDisabledState);
456ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
4577d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4587d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
459ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
460ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
46155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
46255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
46355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
46455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
46555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
46655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
46755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
46855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnabledState extends State {
46955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
47055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
471ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
47255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(true);
473aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(true);
4749322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff            initializeP2pSettings();
47555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
47655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
47755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
47855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
479ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
48055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
4817d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4827d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    //Nothing to do
483ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
4847d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
485ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
4867d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    mWifiNative.closeSupplicantConnection();
48755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisablingState);
48855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
48955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
4907d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
491ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
492ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
4934be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
4944be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
495ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
49655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
4977d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
4987d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (mWifiNative.p2pStopFind()) {
4997d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED);
5007d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } else {
5017d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
5027d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                                WifiP2pManager.ERROR);
5037d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    }
5047d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    break;
50555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
50655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
507651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
5084be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    mPeers.update(device);
50955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
51055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
51155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
51255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    device = (WifiP2pDevice) message.obj;
51355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
51455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
5157d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               default:
51655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
51755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
51855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
51955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
52055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
52155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
52255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void exit() {
52355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(false);
524aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(false);
52555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
52655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
52755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
52855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class InactiveState extends State {
5294be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        @Override
5304be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        public void enter() {
531ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
5324be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff            //Start listening every time we get inactive
5337d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff            //TODO: Fix listen after driver behavior is fixed
5347d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff            //mWifiNative.p2pListen();
53555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
53655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
53755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
53855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
539ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
54055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
541618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.CONNECT:
542618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd(getName() + " sending connect");
543618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = (WifiP2pConfig) message.obj;
544fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    String updatedPeerDetails = mWifiNative.p2pPeer(mSavedPeerConfig.deviceAddress);
545bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mPeers.update(new WifiP2pDevice(updatedPeerDetails));
546618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mPersistGroup = false;
547618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    int netId = configuredNetworkId(mSavedPeerConfig.deviceAddress);
548618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (netId >= 0) {
549618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //TODO: if failure, remove config and do a regular p2pConnect()
550fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
551618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
5527d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        //Stop discovery before issuing connect
5537d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        mWifiNative.p2pStopFind();
554618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //If peer is a GO, we do not need to send provisional discovery,
555618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //the supplicant takes care of it.
556618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (isGroupOwner(mSavedPeerConfig.deviceAddress)) {
557bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
558618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mGroupNegotiationState);
559618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        } else {
560618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mProvisionDiscoveryState);
561618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        }
562618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
563618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
564618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    sendP2pPeersChangedBroadcast();
565618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
566618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
56755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
568618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = (WifiP2pConfig) message.obj;
569618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
570618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
571618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
572618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pGroup group = (WifiP2pGroup) message.obj;
573bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    WifiP2pDevice owner = group.getOwner();
574bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
575bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    if (owner == null) {
576bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        if (DBG) loge("Ignored invitation from null owner");
577bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        break;
578bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    }
579bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
580bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
581bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mSavedPeerConfig.deviceAddress = group.getOwner().deviceAddress;
582bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
583bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //Check if we have the owner in peer list and use appropriate
584bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //wps method. Default is to use PBC.
585bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    if ((owner = getDeviceFromPeerList(owner.deviceAddress)) != null) {
586bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        if (owner.wpsPbcSupported()) {
587bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.PBC;
588bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        } else if (owner.wpsKeypadSupported()) {
589bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
590bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        } else if (owner.wpsDisplaySupported()) {
591bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
592bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        }
593bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    }
594618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
595618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
596618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
597618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
598618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
599618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
600618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
601618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
602618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
603618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
604618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Keypad prov disc request");
605618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
606618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
607618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
608618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Display prov disc request");
609618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
610618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.PBC;
611618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("PBC prov disc request");
612618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
613618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
61455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
61555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
6164be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    mPersistGroup = true;
617fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pGroupAdd()) {
618ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
619ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
6204be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
6214be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
622ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
62355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
62455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
625618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff               default:
626bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    return NOT_HANDLED;
627bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            }
628bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            return HANDLED;
629bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
630bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff    }
631bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
632618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class GroupCreatingState extends State {
633bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
634bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public void enter() {
635bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName());
636618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT,
637618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    ++mGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS);
638bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
639bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
640bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
641bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public boolean processMessage(Message message) {
642bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName() + message.toString());
643bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            switch (message.what) {
644618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff               case GROUP_CREATING_TIMED_OUT:
645618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mGroupCreatingTimeoutIndex == message.arg1) {
646618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Group negotiation timed out");
647618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED);
648618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig = null;
649618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
650618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mInactiveState);
651618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
652bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
653618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.DISCOVER_PEERS:
654618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    /* Discovery will break negotiation */
655618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
656618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            WifiP2pManager.BUSY);
657bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
658618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
659fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pCancelConnect()) {
660618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED);
661618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
662618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
663618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                WifiP2pManager.ERROR);
664618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
66555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
666ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                default:
66755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
66855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
66955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
67055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
67155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
67255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
673618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class UserAuthorizingInvitationState extends State {
674bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
675bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public void enter() {
676bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName());
677618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            notifyInvitationReceived();
678bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
679bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
680bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
681bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public boolean processMessage(Message message) {
682bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName() + message.toString());
683bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            switch (message.what) {
684618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
685618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    //TODO: handle persistence
686618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (isGroupOwner(mSavedPeerConfig.deviceAddress)) {
687bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
688618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
689bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        p2pConnectWithPinDisplay(mSavedPeerConfig, FORM_GROUP);
690618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
691618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
692618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    sendP2pPeersChangedBroadcast();
693618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupNegotiationState);
694618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
695618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
696618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd("User rejected invitation " + mSavedPeerConfig);
697618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
698bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    transitionTo(mInactiveState);
699bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
700bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                default:
701bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    return NOT_HANDLED;
702bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            }
703bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            return HANDLED;
704bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
705618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
706618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
707618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void exit() {
708618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            //TODO: dismiss dialog if not already done
709618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
710bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff    }
711bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
712618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class ProvisionDiscoveryState extends State {
713618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
714618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void enter() {
715618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName());
716fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff            mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig);
717618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
718618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
719618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
720618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public boolean processMessage(Message message) {
721618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName() + message.toString());
722618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            WifiP2pProvDiscEvent provDisc;
723618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            WifiP2pDevice device;
724618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            switch (message.what) {
725618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:
726618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
727618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
728618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
729618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
730618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
731618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
732fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
733618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mGroupNegotiationState);
734618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
735618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
736618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
737618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
738618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
739618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
740618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
741618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) {
742618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
743618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        /* we already have the pin */
744618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) {
745fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                            mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
746618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mGroupNegotiationState);
747618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        } else {
748618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mUserAuthorizingInvitationState);
749618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        }
750618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
751618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
752618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
753618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
754618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
755618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
756618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
757618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) {
758618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
759618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
760fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
761618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        notifyInvitationSent(provDisc.pin, device.deviceAddress);
762618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mGroupNegotiationState);
763618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
764618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
765618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                default:
766618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    return NOT_HANDLED;
767618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
768618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            return HANDLED;
769618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
770618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
771bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
77255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupNegotiationState extends State {
773aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        @Override
774aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void enter() {
775ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
77655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
77755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
77855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
77955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
780ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
78155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
78255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // We ignore these right now, since we get a GROUP_STARTED notification
78355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // afterwards
78455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
78555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
786ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go success");
78755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
788618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
789618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mGroup = (WifiP2pGroup) message.obj;
790618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd(getName() + " group started");
791618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mGroup.isGroupOwner()) {
792618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        startDhcpServer(mGroup.getInterface());
793618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
794618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
795618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                P2pStateMachine.this, mGroup.getInterface());
796618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
797618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        WifiP2pDevice groupOwner = mGroup.getOwner();
798618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        updateDeviceStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
799618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
800618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
801618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
802618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
803618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
80455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
80555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
806ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go failure");
807618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED);
808618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
809ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    sendP2pPeersChangedBroadcast();
81055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
81155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
81255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
81355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
81455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
81555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
81655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
81755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
81855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
819618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
820618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
82155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupCreatedState extends State {
82255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
82355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
824ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
825aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
826859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
827651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff            updateThisDevice(WifiP2pDevice.CONNECTED);
828651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
829859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            //DHCP server has already been started if I am a group owner
830859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            if (mGroup.isGroupOwner()) {
831859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
832859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                sendP2pConnectionChangedBroadcast();
833859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            }
83455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
83555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
83655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
83755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
838ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
83955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
84055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_CONNECTED_EVENT:
841bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
842bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    String deviceAddress = device.deviceAddress;
8439322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
8449322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        mGroup.addClient(deviceAddress);
845bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        mPeers.updateInterfaceAddress(device);
846651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(deviceAddress, WifiP2pDevice.CONNECTED);
8479322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) logd(getName() + " ap sta connected");
8489322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        sendP2pPeersChangedBroadcast();
8499322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
850bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        loge("Connect on null device address, ignore");
8519322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    }
85255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
85355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
854bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //TODO: the disconnection event is still inconsistent and reports
855bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //interface address. Fix this after wpa_supplicant is fixed.
856bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    String interfaceAddress = (String) message.obj;
8578c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                    deviceAddress = getDeviceAddress(interfaceAddress);
8589322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
859651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(deviceAddress, WifiP2pDevice.AVAILABLE);
8609322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (mGroup.removeClient(deviceAddress)) {
8619322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Removed client " + deviceAddress);
8624be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            if (!mPersistGroup && mGroup.isClientListEmpty()) {
8634be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                Slog.d(TAG, "Client list empty, remove non-persistent p2p group");
864fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                                mWifiNative.p2pGroupRemove(mGroup.getInterface());
8654be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            }
8669322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        } else {
8679322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Failed to remove client " + deviceAddress);
8689322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            for (WifiP2pDevice c : mGroup.getClientList()) {
8699322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                                if (DBG) logd("client " + c.deviceAddress);
8709322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            }
87155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
8724be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
8739322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) loge(getName() + " ap sta disconnected");
8749322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
875bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        loge("Disconnect on unknown interface address : " + interfaceAddress);
87655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
87755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
878aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                case DhcpStateMachine.CMD_POST_DHCP_ACTION:
879aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
880ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
881ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            dhcpInfo != null) {
882ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
883ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
884aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        sendP2pConnectionChangedBroadcast();
885ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
886fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pGroupRemove(mGroup.getInterface());
887aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
888aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    break;
88955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
890ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " remove group");
891fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
892ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
893ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
8944be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
8954be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
896ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
89755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
89855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
899ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " group removed");
90055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
90155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    boolean changed = false;
90255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
90355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
904651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            d.status = WifiP2pDevice.AVAILABLE;
90555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            changed = true;
90655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
90755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
908aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
909aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    if (mGroup.isGroupOwner()) {
910aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        stopDhcpServer();
911aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    } else {
912ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("stop DHCP client");
913aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
914aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.quit();
915aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine = null;
916aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
917aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
91855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup = null;
91955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (changed) sendP2pPeersChangedBroadcast();
92055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
92155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
92255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
923bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    device = (WifiP2pDevice) message.obj;
924530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    //Device loss for a connected device indicates it is not in discovery any more
925530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    if (mGroup.contains(device)) {
926530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                        if (DBG) logd("Lost " + device +" , do nothing");
927530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                        return HANDLED;
92855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
929530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    // Do the regular device lost handling
930530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    return NOT_HANDLED;
9317d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
93255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.REMOVE_GROUP);
93355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
93455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
93555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
93655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pConfig config = (WifiP2pConfig) message.obj;
937ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("Inviting device : " + config.deviceAddress);
938fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {
939651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(config.deviceAddress, WifiP2pDevice.INVITED);
940ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        sendP2pPeersChangedBroadcast();
941ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
942ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
9434be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
9444be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
945ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
94655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: figure out updating the status to declined when invitation is rejected
94755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
94855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
94955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
950618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
951618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
952618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
953618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
954618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
955618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
956618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
957618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
958618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
959618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
960618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.PBC;
961618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
962618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingJoinState);
96355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
9649322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
9659322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Slog.e(TAG, "Duplicate group creation event notice, ignore");
9669322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    break;
96755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
96855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
96955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
97055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
97155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
972aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
973aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void exit() {
974651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff            updateThisDevice(WifiP2pDevice.AVAILABLE);
975ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            setWifiP2pInfoOnGroupTermination();
976aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
977ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            sendP2pConnectionChangedBroadcast();
978aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
97955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
98055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
981618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class UserAuthorizingJoinState extends State {
982618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
983618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void enter() {
984618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName());
985618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            notifyInvitationReceived();
986618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
987618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
988618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
989618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public boolean processMessage(Message message) {
990618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName() + message.toString());
991618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            switch (message.what) {
992618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
993618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
994618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
995618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    //Ignore more client requests
996618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
997618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
998618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
99986a5f5b9afa97a4ed6f5a2466fb9359ea131e2fbIrfan Sheriff                        mWifiNative.startWpsPbc(null);
1000618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
1001fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.startWpsPinKeypad(mSavedPeerConfig.wps.pin);
1002618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
1003618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
1004618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
1005618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1006618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
1007618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd("User rejected incoming request");
1008618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
1009618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
1010618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1011618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                default:
1012618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    return NOT_HANDLED;
1013618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
1014618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            return HANDLED;
1015618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1016618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1017618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
1018618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void exit() {
1019618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            //TODO: dismiss dialog if not already done
1020618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1021618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
1022618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
102355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pStateChangedBroadcast(boolean enabled) {
102455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
102555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
102655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (enabled) {
102755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
102855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_ENABLED);
102955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
103055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
103155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_DISABLED);
103255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
103355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendStickyBroadcast(intent);
103455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
103555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1036651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void sendThisDeviceChangedBroadcast() {
1037651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
1038651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1039651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice));
1040651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mContext.sendStickyBroadcast(intent);
1041651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1042651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
104355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pPeersChangedBroadcast() {
104455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
104555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
104655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendBroadcast(intent);
104755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
104855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1049aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void sendP2pConnectionChangedBroadcast() {
1050ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (DBG) logd("sending p2p connection changed broadcast");
1051aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
1052aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1053aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
1054ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
1055aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
1056aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mContext.sendStickyBroadcast(intent);
1057aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
1058aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1059aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void startDhcpServer(String intf) {
1060aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        InterfaceConfiguration ifcg = null;
1061aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
1062aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            ifcg = mNwService.getInterfaceConfig(intf);
1063ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
1064ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey                        SERVER_ADDRESS), 24));
1065ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            ifcg.setInterfaceUp();
1066aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.setInterfaceConfig(intf, ifcg);
1067aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            /* This starts the dnsmasq server */
1068859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            mNwService.startTethering(DHCP_RANGE);
1069aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
1070ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error configuring interface " + intf + ", :" + e);
1071aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
1072aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
1073aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1074ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Started Dhcp server on " + intf);
1075859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff   }
1076aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1077aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void stopDhcpServer() {
1078aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
1079aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.stopTethering();
1080aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
1081ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error stopping Dhcp server" + e);
1082aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
1083aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
1084aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1085ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Stopped Dhcp server");
1086aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
1087aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
108855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pEnableFailure() {
108955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
109055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
109155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
109255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_failed_message))
109355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
109455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
109555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
109655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
109755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
109855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1099618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void addRowToDialog(ViewGroup group, int stringId, String value) {
110055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1101618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        View row = LayoutInflater.from(mContext).inflate(R.layout.wifi_p2p_dialog_row,
1102618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                group, false);
1103618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId));
1104618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ((TextView) row.findViewById(R.id.value)).setText(value);
1105618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        group.addView(row);
110655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
110755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1108618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void notifyInvitationSent(String pin, String peerAddress) {
110955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1110aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
111155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
1112618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                .inflate(R.layout.wifi_p2p_dialog, null);
1113618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1114618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
1115618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress));
1116618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin);
111755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
111855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
1119618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title))
112055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
1121618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setPositiveButton(r.getString(R.string.ok), null)
112255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
112355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
112455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
112555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
112655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1127618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void notifyInvitationReceived() {
112855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1129618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        final WpsInfo wps = mSavedPeerConfig.wps;
113055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
1131618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                .inflate(R.layout.wifi_p2p_dialog, null);
113255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1133618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
1134618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_from_message, getDeviceName(
1135618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                mSavedPeerConfig.deviceAddress));
113655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1137618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        final EditText pin = (EditText) textEntryView.findViewById(R.id.wifi_p2p_wps_pin);
113855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
113955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
1140618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title))
114155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
1142618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setPositiveButton(r.getString(R.string.accept), new OnClickListener() {
114355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
1144618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (wps.setup == WpsInfo.KEYPAD) {
1145618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                mSavedPeerConfig.wps.pin = pin.getText().toString();
1146618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            }
1147618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (DBG) logd(getName() + " accept invitation " + mSavedPeerConfig);
1148618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            sendMessage(PEER_CONNECTION_USER_ACCEPT);
1149bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        }
1150bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    })
1151618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
1152bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        @Override
1153bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        public void onClick(DialogInterface dialog, int which) {
1154618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (DBG) logd(getName() + " ignore connect");
1155618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            sendMessage(PEER_CONNECTION_USER_REJECT);
115655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
115755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
115855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
115955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1160618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //make the enter pin area or the display pin area visible
1161618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        switch (wps.setup) {
1162618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            case WpsInfo.KEYPAD:
1163618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                if (DBG) logd("Enter pin section visible");
1164618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE);
1165618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1166618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            case WpsInfo.DISPLAY:
1167618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                if (DBG) logd("Shown pin section visible");
1168618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin);
1169618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1170618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            default:
1171618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1172618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
117355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
117455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
117555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
117655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
117755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1178651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void updateDeviceStatus(String deviceAddress, int status) {
117955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
11808c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            if (d.deviceAddress.equals(deviceAddress)) {
118155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                d.status = status;
118255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
118355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
118455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
11858c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync
11864be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff    private boolean isGroupOwner(String deviceAddress) {
11874be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
11884be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
11894be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                return d.isGroupOwner();
11904be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff            }
11914be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        }
11924be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        return false;
11934be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff    }
11944be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff
1195ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //TODO: implement when wpa_supplicant is fixed
1196ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int configuredNetworkId(String deviceAddress) {
1197ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        return -1;
1198ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1199ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1200ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
1201ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = true;
1202ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
1203ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
1204ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1205ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1206ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupTermination() {
1207ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = false;
1208ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = false;
1209ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = null;
1210ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1211ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1212618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private String getDeviceName(String deviceAddress) {
1213618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1214618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
1215618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                return d.deviceName;
1216618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
1217618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1218618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //Treat the address as name if there is no match
1219618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        return deviceAddress;
1220618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
1221618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
12228c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync    private String getDeviceAddress(String interfaceAddress) {
12238c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1224bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            if (interfaceAddress.equals(d.interfaceAddress)) {
12258c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                return d.deviceAddress;
12268c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            }
12278c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync        }
12288c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync        return null;
12298c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync    }
12308c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync
1231bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    private WifiP2pDevice getDeviceFromPeerList(String deviceAddress) {
1232bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1233bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
1234bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                return d;
1235bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            }
1236bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        }
1237bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        return null;
1238bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    }
1239bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
1240bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    private void p2pConnectWithPinDisplay(WifiP2pConfig config, boolean join) {
1241fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        String pin = mWifiNative.p2pConnect(config, join);
1242bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        try {
1243bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            Integer.parseInt(pin);
1244bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            notifyInvitationSent(pin, config.deviceAddress);
1245bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        } catch (NumberFormatException ignore) {
1246bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            // do nothing if p2pConnect did not return a pin
1247bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        }
1248bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    }
1249bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
12509322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private void initializeP2pSettings() {
1251fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setPersistentReconnect(true);
1252fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setDeviceName(mThisDevice.deviceName);
1253530040e0b9458994c02f4392765db168128d48daIrfan Sheriff        //DIRECT-XY-DEVICENAME (XY is randomly generated)
1254fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
1255fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setDeviceType(mThisDevice.primaryDeviceType);
1256618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //The supplicant default is to support everything, but a bug necessitates
1257618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //the framework to specify this explicitly
1258fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setConfigMethods("keypad display push_button");
12594be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff
1260fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
1261651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        updateThisDevice(WifiP2pDevice.AVAILABLE);
1262651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        if (DBG) Slog.d(TAG, "DeviceAddress: " + mThisDevice.deviceAddress);
1263651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1264651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
1265651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void updateThisDevice(int status) {
1266651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.status = status;
1267651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        sendThisDeviceChangedBroadcast();
12689322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
12699322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
1270ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //State machine initiated requests can have replyTo set to null indicating
1271ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //there are no recepients, we ignore those reply actions
1272ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what) {
1273ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1274651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1275651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1276651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1277ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1278ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1279f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff    private void replyToMessage(Message msg, int what, int arg1) {
1280f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff        if (msg.replyTo == null) return;
1281651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1282651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1283651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.arg1 = arg1;
1284651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1285f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff    }
1286f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff
1287ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what, Object obj) {
1288ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1289651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1290651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1291651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.obj = obj;
1292651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1293651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1294651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
1295651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    /* arg2 on the source message has a hash code that needs to be retained in replies
1296651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff     * see WifiP2pManager for details */
1297651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private Message obtainMessage(Message srcMsg) {
1298651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message msg = Message.obtain();
1299651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        msg.arg2 = srcMsg.arg2;
1300651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        return msg;
1301ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1302ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1303ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void logd(String s) {
1304ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.d(TAG, s);
1305ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1306ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1307ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void loge(String s) {
1308ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.e(TAG, s);
1309ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1310ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
131155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
131255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync}
1313