WifiP2pService.java revision 55bfa42b05868a62ea66d291dcc51f0150fadcc2
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
11255bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff    /* Idle time after a peer is gone when the group is torn down */
11355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff    private static final int GROUP_IDLE_TIME_S = 2;
11455bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff
115ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /**
116ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     * Delay between restarts upon failure to setup connection with supplicant
117ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     */
118ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
119ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
120ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /**
121ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     * Number of times we attempt to restart p2p
122ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     */
123ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int P2P_RESTART_TRIES = 5;
124ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
125ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int mP2pRestartCount = 0;
126ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
12755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
12855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
129618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    /* Delayed message to timeout group creation */
1307d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    public static final int GROUP_CREATING_TIMED_OUT        =   BASE + 1;
13155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
132618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    /* User accepted a peer request */
1337d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    private static final int PEER_CONNECTION_USER_ACCEPT    =   BASE + 2;
134618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    /* User rejected a peer request */
1357d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff    private static final int PEER_CONNECTION_USER_REJECT    =   BASE + 3;
136295da73f051e1a1280284d94d800c57f163a3986Irfan Sheriff
13755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private final boolean mP2pSupported;
138651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
139651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private WifiP2pDevice mThisDevice = new WifiP2pDevice();
1404be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff
1414be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff    /* When a group has been explicitly created by an app, we persist the group
1424be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff     * even after all clients have been disconnected until an explicit remove
1434be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff     * is invoked */
1444be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff    private boolean mPersistGroup;
14555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
146c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    /* Track whether we are in p2p discovery. This is used to avoid sending duplicate
147c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff     * broadcasts
148c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff     */
149c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    private boolean mDiscoveryStarted;
150c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
151aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private NetworkInfo mNetworkInfo;
152aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
153859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    /* Is chosen as a unique range to avoid conflict with
154859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff       the range defined in Tethering.java */
155859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
156859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String SERVER_ADDRESS = "192.168.49.1";
157859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
15855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public WifiP2pService(Context context) {
15955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext = context;
16055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1617d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff        //STOPSHIP: get this from native side
162fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mInterface = "p2p0";
163aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
164aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
165a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff        mP2pSupported = mContext.getPackageManager().hasSystemFeature(
166a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff                PackageManager.FEATURE_WIFI_DIRECT);
167a8f63a38a0570d2521d5db73f05218d114fa902aIrfan Sheriff
168651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.primaryDeviceType = mContext.getResources().getString(
1699322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                com.android.internal.R.string.config_wifi_p2p_device_type);
170651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.deviceName = getDefaultDeviceName();
17155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
17255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
17355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine.start();
174aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
17555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
176cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    public void connectivityServiceReady() {
177cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
178cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        mNwService = INetworkManagementService.Stub.asInterface(b);
179cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    }
180cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
18155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceAccessPermission() {
18255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
18355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
18455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
18555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
18655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceChangePermission() {
18755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
18855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
18955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
19055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1919322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    /* We use the 4 digits of the ANDROID_ID to have a friendly
1929322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff     * default that has low likelihood of collision with a peer */
1939322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private String getDefaultDeviceName() {
1949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        String id = Settings.Secure.getString(mContext.getContentResolver(),
1959322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Settings.Secure.ANDROID_ID);
1969322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        return "Android_" + id.substring(0,4);
1979322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
1989322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
19955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
20055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Get a reference to handler. This is used by a client to establish
20155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * an AsyncChannel communication with WifiP2pService
20255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
20355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public Messenger getMessenger() {
20455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceAccessPermission();
20555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceChangePermission();
20655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        return new Messenger(mP2pStateMachine.getHandler());
20755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
20855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
20955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    @Override
21055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
21155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
21255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                != PackageManager.PERMISSION_GRANTED) {
21355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pw.println("Permission Denial: can't dump WifiP2pService from from pid="
21455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + Binder.getCallingPid()
21555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + ", uid=" + Binder.getCallingUid());
21655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return;
21755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
21855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
21955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
22055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
22155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
22255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Handles interaction with WifiStateMachine
22355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
22455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class P2pStateMachine extends StateMachine {
22555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
22655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private DefaultState mDefaultState = new DefaultState();
22755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
22855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
22955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
23055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
23155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
23255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Inactive is when p2p is enabled with no connectivity
23355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private InactiveState mInactiveState = new InactiveState();
234618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private GroupCreatingState mGroupCreatingState = new GroupCreatingState();
235618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private UserAuthorizingInvitationState mUserAuthorizingInvitationState
236618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                = new UserAuthorizingInvitationState();
237618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState();
23855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
239618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
24055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
241618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
24255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
243fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        private WifiNative mWifiNative = new WifiNative(mInterface);
244fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
24555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
247ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
24855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mGroup;
24955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
250618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        // Saved WifiP2pConfig for a peer connection
251618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        private WifiP2pConfig mSavedPeerConfig;
25255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pGroup from invitation request
25455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mSavedP2pGroup;
25555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        P2pStateMachine(String name, boolean p2pSupported) {
25755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            super(name);
25855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            addState(mDefaultState);
26055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pNotSupportedState, mDefaultState);
26155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisablingState, mDefaultState);
26255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisabledState, mDefaultState);
26355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnablingState, mDefaultState);
26455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnabledState, mDefaultState);
26555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mInactiveState, mP2pEnabledState);
266618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    addState(mGroupCreatingState, mP2pEnabledState);
267618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mUserAuthorizingInvitationState, mGroupCreatingState);
268618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mProvisionDiscoveryState, mGroupCreatingState);
269618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mGroupNegotiationState, mGroupCreatingState);
27055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupCreatedState, mP2pEnabledState);
271618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        addState(mUserAuthorizingJoinState, mGroupCreatedState);
27255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
27355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (p2pSupported) {
27455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pDisabledState);
27555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else {
27655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pNotSupportedState);
27755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
27855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
27955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
28055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class DefaultState extends State {
28155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
28255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
283ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
28455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
28555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
28655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
287ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("Full connection with WifiStateMachine established");
28855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = (AsyncChannel) message.obj;
28955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
290ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Full connection failure, error = " + message.arg1);
29155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = null;
29255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
29355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
29455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
29555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
29655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
297ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Send failed, client connection lost");
29855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
299ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Client connection lost with reason: " + message.arg1);
30055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
30155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel = null;
30255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
30455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
30555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    AsyncChannel ac = new AsyncChannel();
30655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    ac.connect(mContext, getHandler(), message.replyTo);
30755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
3094be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
3104be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
31155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3127d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
3137d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
3147d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                            WifiP2pManager.BUSY);
3157d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    break;
31655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
3174be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
3184be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
31955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
320651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
321651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
322651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            WifiP2pManager.BUSY);
323651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    break;
32455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
3254be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
3264be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
32755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
3294be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
3304be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            WifiP2pManager.BUSY);
33155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
33255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_PEERS:
333ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
334ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
335ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REQUEST_CONNECTION_INFO:
336ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
33755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3384be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                case WifiP2pManager.REQUEST_GROUP_INFO:
3394be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
3404be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    break;
341295da73f051e1a1280284d94d800c57f163a3986Irfan Sheriff                    // Ignore
342618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
3437d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SCAN_RESULTS_EVENT:
3447d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUP_CONNECTION_EVENT:
3457d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
3467d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.NETWORK_CONNECTION_EVENT:
3477d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
3487d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
34955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
350618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
351618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
352618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case GROUP_CREATING_TIMED_OUT:
35355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
35455bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                /* unexpected group created, remove */
35555bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
35655bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    mGroup = (WifiP2pGroup) message.obj;
35755bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    loge("Unexpected group creation, remove " + mGroup);
35855bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    mWifiNative.p2pGroupRemove(mGroup.getInterface());
35955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    break;
36055bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
36155bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    loge("Unexpected group failure, flush peers");
36255bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    mWifiNative.p2pFlush();
36355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    break;
36455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
365ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    loge("Unhandled message " + message);
36655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
36755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
36855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
36955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
37055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
37155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
37255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pNotSupportedState extends State {
37355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
37455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
37555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
3767d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               case WifiP2pManager.DISCOVER_PEERS:
3777d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
37855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
37955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
3807d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
3817d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
382ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
383ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
384ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.CONNECT:
385ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
386ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
387ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
388651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
389651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
390651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
391651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    break;
3927d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               case WifiP2pManager.CREATE_GROUP:
393ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
394ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
395ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
396ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REMOVE_GROUP:
397ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
398ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
399ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
400ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff               default:
40155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
40255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
40355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
40455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
40555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
40655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
40755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisablingState extends State {
40855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
40955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
410ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
41155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
41255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_DISCONNECTION_EVENT:
4137d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (DBG) logd("p2p socket connection lost");
41455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisabledState);
41555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
4167d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4177d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
418ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
419ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
42055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
42155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
42255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
42355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
42455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
42555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
42655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
42755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisabledState extends State {
42855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync       @Override
42955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
430ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
43155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
43255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
43355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
43455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
435ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
43655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
4377d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
438cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                    try {
4397d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        mNwService.setInterfaceUp(mInterface);
4407d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } catch (RemoteException re) {
4417d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        loge("Unable to change interface settings: " + re);
4427d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } catch (IllegalStateException ie) {
4437d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        loge("Unable to change interface settings: " + ie);
44455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
4457d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    mWifiMonitor.startMonitoring();
4467d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    transitionTo(mP2pEnablingState);
44755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
4487d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
4497d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    //Nothing to do
450ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
45155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
45255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
45355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
45455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
45555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
45655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
45755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
45855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnablingState extends State {
45955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
46055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
461ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
46255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
46355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
46455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
46555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
466ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
46755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
46855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_CONNECTION_EVENT:
4697d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (DBG) logd("P2p socket connection successful");
47055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
47155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
472ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
4737d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    loge("P2p socket connection failed");
474aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    transitionTo(mP2pDisabledState);
475ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
4767d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
4777d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
478ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
479ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
48055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
48155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
48255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
48355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
48455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
48555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
48655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
48755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnabledState extends State {
48855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
48955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
490ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
49155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(true);
492aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(true);
49355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff            sendP2pConnectionChangedBroadcast();
4949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff            initializeP2pSettings();
49555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
49655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
49755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
49855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
499ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
50055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
5017d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_ENABLE_P2P:
5027d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    //Nothing to do
503ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
5047d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
505ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
5067d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    mWifiNative.closeSupplicantConnection();
50755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisablingState);
50855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
50955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
5107d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
511ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
512c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                        sendP2pDiscoveryChangedBroadcast(true);
513ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
5144be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
5154be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
516ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
51755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
518c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                case WifiMonitor.P2P_FIND_STOPPED_EVENT:
519c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                    sendP2pDiscoveryChangedBroadcast(false);
520c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                    break;
5217d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiP2pManager.STOP_DISCOVERY:
5227d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    if (mWifiNative.p2pStopFind()) {
5237d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED);
5247d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    } else {
5257d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
5267d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                                WifiP2pManager.ERROR);
5277d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    }
5287d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                    break;
52955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
53055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
531651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                    if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
5324be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    mPeers.update(device);
53355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
53455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
53555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
53655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    device = (WifiP2pDevice) message.obj;
53755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
53855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
5397d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff               default:
54055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
54155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
54255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
54355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
54455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
54555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
54655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void exit() {
54755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(false);
548aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(false);
54955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
55055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
55155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
55255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class InactiveState extends State {
5534be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        @Override
5544be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff        public void enter() {
555ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
5564be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff            //Start listening every time we get inactive
5577d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff            //TODO: Fix listen after driver behavior is fixed
5587d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff            //mWifiNative.p2pListen();
55955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
56055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
56155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
56255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
563ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
56455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
565618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.CONNECT:
566618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd(getName() + " sending connect");
567618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = (WifiP2pConfig) message.obj;
568618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mPersistGroup = false;
569618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    int netId = configuredNetworkId(mSavedPeerConfig.deviceAddress);
570618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (netId >= 0) {
571618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //TODO: if failure, remove config and do a regular p2pConnect()
572fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
573618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
5747d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        //Stop discovery before issuing connect
5757d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                        mWifiNative.p2pStopFind();
576618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //If peer is a GO, we do not need to send provisional discovery,
577618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        //the supplicant takes care of it.
57861472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                        if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
57955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                            if (DBG) logd("Sending join to GO");
580bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
581618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mGroupNegotiationState);
582618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        } else {
58355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                            if (DBG) logd("Sending prov disc");
584618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mProvisionDiscoveryState);
585618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        }
586618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
587618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
588618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    sendP2pPeersChangedBroadcast();
589618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
590618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
59155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
592618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = (WifiP2pConfig) message.obj;
593618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
594618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
595618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
596618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pGroup group = (WifiP2pGroup) message.obj;
597bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    WifiP2pDevice owner = group.getOwner();
598bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
599bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    if (owner == null) {
600bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        if (DBG) loge("Ignored invitation from null owner");
601bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        break;
602bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    }
603bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
604bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
605bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    mSavedPeerConfig.deviceAddress = group.getOwner().deviceAddress;
606bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
607bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //Check if we have the owner in peer list and use appropriate
608bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    //wps method. Default is to use PBC.
609bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    if ((owner = getDeviceFromPeerList(owner.deviceAddress)) != null) {
610bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        if (owner.wpsPbcSupported()) {
611bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.PBC;
612bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        } else if (owner.wpsKeypadSupported()) {
613bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
614bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        } else if (owner.wpsDisplaySupported()) {
615bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                            mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
616bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        }
617bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    }
618618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
619618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
620618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
621618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
622618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
623618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
624618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
625618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
626618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
627618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
628618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Keypad prov disc request");
629618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
630618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
631618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
632618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Display prov disc request");
633618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
634618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.PBC;
635618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("PBC prov disc request");
636618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
637618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingInvitationState);
63855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
63955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
6404be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                    mPersistGroup = true;
641fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pGroupAdd()) {
642ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
643ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
6444be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
6454be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
646ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
64755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
64855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
649618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff               default:
650bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    return NOT_HANDLED;
651bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            }
652bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            return HANDLED;
653bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
654bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff    }
655bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
656618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class GroupCreatingState extends State {
657bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
658bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public void enter() {
659bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName());
660618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT,
661618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    ++mGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS);
662bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
663bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
664bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
665bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public boolean processMessage(Message message) {
666bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName() + message.toString());
667bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            switch (message.what) {
668618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff               case GROUP_CREATING_TIMED_OUT:
669618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mGroupCreatingTimeoutIndex == message.arg1) {
670618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Group negotiation timed out");
67155bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                        handleGroupCreationFailure();
672618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mInactiveState);
673618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
674bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
675618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.DISCOVER_PEERS:
676618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    /* Discovery will break negotiation */
677618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
678618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            WifiP2pManager.BUSY);
679bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
680618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiP2pManager.CANCEL_CONNECT:
68155bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    //Do a supplicant p2p_cancel which only cancels an ongoing
68255bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    //group negotiation. This will fail for a pending provision
68355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    //discovery or for a pending user action, but at the framework
68455bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    //level, we always treat cancel as succeded and enter
68555bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    //an inactive state
68655bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    mWifiNative.p2pCancelConnect();
68755bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    handleGroupCreationFailure();
68855bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    transitionTo(mInactiveState);
68955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED);
69055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
691ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                default:
69255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
69355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
69455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
69555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
69655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
69755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
698618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class UserAuthorizingInvitationState extends State {
699bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
700bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public void enter() {
701bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName());
702618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            notifyInvitationReceived();
703bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
704bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
705bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        @Override
706bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        public boolean processMessage(Message message) {
707bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            if (DBG) logd(getName() + message.toString());
708bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            switch (message.what) {
709618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
710618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    //TODO: handle persistence
71161472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
712bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
713618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
714bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        p2pConnectWithPinDisplay(mSavedPeerConfig, FORM_GROUP);
715618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
716618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
717618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    sendP2pPeersChangedBroadcast();
718618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupNegotiationState);
719618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
720618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
721618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd("User rejected invitation " + mSavedPeerConfig);
722618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
723bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    transitionTo(mInactiveState);
724bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    break;
725bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                default:
726bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    return NOT_HANDLED;
727bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            }
728bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff            return HANDLED;
729bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff        }
730618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
731618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
732618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void exit() {
733618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            //TODO: dismiss dialog if not already done
734618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
735bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff    }
736bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
737618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class ProvisionDiscoveryState extends State {
738618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
739618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void enter() {
740618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName());
741fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff            mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig);
742618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
743618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
744618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
745618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public boolean processMessage(Message message) {
746618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName() + message.toString());
747618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            WifiP2pProvDiscEvent provDisc;
748618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            WifiP2pDevice device;
749618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            switch (message.what) {
750618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:
751618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
752618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
753618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
754618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
755618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
756618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
757fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
758618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mGroupNegotiationState);
759618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
760618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
761618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
762618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
763618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
764618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
765618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
766618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) {
767618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
768618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        /* we already have the pin */
769618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) {
770fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                            mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
771618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mGroupNegotiationState);
772618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        } else {
773618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            transitionTo(mUserAuthorizingInvitationState);
774618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        }
775618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
776618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
777618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
778618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    provDisc = (WifiP2pProvDiscEvent) message.obj;
779618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    device = provDisc.device;
780618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
781618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
782618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) {
783618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        if (DBG) logd("Found a match " + mSavedPeerConfig);
784618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
785fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
786618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        notifyInvitationSent(provDisc.pin, device.deviceAddress);
787618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        transitionTo(mGroupNegotiationState);
788618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
789618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
790618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                default:
791618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    return NOT_HANDLED;
792618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
793618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            return HANDLED;
794618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
795618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
796bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff
79755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupNegotiationState extends State {
798aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        @Override
799aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void enter() {
800ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
80155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
80255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
80355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
80455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
805ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
80655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
80755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // We ignore these right now, since we get a GROUP_STARTED notification
80855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // afterwards
80955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
81055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
811ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go success");
81255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
813618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
814618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mGroup = (WifiP2pGroup) message.obj;
815618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd(getName() + " group started");
816618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mGroup.isGroupOwner()) {
817618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        startDhcpServer(mGroup.getInterface());
818618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
819618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
820618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                P2pStateMachine.this, mGroup.getInterface());
821618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
822618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        WifiP2pDevice groupOwner = mGroup.getOwner();
823618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        updateDeviceStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
824618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
825618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
826618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
827618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
828618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
82955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
83055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
831ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go failure");
83255bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                    handleGroupCreationFailure();
83355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
83455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
83555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
83655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
83755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
83855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
83955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
84055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
84155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
842618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
843618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
84455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupCreatedState extends State {
84555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
84655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
847ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
848aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
849859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
850651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff            updateThisDevice(WifiP2pDevice.CONNECTED);
851651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
852859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            //DHCP server has already been started if I am a group owner
853859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            if (mGroup.isGroupOwner()) {
854859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
855859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                sendP2pConnectionChangedBroadcast();
856859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            }
85755bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff
85855bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff            if (!mPersistGroup) {
85955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
86055bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff            }
86155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
86255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
86355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
86455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
865ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
86655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
86755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_CONNECTED_EVENT:
868bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
869bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    String deviceAddress = device.deviceAddress;
8709322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
8719322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        mGroup.addClient(deviceAddress);
872651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(deviceAddress, WifiP2pDevice.CONNECTED);
8739322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) logd(getName() + " ap sta connected");
8749322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        sendP2pPeersChangedBroadcast();
8759322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
876bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                        loge("Connect on null device address, ignore");
8779322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    }
87855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
87955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
88061472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    device = (WifiP2pDevice) message.obj;
88161472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    deviceAddress = device.deviceAddress;
8829322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
883651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(deviceAddress, WifiP2pDevice.AVAILABLE);
8849322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (mGroup.removeClient(deviceAddress)) {
8859322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Removed client " + deviceAddress);
8864be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            if (!mPersistGroup && mGroup.isClientListEmpty()) {
8874be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                Slog.d(TAG, "Client list empty, remove non-persistent p2p group");
888fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                                mWifiNative.p2pGroupRemove(mGroup.getInterface());
8894be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                            }
8909322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        } else {
8919322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Failed to remove client " + deviceAddress);
8929322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            for (WifiP2pDevice c : mGroup.getClientList()) {
8939322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                                if (DBG) logd("client " + c.deviceAddress);
8949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            }
89555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
8964be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        sendP2pPeersChangedBroadcast();
8979322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) loge(getName() + " ap sta disconnected");
8989322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
89961472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                        loge("Disconnect on unknown device: " + device);
90055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
90155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
902aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                case DhcpStateMachine.CMD_POST_DHCP_ACTION:
903aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
904ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
905ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            dhcpInfo != null) {
906ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
907ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
908aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        sendP2pConnectionChangedBroadcast();
90955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                        //Turn on power save on client
91055bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff                        mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
911ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
91261472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                        loge("DHCP failed");
913fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.p2pGroupRemove(mGroup.getInterface());
914aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
915aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    break;
91655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
917ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " remove group");
918fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
919ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
920ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
9214be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
9224be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
923ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
92455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
92555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
926ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " group removed");
92755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
92855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    boolean changed = false;
92955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
93055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
931651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                            d.status = WifiP2pDevice.AVAILABLE;
93255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            changed = true;
93355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
93455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
935aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
936aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    if (mGroup.isGroupOwner()) {
937aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        stopDhcpServer();
938aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    } else {
939ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("stop DHCP client");
940aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
941aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.quit();
942aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine = null;
943aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
944aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
94555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup = null;
94661472a8314e6716f231ec1c0aba73e005935829bYoshihiko Ikenaga                    mWifiNative.p2pFlush();
94755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (changed) sendP2pPeersChangedBroadcast();
94855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
94955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
95055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
951bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                    device = (WifiP2pDevice) message.obj;
952530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    //Device loss for a connected device indicates it is not in discovery any more
953530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    if (mGroup.contains(device)) {
954530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                        if (DBG) logd("Lost " + device +" , do nothing");
955530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                        return HANDLED;
95655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
957530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    // Do the regular device lost handling
958530040e0b9458994c02f4392765db168128d48daIrfan Sheriff                    return NOT_HANDLED;
9597d6d9c005e5cfad787bb62b7fee6be2d75b13ca3Irfan Sheriff                case WifiStateMachine.CMD_DISABLE_P2P:
96055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.REMOVE_GROUP);
96155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
96255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
96355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
96455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pConfig config = (WifiP2pConfig) message.obj;
965ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("Inviting device : " + config.deviceAddress);
966fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                    if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {
967651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff                        updateDeviceStatus(config.deviceAddress, WifiP2pDevice.INVITED);
968ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        sendP2pPeersChangedBroadcast();
969ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
970ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
9714be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
9724be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff                                WifiP2pManager.ERROR);
973ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
97455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: figure out updating the status to declined when invitation is rejected
97555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
97655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
97755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
978618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
979618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
980618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = new WifiP2pConfig();
981618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
982618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
983618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
984618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
985618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
986618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.pin = provDisc.pin;
987618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
988618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                        mSavedPeerConfig.wps.setup = WpsInfo.PBC;
989618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
990618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mUserAuthorizingJoinState);
99155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
9929322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
9939322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Slog.e(TAG, "Duplicate group creation event notice, ignore");
9949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    break;
99555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
99655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
99755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
99855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
99955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
1000aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1001aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void exit() {
1002651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff            updateThisDevice(WifiP2pDevice.AVAILABLE);
1003ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            setWifiP2pInfoOnGroupTermination();
1004aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
1005ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            sendP2pConnectionChangedBroadcast();
1006aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
100755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
100855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1009618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    class UserAuthorizingJoinState extends State {
1010618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
1011618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void enter() {
1012618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName());
1013618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            notifyInvitationReceived();
1014618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1015618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1016618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
1017618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public boolean processMessage(Message message) {
1018618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (DBG) logd(getName() + message.toString());
1019618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            switch (message.what) {
1020618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
1021618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
1022618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
1023618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    //Ignore more client requests
1024618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1025618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_ACCEPT:
1026618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
102786a5f5b9afa97a4ed6f5a2466fb9359ea131e2fbIrfan Sheriff                        mWifiNative.startWpsPbc(null);
1028618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    } else {
1029fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                        mWifiNative.startWpsPinKeypad(mSavedPeerConfig.wps.pin);
1030618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    }
1031618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
1032618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
1033618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1034618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                case PEER_CONNECTION_USER_REJECT:
1035618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    if (DBG) logd("User rejected incoming request");
1036618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    mSavedPeerConfig = null;
1037618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    transitionTo(mGroupCreatedState);
1038618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    break;
1039618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                default:
1040618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                    return NOT_HANDLED;
1041618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
1042618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            return HANDLED;
1043618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1044618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1045618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        @Override
1046618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        public void exit() {
1047618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            //TODO: dismiss dialog if not already done
1048618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1049618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
1050618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
105155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pStateChangedBroadcast(boolean enabled) {
105255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
105355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
105455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (enabled) {
105555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
105655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_ENABLED);
105755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
105855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
105955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_DISABLED);
106055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
106155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendStickyBroadcast(intent);
106255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
106355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1064c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    private void sendP2pDiscoveryChangedBroadcast(boolean started) {
1065c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        if (mDiscoveryStarted == started) return;
1066c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        mDiscoveryStarted = started;
1067c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
1068c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        if (DBG) logd("discovery change broadcast " + started);
1069c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
1070c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
1071c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1072c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started ?
1073c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED :
1074c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff                WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);
1075c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff        mContext.sendStickyBroadcast(intent);
1076c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff    }
1077c111d1caa8d4cc5d2139b5abd4d2db1f78560effIrfan Sheriff
1078651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void sendThisDeviceChangedBroadcast() {
1079651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
1080651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1081651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice));
1082651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mContext.sendStickyBroadcast(intent);
1083651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1084651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
108555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pPeersChangedBroadcast() {
108655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
108755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
108855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendBroadcast(intent);
108955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
109055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1091aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void sendP2pConnectionChangedBroadcast() {
1092ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (DBG) logd("sending p2p connection changed broadcast");
1093aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
1094aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1095aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
1096ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
1097aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
1098aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mContext.sendStickyBroadcast(intent);
1099aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
1100aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1101aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void startDhcpServer(String intf) {
1102aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        InterfaceConfiguration ifcg = null;
1103aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
1104aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            ifcg = mNwService.getInterfaceConfig(intf);
1105ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
1106ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey                        SERVER_ADDRESS), 24));
1107ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            ifcg.setInterfaceUp();
1108aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.setInterfaceConfig(intf, ifcg);
1109aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            /* This starts the dnsmasq server */
1110859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            mNwService.startTethering(DHCP_RANGE);
1111aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
1112ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error configuring interface " + intf + ", :" + e);
1113aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
1114aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
1115aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1116ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Started Dhcp server on " + intf);
1117859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff   }
1118aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1119aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void stopDhcpServer() {
1120aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
1121aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.stopTethering();
1122aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
1123ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error stopping Dhcp server" + e);
1124aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
1125aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
1126aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1127ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Stopped Dhcp server");
1128aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
1129aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
113055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pEnableFailure() {
113155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
113255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
113355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
113455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_failed_message))
113555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
113655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
113755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
113855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
113955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
114055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1141618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void addRowToDialog(ViewGroup group, int stringId, String value) {
114255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1143618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        View row = LayoutInflater.from(mContext).inflate(R.layout.wifi_p2p_dialog_row,
1144618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                group, false);
1145618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId));
1146618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ((TextView) row.findViewById(R.id.value)).setText(value);
1147618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        group.addView(row);
114855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
114955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1150618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void notifyInvitationSent(String pin, String peerAddress) {
115155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1152aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
115355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
1154618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                .inflate(R.layout.wifi_p2p_dialog, null);
1155618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1156618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
1157618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress));
1158618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin);
115955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
116055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
1161618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title))
116255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
1163618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setPositiveButton(r.getString(R.string.ok), null)
116455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
116555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
116655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
116755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
116855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1169618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private void notifyInvitationReceived() {
117055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
1171618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        final WpsInfo wps = mSavedPeerConfig.wps;
117255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
1173618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                .inflate(R.layout.wifi_p2p_dialog, null);
117455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1175618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
1176618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        addRowToDialog(group, R.string.wifi_p2p_from_message, getDeviceName(
1177618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                mSavedPeerConfig.deviceAddress));
117855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1179618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        final EditText pin = (EditText) textEntryView.findViewById(R.id.wifi_p2p_wps_pin);
118055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
118155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
1182618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title))
118355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
1184618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setPositiveButton(r.getString(R.string.accept), new OnClickListener() {
118555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
1186618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (wps.setup == WpsInfo.KEYPAD) {
1187618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                                mSavedPeerConfig.wps.pin = pin.getText().toString();
1188618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            }
1189618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (DBG) logd(getName() + " accept invitation " + mSavedPeerConfig);
1190618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            sendMessage(PEER_CONNECTION_USER_ACCEPT);
1191bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        }
1192bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                    })
1193618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
1194bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        @Override
1195bbe77ca6be1f6fe5c13c97ccd8baa68ab0272cf5Irfan Sheriff                        public void onClick(DialogInterface dialog, int which) {
1196618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            if (DBG) logd(getName() + " ignore connect");
1197618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                            sendMessage(PEER_CONNECTION_USER_REJECT);
119855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
119955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
120055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
120155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1202618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //make the enter pin area or the display pin area visible
1203618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        switch (wps.setup) {
1204618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            case WpsInfo.KEYPAD:
1205618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                if (DBG) logd("Enter pin section visible");
1206618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE);
1207618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1208618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            case WpsInfo.DISPLAY:
1209618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                if (DBG) logd("Shown pin section visible");
1210618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin);
1211618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1212618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            default:
1213618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                break;
1214618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
121555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
121655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
121755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
121855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
121955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
1220651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void updateDeviceStatus(String deviceAddress, int status) {
122155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
12228c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            if (d.deviceAddress.equals(deviceAddress)) {
122355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                d.status = status;
122455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
122555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
122655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
12278c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync
1228ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //TODO: implement when wpa_supplicant is fixed
1229ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int configuredNetworkId(String deviceAddress) {
1230ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        return -1;
1231ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1232ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1233ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
1234ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = true;
1235ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
1236ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
1237ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1238ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1239ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupTermination() {
1240ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = false;
1241ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = false;
1242ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = null;
1243ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1244ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1245618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    private String getDeviceName(String deviceAddress) {
1246618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1247618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
1248618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff                return d.deviceName;
1249618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff            }
1250618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        }
1251618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //Treat the address as name if there is no match
1252618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        return deviceAddress;
1253618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff    }
1254618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff
1255bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    private WifiP2pDevice getDeviceFromPeerList(String deviceAddress) {
1256bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        for (WifiP2pDevice d : mPeers.getDeviceList()) {
1257bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            if (d.deviceAddress.equals(deviceAddress)) {
1258bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff                return d;
1259bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            }
1260bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        }
1261bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        return null;
1262bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    }
1263bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
1264bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    private void p2pConnectWithPinDisplay(WifiP2pConfig config, boolean join) {
1265fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        String pin = mWifiNative.p2pConnect(config, join);
1266bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        try {
1267bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            Integer.parseInt(pin);
1268bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            notifyInvitationSent(pin, config.deviceAddress);
1269bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        } catch (NumberFormatException ignore) {
1270bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff            // do nothing if p2pConnect did not return a pin
1271bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff        }
1272bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff    }
1273bfed2d6c618e0bf2c271dad1f4acf6d29ebbea51Irfan Sheriff
12749322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private void initializeP2pSettings() {
1275fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setPersistentReconnect(true);
1276fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setDeviceName(mThisDevice.deviceName);
1277530040e0b9458994c02f4392765db168128d48daIrfan Sheriff        //DIRECT-XY-DEVICENAME (XY is randomly generated)
1278fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
1279fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setDeviceType(mThisDevice.primaryDeviceType);
1280618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //The supplicant default is to support everything, but a bug necessitates
1281618455f7e7255019c8cc08a734ba7c52b67a7dc8Irfan Sheriff        //the framework to specify this explicitly
1282fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiNative.setConfigMethods("keypad display push_button");
128355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff        //STA has higher priority over P2P
128455bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff        mWifiNative.setConcurrencyPriority("sta");
12854be4d31f34a0fd0e23de1cbda311c07412f8d0b8Irfan Sheriff
1286fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
1287651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        updateThisDevice(WifiP2pDevice.AVAILABLE);
1288651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        if (DBG) Slog.d(TAG, "DeviceAddress: " + mThisDevice.deviceAddress);
1289651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1290651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
1291651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private void updateThisDevice(int status) {
1292651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mThisDevice.status = status;
1293651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        sendThisDeviceChangedBroadcast();
12949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
12959322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
129655bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff    private void handleGroupCreationFailure() {
129755bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff        mSavedPeerConfig = null;
129855bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff        /* After cancelling group formation, new connections on existing peers can fail
129955bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff         * at supplicant. Flush and restart discovery */
130055bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff        mWifiNative.p2pFlush();
130155bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff        sendMessage(WifiP2pManager.DISCOVER_PEERS);
130255bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff    }
130355bfa42b05868a62ea66d291dcc51f0150fadcc2Irfan Sheriff
1304ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //State machine initiated requests can have replyTo set to null indicating
1305ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //there are no recepients, we ignore those reply actions
1306ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what) {
1307ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1308651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1309651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1310651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1311ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1312ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1313f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff    private void replyToMessage(Message msg, int what, int arg1) {
1314f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff        if (msg.replyTo == null) return;
1315651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1316651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1317651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.arg1 = arg1;
1318651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1319f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff    }
1320f0ef26af3430b9c6402a34eeb9248f805d570922Irfan Sheriff
1321ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what, Object obj) {
1322ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1323651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message dstMsg = obtainMessage(msg);
1324651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.what = what;
1325651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        dstMsg.obj = obj;
1326651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        mReplyChannel.replyToMessage(msg, dstMsg);
1327651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    }
1328651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff
1329651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    /* arg2 on the source message has a hash code that needs to be retained in replies
1330651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff     * see WifiP2pManager for details */
1331651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff    private Message obtainMessage(Message srcMsg) {
1332651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        Message msg = Message.obtain();
1333651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        msg.arg2 = srcMsg.arg2;
1334651cdfcbac6245f570475991588ddc2d30265e8dIrfan Sheriff        return msg;
1335ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1336ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1337ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void logd(String s) {
1338ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.d(TAG, s);
1339ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1340ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1341ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void loge(String s) {
1342ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.e(TAG, s);
1343ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1344ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
134555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
134655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync}
1347