WifiP2pService.java revision c111d1caa8d4cc5d2139b5abd4d2db1f78560eff
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
143c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    /* Track whether we are in p2p discovery. This is used to avoid sending duplicate
144c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff     * broadcasts
145c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff     */
146c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    private boolean mDiscoveryStarted;
147c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
148aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private NetworkInfo mNetworkInfo;
149aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
150859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    /* Is chosen as a unique range to avoid conflict with
151859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff       the range defined in Tethering.java */
152859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
153859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String SERVER_ADDRESS = "192.168.49.1";
154859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
15555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public WifiP2pService(Context context) {
15655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext = context;
15755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1587d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff        //STOPSHIP: get this from native side
159fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mInterface = "p2p0";
160aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
161aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
162a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff        mP2pSupported = mContext.getPackageManager().hasSystemFeature(
163a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff                PackageManager.FEATURE_WIFI_DIRECT);
164a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff
165651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.primaryDeviceType = mContext.getResources().getString(
1669322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                com.android.internal.R.string.config_wifi_p2p_device_type);
167651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.deviceName = getDefaultDeviceName();
16855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
16955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
17055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine.start();
171aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
17255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
173cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    public void connectivityServiceReady() {
174cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
175cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        mNwService = INetworkManagementService.Stub.asInterface(b);
176cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    }
177cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
17855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceAccessPermission() {
17955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
18055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
18155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
18255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
18355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceChangePermission() {
18455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
18555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
18655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
18755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1889322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    /* We use the 4 digits of the ANDROID_ID to have a friendly
1899322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff     * default that has low likelihood of collision with a peer */
1909322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private String getDefaultDeviceName() {
1919322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        String id = Settings.Secure.getString(mContext.getContentResolver(),
1929322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Settings.Secure.ANDROID_ID);
1939322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        return "Android_" + id.substring(0,4);
1949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
1959322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
19655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
19755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Get a reference to handler. This is used by a client to establish
19855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * an AsyncChannel communication with WifiP2pService
19955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
20055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public Messenger getMessenger() {
20155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceAccessPermission();
20255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceChangePermission();
20355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        return new Messenger(mP2pStateMachine.getHandler());
20455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
20555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
20655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    @Override
20755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
20855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
20955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                != PackageManager.PERMISSION_GRANTED) {
21055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pw.println("Permission Denial: can't dump WifiP2pService from from pid="
21155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + Binder.getCallingPid()
21255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + ", uid=" + Binder.getCallingUid());
21355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return;
21455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
21555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
21655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
21955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Handles interaction with WifiStateMachine
22055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
22155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class P2pStateMachine extends StateMachine {
22255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
22355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private DefaultState mDefaultState = new DefaultState();
22455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
22555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
22655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
22755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
22855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
22955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Inactive is when p2p is enabled with no connectivity
23055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private InactiveState mInactiveState = new InactiveState();
231618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private GroupCreatingState mGroupCreatingState = new GroupCreatingState();
232618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private UserAuthorizingInvitationState mUserAuthorizingInvitationState
233618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                = new UserAuthorizingInvitationState();
234618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState();
23555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
236618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
23755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
238618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
23955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
240fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        private WifiNative mWifiNative = new WifiNative(mInterface);
241fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
24255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
244ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
24555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mGroup;
24655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
247618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        // Saved WifiP2pConfig for a peer connection
248618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private WifiP2pConfig mSavedPeerConfig;
24955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pGroup from invitation request
25155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mSavedP2pGroup;
25255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        P2pStateMachine(String name, boolean p2pSupported) {
25455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            super(name);
25555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            addState(mDefaultState);
25755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pNotSupportedState, mDefaultState);
25855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisablingState, mDefaultState);
25955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisabledState, mDefaultState);
26055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnablingState, mDefaultState);
26155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnabledState, mDefaultState);
26255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mInactiveState, mP2pEnabledState);
263618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    addState(mGroupCreatingState, mP2pEnabledState);
264618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mUserAuthorizingInvitationState, mGroupCreatingState);
265618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mProvisionDiscoveryState, mGroupCreatingState);
266618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mGroupNegotiationState, mGroupCreatingState);
26755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupCreatedState, mP2pEnabledState);
268618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mUserAuthorizingJoinState, mGroupCreatedState);
26955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
27055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (p2pSupported) {
27155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pDisabledState);
27255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else {
27355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pNotSupportedState);
27455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
27555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
27655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
27755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class DefaultState extends State {
27855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
27955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
280ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
28155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
28255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
28355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
284ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("Full connection with WifiStateMachine established");
28555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = (AsyncChannel) message.obj;
28655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
287ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Full connection failure, error = " + message.arg1);
28855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = null;
28955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
29055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
29155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
29255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
29355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
294ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Send failed, client connection lost");
29555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
296ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Client connection lost with reason: " + message.arg1);
29755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
29855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel = null;
29955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
30155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
30255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    AsyncChannel ac = new AsyncChannel();
30355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    ac.connect(mContext, getHandler(), message.replyTo);
30455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
3064be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
3074be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
30855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3097d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
3107d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
3117d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                            WifiP2pManager.BUSY);
3127d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    break;
31355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
3144be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
3154be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
31655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
317651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
318651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
319651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            WifiP2pManager.BUSY);
320651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    break;
32155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
3224be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
3234be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
32455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
3264be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
3274be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
32855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_PEERS:
330ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
331ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
332ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REQUEST_CONNECTION_INFO:
333ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
33455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3354be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                case WifiP2pManager.REQUEST_GROUP_INFO:
3364be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
3374be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    break;
338295da73f051e1a1280284d94d800c57f163a3986Irfan Sheriff                    // Ignore
339618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
3407d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SCAN_RESULTS_EVENT:
3417d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUP_CONNECTION_EVENT:
3427d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
3437d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.NETWORK_CONNECTION_EVENT:
3447d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
3457d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
346618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
347618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
348618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case GROUP_CREATING_TIMED_OUT:
34955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
35055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
351ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    loge("Unhandled message " + message);
35255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
35355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
35455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
35555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
35655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
35755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
35855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pNotSupportedState extends State {
35955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
36055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
36155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
3627d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               case WifiP2pManager.DISCOVER_PEERS:
3637d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
36455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
36555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3667d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
3677d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
368ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
369ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
370ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.CONNECT:
371ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
372ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
373ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
374651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
375651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
376651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
377651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    break;
3787d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               case WifiP2pManager.CREATE_GROUP:
379ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
380ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
381ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
382ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REMOVE_GROUP:
383ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
384ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
385ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
386ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff               default:
38755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
38855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
38955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
39055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
39155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
39255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
39355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisablingState extends State {
39455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
39555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
396ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
39755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
39855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_DISCONNECTION_EVENT:
3997d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (DBG) logd("p2p socket connection lost");
40055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisabledState);
40155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
4027d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4037d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
404ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
405ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
40655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
40755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
40855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
40955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
41055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
41155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
41255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
41355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisabledState extends State {
41455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync       @Override
41555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
416ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
41755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
41855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
41955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
42055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
421ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
42255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
4237d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
424cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                    try {
4257d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        mNwService.setInterfaceUp(mInterface);
4267d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } catch (RemoteException re) {
4277d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        loge("Unable to change interface settings: " + re);
4287d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } catch (IllegalStateException ie) {
4297d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        loge("Unable to change interface settings: " + ie);
43055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
4317d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    mWifiMonitor.startMonitoring();
4327d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    transitionTo(mP2pEnablingState);
43355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
4347d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
4357d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    //Nothing to do
436ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
43755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
43855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
43955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
44055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
44155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
44255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
44355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
44455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnablingState extends State {
44555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
44655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
447ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
44855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
44955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
45055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
45155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
452ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
45355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
45455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_CONNECTION_EVENT:
4557d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (DBG) logd("P2p socket connection successful");
45655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
45755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
458ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
4597d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    loge("P2p socket connection failed");
460aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    transitionTo(mP2pDisabledState);
461ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
4627d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4637d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
464ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
465ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
46655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
46755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
46855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
46955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
47055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
47155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
47255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
47355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnabledState extends State {
47455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
47555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
476ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
47755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(true);
478aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(true);
4799322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff            initializeP2pSettings();
48055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
48155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
48255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
48355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
484ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
48555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
4867d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4877d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    //Nothing to do
488ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
4897d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
490ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
4917d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    mWifiNative.closeSupplicantConnection();
49255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisablingState);
49355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
49455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
4957d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
496ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
497c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                        sendP2pDiscoveryChangedBroadcast(true);
498ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
4994be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
5004be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
501ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
50255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
503c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                case WifiMonitor.P2P_FIND_STOPPED_EVENT:
504c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                    sendP2pDiscoveryChangedBroadcast(false);
505c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                    break;
5067d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
5077d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (mWifiNative.p2pStopFind()) {
5087d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED);
5097d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } else {
5107d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
5117d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                                WifiP2pManager.ERROR);
5127d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    }
5137d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    break;
51455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
51555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
516651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
5174be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    mPeers.update(device);
51855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
51955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
52055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
52155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    device = (WifiP2pDevice) message.obj;
52255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
52355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
5247d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               default:
52555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
52655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
52755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
52855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
52955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
53055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
53155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void exit() {
53255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(false);
533aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(false);
53455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
53555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
53655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
53755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class InactiveState extends State {
5384be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        @Override
5394be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        public void enter() {
540ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
5414be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff            //Start listening every time we get inactive
5427d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff            //TODO: Fix listen after driver behavior is fixed
5437d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff            //mWifiNative.p2pListen();
54455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
54555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
54655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
54755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
548ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
54955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
550618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.CONNECT:
551618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd(getName() + " sending connect");
552618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = (WifiP2pConfig) message.obj;
553618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mPersistGroup = false;
554618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    int netId = configuredNetworkId(mSavedPeerConfig.deviceAddress);
555618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (netId >= 0) {
556618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //TODO: if failure, remove config and do a regular p2pConnect()
557fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
558618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
5597d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        //Stop discovery before issuing connect
5607d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        mWifiNative.p2pStopFind();
561618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //If peer is a GO, we do not need to send provisional discovery,
562618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //the supplicant takes care of it.
56361472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                        if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
564bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
565618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mGroupNegotiationState);
566618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        } else {
567618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mProvisionDiscoveryState);
568618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        }
569618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
570618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
571618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    sendP2pPeersChangedBroadcast();
572618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
573618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
57455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
575618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = (WifiP2pConfig) message.obj;
576618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
577618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
578618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
579618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pGroup group = (WifiP2pGroup) message.obj;
580bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    WifiP2pDevice owner = group.getOwner();
581bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
582bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    if (owner == null) {
583bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        if (DBG) loge("Ignored invitation from null owner");
584bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        break;
585bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    }
586bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
587bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
588bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mSavedPeerConfig.deviceAddress = group.getOwner().deviceAddress;
589bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
590bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //Check if we have the owner in peer list and use appropriate
591bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //wps method. Default is to use PBC.
592bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    if ((owner = getDeviceFromPeerList(owner.deviceAddress)) != null) {
593bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        if (owner.wpsPbcSupported()) {
594bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.PBC;
595bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        } else if (owner.wpsKeypadSupported()) {
596bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
597bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        } else if (owner.wpsDisplaySupported()) {
598bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
599bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        }
600bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    }
601618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
602618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
603618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
604618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
605618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
606618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
607618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
608618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
609618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
610618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
611618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Keypad prov disc request");
612618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
613618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
614618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
615618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Display prov disc request");
616618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
617618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.PBC;
618618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("PBC prov disc request");
619618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
620618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
62155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
62255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
6234be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    mPersistGroup = true;
624fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pGroupAdd()) {
625ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
626ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
6274be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
6284be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
629ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
63055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
63155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
632618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff               default:
633bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    return NOT_HANDLED;
634bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            }
635bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            return HANDLED;
636bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
637bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff    }
638bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
639618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class GroupCreatingState extends State {
640bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
641bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public void enter() {
642bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName());
643618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT,
644618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    ++mGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS);
645bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
646bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
647bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
648bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public boolean processMessage(Message message) {
649bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName() + message.toString());
650bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            switch (message.what) {
651618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff               case GROUP_CREATING_TIMED_OUT:
652618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mGroupCreatingTimeoutIndex == message.arg1) {
653618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Group negotiation timed out");
654618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED);
655618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig = null;
656618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
657618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mInactiveState);
658618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
659bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
660618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.DISCOVER_PEERS:
661618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    /* Discovery will break negotiation */
662618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
663618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            WifiP2pManager.BUSY);
664bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
665618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
666fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pCancelConnect()) {
667618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED);
668618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
669618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
670618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                WifiP2pManager.ERROR);
671618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
67255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
673ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                default:
67455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
67555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
67655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
67755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
67855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
67955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
680618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class UserAuthorizingInvitationState extends State {
681bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
682bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public void enter() {
683bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName());
684618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            notifyInvitationReceived();
685bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
686bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
687bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
688bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public boolean processMessage(Message message) {
689bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName() + message.toString());
690bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            switch (message.what) {
691618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
692618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    //TODO: handle persistence
69361472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
694bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
695618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
696bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        p2pConnectWithPinDisplay(mSavedPeerConfig, FORM_GROUP);
697618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
698618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
699618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    sendP2pPeersChangedBroadcast();
700618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupNegotiationState);
701618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
702618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
703618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd("User rejected invitation " + mSavedPeerConfig);
704618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
705bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    transitionTo(mInactiveState);
706bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
707bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                default:
708bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    return NOT_HANDLED;
709bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            }
710bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            return HANDLED;
711bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
712618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
713618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
714618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void exit() {
715618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            //TODO: dismiss dialog if not already done
716618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
717bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff    }
718bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
719618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class ProvisionDiscoveryState extends State {
720618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
721618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void enter() {
722618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName());
723fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff            mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig);
724618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
725618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
726618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
727618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public boolean processMessage(Message message) {
728618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName() + message.toString());
729618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            WifiP2pProvDiscEvent provDisc;
730618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            WifiP2pDevice device;
731618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            switch (message.what) {
732618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:
733618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
734618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
735618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
736618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
737618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
738618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
739fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
740618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mGroupNegotiationState);
741618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
742618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
743618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
744618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
745618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
746618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
747618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
748618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) {
749618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
750618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        /* we already have the pin */
751618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) {
752fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                            mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
753618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mGroupNegotiationState);
754618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        } else {
755618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mUserAuthorizingInvitationState);
756618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        }
757618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
758618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
759618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
760618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
761618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
762618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
763618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
764618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) {
765618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
766618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
767fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
768618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        notifyInvitationSent(provDisc.pin, device.deviceAddress);
769618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mGroupNegotiationState);
770618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
771618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
772618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                default:
773618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    return NOT_HANDLED;
774618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
775618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            return HANDLED;
776618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
777618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
778bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
77955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupNegotiationState extends State {
780aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        @Override
781aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void enter() {
782ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
78355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
78455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
78555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
78655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
787ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
78855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
78955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // We ignore these right now, since we get a GROUP_STARTED notification
79055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // afterwards
79155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
79255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
793ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go success");
79455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
795618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
796618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mGroup = (WifiP2pGroup) message.obj;
797618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd(getName() + " group started");
798618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mGroup.isGroupOwner()) {
799618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        startDhcpServer(mGroup.getInterface());
800618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
801618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
802618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                P2pStateMachine.this, mGroup.getInterface());
803618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
804618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        WifiP2pDevice groupOwner = mGroup.getOwner();
805618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        updateDeviceStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
806618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
807618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
808618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
809618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
810618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
81155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
81255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
813ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go failure");
814618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED);
815618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
816ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    sendP2pPeersChangedBroadcast();
81755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
81855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
81955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
82055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
82155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
82255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
82355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
82455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
82555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
826618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
827618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
82855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupCreatedState extends State {
82955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
83055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
831ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
832aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
833859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
834651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff            updateThisDevice(WifiP2pDevice.CONNECTED);
835651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
836859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            //DHCP server has already been started if I am a group owner
837859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            if (mGroup.isGroupOwner()) {
838859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
839859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                sendP2pConnectionChangedBroadcast();
840859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            }
84155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
84255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
84355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
84455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
845ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
84655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
84755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_CONNECTED_EVENT:
848bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
849bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    String deviceAddress = device.deviceAddress;
8509322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
8519322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        mGroup.addClient(deviceAddress);
852651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(deviceAddress, WifiP2pDevice.CONNECTED);
8539322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) logd(getName() + " ap sta connected");
8549322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        sendP2pPeersChangedBroadcast();
8559322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
856bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        loge("Connect on null device address, ignore");
8579322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    }
85855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
85955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
86061472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    device = (WifiP2pDevice) message.obj;
86161472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    deviceAddress = device.deviceAddress;
8629322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
863651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(deviceAddress, WifiP2pDevice.AVAILABLE);
8649322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (mGroup.removeClient(deviceAddress)) {
8659322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Removed client " + deviceAddress);
8664be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            if (!mPersistGroup && mGroup.isClientListEmpty()) {
8674be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                Slog.d(TAG, "Client list empty, remove non-persistent p2p group");
868fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                                mWifiNative.p2pGroupRemove(mGroup.getInterface());
8694be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            }
8709322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        } else {
8719322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Failed to remove client " + deviceAddress);
8729322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            for (WifiP2pDevice c : mGroup.getClientList()) {
8739322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                                if (DBG) logd("client " + c.deviceAddress);
8749322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            }
87555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
8764be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
8779322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) loge(getName() + " ap sta disconnected");
8789322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
87961472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                        loge("Disconnect on unknown device: " + device);
88055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
88155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
882aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                case DhcpStateMachine.CMD_POST_DHCP_ACTION:
883aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
884ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
885ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            dhcpInfo != null) {
886ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
887ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
888aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        sendP2pConnectionChangedBroadcast();
889ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
89061472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                        loge("DHCP failed");
891fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pGroupRemove(mGroup.getInterface());
892aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
893aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    break;
89455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
895ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " remove group");
896fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
897ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
898ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
8994be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
9004be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
901ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
90255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
90355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
904ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " group removed");
90555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
90655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    boolean changed = false;
90755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
90855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
909651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            d.status = WifiP2pDevice.AVAILABLE;
91055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            changed = true;
91155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
91255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
913aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
914aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    if (mGroup.isGroupOwner()) {
915aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        stopDhcpServer();
916aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    } else {
917ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("stop DHCP client");
918aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
919aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.quit();
920aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine = null;
921aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
922aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
92355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup = null;
92461472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    mWifiNative.p2pFlush();
92555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (changed) sendP2pPeersChangedBroadcast();
92655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
92755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
92855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
929bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    device = (WifiP2pDevice) message.obj;
930530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    //Device loss for a connected device indicates it is not in discovery any more
931530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    if (mGroup.contains(device)) {
932530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                        if (DBG) logd("Lost " + device +" , do nothing");
933530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                        return HANDLED;
93455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
935530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    // Do the regular device lost handling
936530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    return NOT_HANDLED;
9377d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
93855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.REMOVE_GROUP);
93955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
94055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
94155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
94255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pConfig config = (WifiP2pConfig) message.obj;
943ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("Inviting device : " + config.deviceAddress);
944fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {
945651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(config.deviceAddress, WifiP2pDevice.INVITED);
946ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        sendP2pPeersChangedBroadcast();
947ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
948ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
9494be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
9504be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
951ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
95255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: figure out updating the status to declined when invitation is rejected
95355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
95455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
95555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
956618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
957618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
958618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
959618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
960618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
961618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
962618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
963618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
964618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
965618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
966618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.PBC;
967618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
968618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingJoinState);
96955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
9709322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
9719322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Slog.e(TAG, "Duplicate group creation event notice, ignore");
9729322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    break;
97355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
97455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
97555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
97655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
97755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
978aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
979aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void exit() {
980651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff            updateThisDevice(WifiP2pDevice.AVAILABLE);
981ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            setWifiP2pInfoOnGroupTermination();
982aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
983ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            sendP2pConnectionChangedBroadcast();
984aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
98555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
98655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
987618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class UserAuthorizingJoinState extends State {
988618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
989618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void enter() {
990618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName());
991618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            notifyInvitationReceived();
992618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
993618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
994618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
995618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public boolean processMessage(Message message) {
996618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName() + message.toString());
997618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            switch (message.what) {
998618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
999618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
1000618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
1001618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    //Ignore more client requests
1002618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1003618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
1004618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
100586a5f5b9afa97a4ed6f5a2466fb9359ea131e2fbIrfan Sheriff                        mWifiNative.startWpsPbc(null);
1006618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
1007fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.startWpsPinKeypad(mSavedPeerConfig.wps.pin);
1008618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
1009618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
1010618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
1011618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1012618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
1013618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd("User rejected incoming request");
1014618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
1015618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
1016618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1017618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                default:
1018618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    return NOT_HANDLED;
1019618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
1020618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            return HANDLED;
1021618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1022618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1023618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
1024618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void exit() {
1025618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            //TODO: dismiss dialog if not already done
1026618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1027618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
1028618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
102955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pStateChangedBroadcast(boolean enabled) {
103055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
103155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
103255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (enabled) {
103355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
103455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_ENABLED);
103555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
103655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
103755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_DISABLED);
103855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
103955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendStickyBroadcast(intent);
104055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
104155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1042c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    private void sendP2pDiscoveryChangedBroadcast(boolean started) {
1043c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        if (mDiscoveryStarted == started) return;
1044c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        mDiscoveryStarted = started;
1045c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
1046c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        if (DBG) logd("discovery change broadcast " + started);
1047c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
1048c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
1049c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1050c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started ?
1051c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED :
1052c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);
1053c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        mContext.sendStickyBroadcast(intent);
1054c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    }
1055c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
1056651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void sendThisDeviceChangedBroadcast() {
1057651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
1058651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1059651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice));
1060651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mContext.sendStickyBroadcast(intent);
1061651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1062651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
106355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pPeersChangedBroadcast() {
106455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
106555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
106655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendBroadcast(intent);
106755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
106855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1069aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void sendP2pConnectionChangedBroadcast() {
1070ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (DBG) logd("sending p2p connection changed broadcast");
1071aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
1072aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1073aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
1074ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
1075aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
1076aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mContext.sendStickyBroadcast(intent);
1077aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
1078aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1079aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void startDhcpServer(String intf) {
1080aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        InterfaceConfiguration ifcg = null;
1081aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
1082aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            ifcg = mNwService.getInterfaceConfig(intf);
1083ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
1084ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey                        SERVER_ADDRESS), 24));
1085ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            ifcg.setInterfaceUp();
1086aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.setInterfaceConfig(intf, ifcg);
1087aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            /* This starts the dnsmasq server */
1088859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            mNwService.startTethering(DHCP_RANGE);
1089aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
1090ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error configuring interface " + intf + ", :" + e);
1091aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
1092aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
1093aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1094ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Started Dhcp server on " + intf);
1095859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff   }
1096aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1097aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void stopDhcpServer() {
1098aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
1099aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.stopTethering();
1100aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
1101ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error stopping Dhcp server" + e);
1102aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
1103aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
1104aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1105ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Stopped Dhcp server");
1106aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
1107aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
110855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pEnableFailure() {
110955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
111055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
111155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
111255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_failed_message))
111355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
111455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
111555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
111655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
111755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
111855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1119618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void addRowToDialog(ViewGroup group, int stringId, String value) {
112055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1121618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        View row = LayoutInflater.from(mContext).inflate(R.layout.wifi_p2p_dialog_row,
1122618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                group, false);
1123618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId));
1124618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ((TextView) row.findViewById(R.id.value)).setText(value);
1125618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        group.addView(row);
112655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
112755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1128618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void notifyInvitationSent(String pin, String peerAddress) {
112955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1130aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
113155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
1132618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                .inflate(R.layout.wifi_p2p_dialog, null);
1133618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1134618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
1135618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress));
1136618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin);
113755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
113855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
1139618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title))
114055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
1141618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setPositiveButton(r.getString(R.string.ok), null)
114255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
114355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
114455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
114555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
114655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1147618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void notifyInvitationReceived() {
114855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1149618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        final WpsInfo wps = mSavedPeerConfig.wps;
115055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
1151618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                .inflate(R.layout.wifi_p2p_dialog, null);
115255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1153618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
1154618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_from_message, getDeviceName(
1155618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                mSavedPeerConfig.deviceAddress));
115655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1157618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        final EditText pin = (EditText) textEntryView.findViewById(R.id.wifi_p2p_wps_pin);
115855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
115955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
1160618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title))
116155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
1162618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setPositiveButton(r.getString(R.string.accept), new OnClickListener() {
116355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
1164618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (wps.setup == WpsInfo.KEYPAD) {
1165618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                mSavedPeerConfig.wps.pin = pin.getText().toString();
1166618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            }
1167618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (DBG) logd(getName() + " accept invitation " + mSavedPeerConfig);
1168618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            sendMessage(PEER_CONNECTION_USER_ACCEPT);
1169bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        }
1170bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    })
1171618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
1172bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        @Override
1173bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        public void onClick(DialogInterface dialog, int which) {
1174618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (DBG) logd(getName() + " ignore connect");
1175618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            sendMessage(PEER_CONNECTION_USER_REJECT);
117655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
117755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
117855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
117955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1180618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //make the enter pin area or the display pin area visible
1181618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        switch (wps.setup) {
1182618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            case WpsInfo.KEYPAD:
1183618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                if (DBG) logd("Enter pin section visible");
1184618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE);
1185618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1186618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            case WpsInfo.DISPLAY:
1187618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                if (DBG) logd("Shown pin section visible");
1188618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin);
1189618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1190618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            default:
1191618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1192618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
119355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
119455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
119555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
119655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
119755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1198651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void updateDeviceStatus(String deviceAddress, int status) {
119955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
12008c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            if (d.deviceAddress.equals(deviceAddress)) {
120155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                d.status = status;
120255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
120355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
120455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
12058c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync
1206ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //TODO: implement when wpa_supplicant is fixed
1207ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int configuredNetworkId(String deviceAddress) {
1208ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        return -1;
1209ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1210ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1211ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
1212ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = true;
1213ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
1214ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
1215ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1216ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1217ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupTermination() {
1218ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = false;
1219ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = false;
1220ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = null;
1221ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1222ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1223618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private String getDeviceName(String deviceAddress) {
1224618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1225618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
1226618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                return d.deviceName;
1227618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
1228618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1229618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //Treat the address as name if there is no match
1230618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        return deviceAddress;
1231618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
1232618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1233bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    private WifiP2pDevice getDeviceFromPeerList(String deviceAddress) {
1234bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1235bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
1236bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                return d;
1237bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            }
1238bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        }
1239bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        return null;
1240bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    }
1241bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
1242bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    private void p2pConnectWithPinDisplay(WifiP2pConfig config, boolean join) {
1243fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        String pin = mWifiNative.p2pConnect(config, join);
1244bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        try {
1245bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            Integer.parseInt(pin);
1246bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            notifyInvitationSent(pin, config.deviceAddress);
1247bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        } catch (NumberFormatException ignore) {
1248bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            // do nothing if p2pConnect did not return a pin
1249bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        }
1250bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    }
1251bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
12529322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private void initializeP2pSettings() {
1253fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setPersistentReconnect(true);
1254fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setDeviceName(mThisDevice.deviceName);
1255530040e0b9458994c02f4392765db168128d48daIrfan Sheriff        //DIRECT-XY-DEVICENAME (XY is randomly generated)
1256fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
1257fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setDeviceType(mThisDevice.primaryDeviceType);
1258618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //The supplicant default is to support everything, but a bug necessitates
1259618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //the framework to specify this explicitly
1260fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setConfigMethods("keypad display push_button");
12614be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff
1262fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
1263651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        updateThisDevice(WifiP2pDevice.AVAILABLE);
1264651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        if (DBG) Slog.d(TAG, "DeviceAddress: " + mThisDevice.deviceAddress);
1265651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1266651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
1267651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void updateThisDevice(int status) {
1268651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.status = status;
1269651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        sendThisDeviceChangedBroadcast();
12709322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
12719322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
1272ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //State machine initiated requests can have replyTo set to null indicating
1273ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //there are no recepients, we ignore those reply actions
1274ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what) {
1275ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1276651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1277651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1278651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1279ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1280ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1281f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff    private void replyToMessage(Message msg, int what, int arg1) {
1282f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff        if (msg.replyTo == null) return;
1283651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1284651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1285651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.arg1 = arg1;
1286651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1287f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff    }
1288f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff
1289ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what, Object obj) {
1290ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1291651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1292651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1293651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.obj = obj;
1294651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1295651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1296651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
1297651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    /* arg2 on the source message has a hash code that needs to be retained in replies
1298651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff     * see WifiP2pManager for details */
1299651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private Message obtainMessage(Message srcMsg) {
1300651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message msg = Message.obtain();
1301651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        msg.arg2 = srcMsg.arg2;
1302651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        return msg;
1303ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1304ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1305ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void logd(String s) {
1306ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.d(TAG, s);
1307ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1308ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1309ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void loge(String s) {
1310ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.e(TAG, s);
1311ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1312ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
131355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
131455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync}
1315