WifiP2pService.java revision 9322687d98ec425da03cc10ab64ea19ad7fe2d69
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;
2055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.BroadcastReceiver;
2155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.Context;
2255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.DialogInterface;
2355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.DialogInterface.OnClickListener;
2455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.Intent;
2555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.IntentFilter;
2655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.pm.PackageManager;
2755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.content.res.Resources;
28aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.IConnectivityManager;
29aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.ConnectivityManager;
30aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.DhcpInfoInternal;
31aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.DhcpStateMachine;
32aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.InterfaceConfiguration;
33aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.LinkAddress;
34aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.LinkProperties;
35aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.NetworkInfo;
36aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport android.net.NetworkUtils;
3755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiManager;
3855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiMonitor;
3955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiNative;
4055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiStateMachine;
4155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WpsConfiguration;
4255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WpsConfiguration.Setup;
4355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.p2p.WifiP2pDevice.Status;
4455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Binder;
4555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.IBinder;
46cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriffimport android.os.INetworkManagementService;
4755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Handler;
4855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.HandlerThread;
4955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Message;
50f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffimport android.os.Messenger;
51cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriffimport android.os.ServiceManager;
52cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriffimport android.os.SystemProperties;
539322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriffimport android.provider.Settings;
5455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.util.Slog;
5555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.LayoutInflater;
5655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.View;
5755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.WindowManager;
5855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.widget.EditText;
5955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
60f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffimport com.android.internal.R;
6155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.AsyncChannel;
6255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.Protocol;
6355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.State;
6455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.StateMachine;
6555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
66aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport java.io.FileDescriptor;
67aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport java.io.PrintWriter;
68aea743aaa43a833fd8ff3dc56205197583152d5frepo syncimport java.util.Collection;
69aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
7055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync/**
7155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications
7255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * communicate with this service to issue device discovery and connectivity requests
7355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * through the WifiP2pManager interface. The state machine communicates with the wifi
7455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * driver through wpa_supplicant and handles the event responses through WifiMonitor.
7555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *
7655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * Note that the term Wifi when used without a p2p suffix refers to the client mode
7755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * of Wifi operation
7855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * @hide
7955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync */
8055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncpublic class WifiP2pService extends IWifiP2pManager.Stub {
8155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final String TAG = "WifiP2pService";
8255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final boolean DBG = true;
83aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private static final String NETWORKTYPE = "WIFI_P2P";
8455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
8555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private Context mContext;
86cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    private String mInterface;
87cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
88cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    INetworkManagementService mNwService;
89aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private DhcpStateMachine mDhcpStateMachine;
9055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
91aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    //Tracked to notify the user about wifi client/hotspot being shut down
92aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    //during p2p bring up
9355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
9455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
9555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
9655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private P2pStateMachine mP2pStateMachine;
97ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private AsyncChannel mReplyChannel = new AsyncChannel();
9855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private AsyncChannel mWifiChannel;
9955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
100ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /* Two minutes comes from the wpa_supplicant setting */
101ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 120 * 1000;
102aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private static int mGroupNegotiationTimeoutIndex = 0;
103aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
104ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /**
105ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     * Delay between restarts upon failure to setup connection with supplicant
106ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     */
107ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
108ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
109ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    /**
110ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     * Number of times we attempt to restart p2p
111ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff     */
112ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private static final int P2P_RESTART_TRIES = 5;
113ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
114ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int mP2pRestartCount = 0;
115ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
11655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
11755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
11855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /* Message sent to WifiStateMachine to indicate p2p enable is pending */
11955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public static final int P2P_ENABLE_PENDING              =   BASE + 1;
12055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
12155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public static final int WIFI_ENABLE_PROCEED             =   BASE + 2;
12255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
123aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    /* Delayed message to timeout of group negotiation */
124aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    public static final int GROUP_NEGOTIATION_TIMED_OUT     =   BASE + 3;
125aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
12655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /* User accepted to disable Wi-Fi in order to enable p2p */
12755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final int WIFI_DISABLE_USER_ACCEPT       =   BASE + 11;
12855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
12955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private final boolean mP2pSupported;
1309322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private final String mDeviceType;
1319322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private String mDeviceName;
13255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
133aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private NetworkInfo mNetworkInfo;
134aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
135859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    /* Is chosen as a unique range to avoid conflict with
136859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff       the range defined in Tethering.java */
137859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
138859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff    private static final String SERVER_ADDRESS = "192.168.49.1";
139859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
14055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public WifiP2pService(Context context) {
14155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext = context;
14255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
143cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        mInterface = SystemProperties.get("wifi.interface", "wlan0");
144aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
145aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
14655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pSupported = mContext.getResources().getBoolean(
14755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                com.android.internal.R.bool.config_wifi_p2p_support);
1489322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        mDeviceType = mContext.getResources().getString(
1499322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                com.android.internal.R.string.config_wifi_p2p_device_type);
1509322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        mDeviceName = getDefaultDeviceName();
15155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
15255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
15355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine.start();
15455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
15555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // broadcasts
15655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        IntentFilter filter = new IntentFilter();
15755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
15855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
15955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.registerReceiver(new WifiStateReceiver(), filter);
16055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
161aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
16255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
163cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    public void connectivityServiceReady() {
164cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
165cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        mNwService = INetworkManagementService.Stub.asInterface(b);
166cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    }
167cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
16855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class WifiStateReceiver extends BroadcastReceiver {
16955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
17055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void onReceive(Context context, Intent intent) {
17155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
17255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
17355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        WifiManager.WIFI_STATE_DISABLED);
17455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else if (intent.getAction().equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
17555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                mWifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
17655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        WifiManager.WIFI_AP_STATE_DISABLED);
17755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
17855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
17955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
18055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
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    /**
21055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Return if p2p is supported
21155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
21255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public boolean isP2pSupported() {
21355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceAccessPermission();
21455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        return mP2pSupported;
21555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
21655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    @Override
21855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
21955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
22055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                != PackageManager.PERMISSION_GRANTED) {
22155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pw.println("Permission Denial: can't dump WifiP2pService from from pid="
22255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + Binder.getCallingPid()
22355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + ", uid=" + Binder.getCallingUid());
22455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return;
22555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
22655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
22755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
22855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
22955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
23055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Handles interaction with WifiStateMachine
23155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
23255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class P2pStateMachine extends StateMachine {
23355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
23455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private DefaultState mDefaultState = new DefaultState();
23555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
23655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
23755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
238ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        private WaitForUserActionState mWaitForUserActionState = new WaitForUserActionState();
23955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
24055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
24155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
24255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Inactive is when p2p is enabled with no connectivity
24355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private InactiveState mInactiveState = new InactiveState();
24455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
24555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
24655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiMonitor mWifiMonitor = new WifiMonitor(this);
24855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
250ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
25155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mGroup;
25255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pConfig from GO negotiation request
25455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pConfig mSavedGoNegotiationConfig;
25555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pConfig from connect request
25755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pConfig mSavedConnectConfig;
25855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
25955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pGroup from invitation request
26055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mSavedP2pGroup;
26155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
26255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        P2pStateMachine(String name, boolean p2pSupported) {
26355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            super(name);
26455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
26555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            addState(mDefaultState);
26655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pNotSupportedState, mDefaultState);
26755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisablingState, mDefaultState);
26855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisabledState, mDefaultState);
269ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    addState(mWaitForUserActionState, mP2pDisabledState);
270ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    addState(mWaitForWifiDisableState, mP2pDisabledState);
27155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnablingState, mDefaultState);
27255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnabledState, mDefaultState);
27355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mInactiveState, mP2pEnabledState);
27455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupNegotiationState, mP2pEnabledState);
27555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupCreatedState, mP2pEnabledState);
27655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
27755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (p2pSupported) {
27855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pDisabledState);
27955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else {
28055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pNotSupportedState);
28155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
28255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
28355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
28455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class DefaultState extends State {
28555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
28655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
287ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
28855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
28955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
29055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
291ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("Full connection with WifiStateMachine established");
29255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = (AsyncChannel) message.obj;
29355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
294ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Full connection failure, error = " + message.arg1);
29555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = null;
29655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
29755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
29855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
29955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
30055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
301ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Send failed, client connection lost");
30255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
303ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Client connection lost with reason: " + message.arg1);
30455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
30555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel = null;
30655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
30855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
30955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    AsyncChannel ac = new AsyncChannel();
31055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    ac.connect(mContext, getHandler(), message.replyTo);
31155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
31255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.WIFI_ENABLE_PENDING:
31355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // Disable p2p operation before we can respond
31455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.DISABLE_P2P);
31555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
31655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
31755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.ENABLE_P2P:
318ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
31955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
321ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
32255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
324ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
32555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
327ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
32855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
32955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
330ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
33155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
33255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
333ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
33455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
33555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_PEERS:
336ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
337ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
338ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REQUEST_CONNECTION_INFO:
339ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
34055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
34155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // Ignore
34255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WIFI_DISABLE_USER_ACCEPT:
343aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                case GROUP_NEGOTIATION_TIMED_OUT:
34455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
34555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
346ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    loge("Unhandled message " + message);
34755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
34855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
34955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
35055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
35155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
35255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
35355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pNotSupportedState extends State {
35455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
35555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
35655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
35755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // Allow Wi-Fi to proceed
35855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.WIFI_ENABLE_PENDING:
359ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WIFI_ENABLE_PROCEED);
36055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
36155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.ENABLE_P2P:
362ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
36355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
36455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
36555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
366ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
36755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
36855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
369ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.DISCOVER_PEERS:
370ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
371ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
372ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
373ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.CONNECT:
374ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
375ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
376ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
377ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.CREATE_GROUP:
378ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
379ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
380ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
381ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.REMOVE_GROUP:
382ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
383ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            WifiP2pManager.P2P_UNSUPPORTED);
384ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
385ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff               default:
38655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
38755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
38855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
38955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
39055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
39155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
39255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisablingState extends State {
39355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
39455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
395ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
396ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            logd("stopping supplicant");
397ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (!WifiNative.stopSupplicant()) {
398ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                loge("Failed to stop supplicant, issue kill");
399ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                WifiNative.killSupplicant();
400ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            }
40155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
40255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
40355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
40455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
405ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
40655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
40755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_DISCONNECTION_EVENT:
408ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("Supplicant connection lost");
409ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    WifiNative.closeSupplicantConnection();
41055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisabledState);
41155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
412ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.ENABLE_P2P:
413ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.DISABLE_P2P:
414ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
415ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
41655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
41755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
41855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
41955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
42055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
42155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
42255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
42355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
42455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisabledState extends State {
42555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync       @Override
42655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
427ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
42855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
42955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
43055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
43155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
432ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
43355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
43455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.ENABLE_P2P:
43555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    OnClickListener listener = new OnClickListener() {
43655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        @Override
43755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
43855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            if (which == DialogInterface.BUTTON_POSITIVE) {
43955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WIFI_DISABLE_USER_ACCEPT);
44055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            } else {
441ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                                logd("User rejected enabling p2p");
442ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                                //ignore
44355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            }
44455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
44555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    };
44655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
44755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // Show a user request dialog if we know Wi-Fi client/hotspot is in operation
44855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mWifiState != WifiManager.WIFI_STATE_DISABLED ||
44955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED) {
45055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Resources r = Resources.getSystem();
45155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        AlertDialog dialog = new AlertDialog.Builder(mContext)
45255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
45355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setMessage(r.getString(R.string.wifi_p2p_turnon_message))
45455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setPositiveButton(r.getString(R.string.ok), listener)
45555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setNegativeButton(r.getString(R.string.cancel), listener)
45655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .create();
45755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
45855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        dialog.show();
459ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        transitionTo(mWaitForUserActionState);
46055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
46155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
46255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        transitionTo(mWaitForWifiDisableState);
46355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
464ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
46555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
466ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.DISABLE_P2P:
467ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
468ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
469ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiStateMachine.WIFI_ENABLE_PENDING:
470ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WIFI_ENABLE_PROCEED);
471ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
472ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                default:
473ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    return NOT_HANDLED;
474ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            }
475ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            return HANDLED;
476ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        }
477ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
478ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
479ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    class WaitForUserActionState extends State {
480ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        @Override
481ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        public void enter() {
482ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
483ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        }
484ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
485ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        @Override
486ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        public boolean processMessage(Message message) {
487ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
488ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            switch (message.what) {
48955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WIFI_DISABLE_USER_ACCEPT:
49055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
49155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mWaitForWifiDisableState);
49255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
493ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.ENABLE_P2P:
494ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.DISABLE_P2P:
495ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
49655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
49755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
49855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
49955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
50055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
50155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
50255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
50355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
50455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class WaitForWifiDisableState extends State {
50555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
50655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
507ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
50855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
50955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
51055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
51155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
512ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
51355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
51455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.P2P_ENABLE_PROCEED:
515cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                    try {
516cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                        mNwService.wifiFirmwareReload(mInterface, "P2P");
517cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                    } catch (Exception e) {
518ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Failed to reload p2p firmware " + e);
519cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                        // continue
520cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff                    }
521ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
522ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    //A runtime crash can leave the interface up and
523ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    //this affects p2p when supplicant starts up.
524ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    //Ensure interface is down before a supplicant start.
525ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    try {
526ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        mNwService.setInterfaceDown(mInterface);
527ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } catch (Exception e) {
528ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) Slog.w(TAG, "Unable to bring down wlan interface: " + e);
529ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
530ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
531f42c39b3d188ebb3ba9003cffc530717829fe874Irfan Sheriff                    if (WifiNative.startP2pSupplicant()) {
53255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiMonitor.startMonitoring();
53355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        transitionTo(mP2pEnablingState);
53455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
53555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        notifyP2pEnableFailure();
53655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        transitionTo(mP2pDisabledState);
53755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
53855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
539ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.ENABLE_P2P:
540ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.DISABLE_P2P:
541ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
542ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
54355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
54455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
54555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
54655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
54755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
54855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
54955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
55055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnablingState extends State {
55155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
55255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
553ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
55455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
55555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
55655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
55755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
558ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
55955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
56055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_CONNECTION_EVENT:
561ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("P2p start successful");
56255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
56355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
564ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:
565ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (++mP2pRestartCount <= P2P_RESTART_TRIES) {
566ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Failed to start p2p, retry");
567ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        WifiNative.killSupplicant();
568ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
569ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
570ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        loge("Failed " + mP2pRestartCount + " times to start p2p, quit ");
571ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        mP2pRestartCount = 0;
572ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
573aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    transitionTo(mP2pDisabledState);
574ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
575ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.ENABLE_P2P:
576ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.DISABLE_P2P:
577ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    deferMessage(message);
578ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
57955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
58055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
58155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
58255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
58355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
58455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
58555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
58655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnabledState extends State {
58755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
58855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
589ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
59055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(true);
591aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(true);
592ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            //Start listening for new connections
593ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            WifiNative.p2pListen();
5949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff            initializeP2pSettings();
59555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
59655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
59755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
59855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
599ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
60055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
601ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiP2pManager.ENABLE_P2P:
602ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
603ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    break;
60455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
605ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
606ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
60755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisablingState);
60855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
60955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
61055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    int timeout = message.arg1;
611ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (WifiNative.p2pFind(timeout)) {
612ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
613ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
614ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
615ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
61655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
61755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
61855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
61955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mPeers.add(device);
62055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
62155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
62255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
62355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    device = (WifiP2pDevice) message.obj;
62455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
62555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
62655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
627ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " sending connect");
62855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedConnectConfig = (WifiP2pConfig) message.obj;
629ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    int netId = configuredNetworkId(mSavedConnectConfig.deviceAddress);
630ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (netId >= 0) {
631ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        //TODO: if failure, remove config and do a regular p2pConnect()
632ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        WifiNative.p2pReinvoke(netId, mSavedConnectConfig.deviceAddress);
633ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
634ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        //TODO: Check if device is a GO and "join"
635ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        String pin = WifiNative.p2pConnect(mSavedConnectConfig, false);
636ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        try {
637ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            Integer.parseInt(pin);
638ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
639ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        } catch (NumberFormatException ignore) {
640ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            // do nothing if p2pConnect did not return a pin
641ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        }
64255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
64355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.INVITED);
64455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
645ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
64655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
64755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
648ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant died */
649ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    loge("Connection lost, restart p2p");
650ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    WifiNative.killSupplicant();
651ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    WifiNative.closeSupplicantConnection();
652ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
653ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    transitionTo(mP2pDisabledState);
654ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
6559322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    break;
6569322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
6579322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    mGroup = (WifiP2pGroup) message.obj;
6589322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (DBG) logd(getName() + " group started");
6599322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (mGroup.isGroupOwner()) {
6609322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        startDhcpServer(mGroup.getInterface());
6619322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
6629322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
6639322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                                P2pStateMachine.this, mGroup.getInterface());
6649322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
6659322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        WifiP2pDevice groupOwner = mGroup.getOwner();
6669322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
6679322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        sendP2pPeersChangedBroadcast();
6689322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    }
6699322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    transitionTo(mGroupCreatedState);
6709322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    break;
67155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
67255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
67355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
67455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
67555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
67655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
67755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
67855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void exit() {
67955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(false);
680aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setIsAvailable(false);
68155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
68255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
68355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
68455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class InactiveState extends State {
68555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override public void enter() {
686ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
68755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
68855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
68955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
69055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
691ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
69255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
69355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
69455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedGoNegotiationConfig = (WifiP2pConfig) message.obj;
69555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig);
69655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
69755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
698ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (WifiNative.p2pGroupAdd()) {
699ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
700ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
701ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
702ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
70355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
70455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
70555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
70655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pGroup group = (WifiP2pGroup) message.obj;
70755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pInvitationReceived(group);
70855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
709ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                default:
71055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
71155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
71255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
71355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
71455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
71555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
71655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupNegotiationState extends State {
717aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        @Override
718aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void enter() {
719ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
720aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            sendMessageDelayed(obtainMessage(GROUP_NEGOTIATION_TIMED_OUT,
721aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    ++mGroupNegotiationTimeoutIndex, 0), GROUP_NEGOTIATION_WAIT_TIME_MS);
72255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
72355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
72455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
72555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
726ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
72755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
72855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // We ignore these right now, since we get a GROUP_STARTED notification
72955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // afterwards
73055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
73155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
732ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go success");
73355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
73455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
73555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
736ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) logd(getName() + " go failure");
73755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
73855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedConnectConfig = null;
739ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    sendP2pPeersChangedBroadcast();
74055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
74155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
742aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                case GROUP_NEGOTIATION_TIMED_OUT:
743aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    if (mGroupNegotiationTimeoutIndex == message.arg1) {
744ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("Group negotiation timed out");
745aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
746aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mSavedConnectConfig = null;
747ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        sendP2pPeersChangedBroadcast();
748aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        transitionTo(mInactiveState);
749aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
750aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    break;
75155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
75255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
75355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
75455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
75555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
75655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
75755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
75855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupCreatedState extends State {
75955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
76055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
761ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName());
762aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
763859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff
764859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            //DHCP server has already been started if I am a group owner
765859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            if (mGroup.isGroupOwner()) {
766859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
767859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                sendP2pConnectionChangedBroadcast();
768859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            }
76955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
77055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
77155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
77255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
773ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            if (DBG) logd(getName() + message.toString());
77455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
77555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_CONNECTED_EVENT:
7768c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                    //After a GO setup, STA connected event comes with interface address
7778c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                    String interfaceAddress = (String) message.obj;
7788c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                    String deviceAddress = getDeviceAddress(interfaceAddress);
7799322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
7809322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        mGroup.addClient(deviceAddress);
7819322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        updateDeviceStatus(deviceAddress, Status.CONNECTED);
7829322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) logd(getName() + " ap sta connected");
7839322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        sendP2pPeersChangedBroadcast();
7849322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
7859322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        loge("Connect on unknown device address : " + interfaceAddress);
7869322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    }
78755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
78855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
7898c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                    interfaceAddress = (String) message.obj;
7908c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                    deviceAddress = getDeviceAddress(interfaceAddress);
7919322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    if (deviceAddress != null) {
7929322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        updateDeviceStatus(deviceAddress, Status.AVAILABLE);
7939322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (mGroup.removeClient(deviceAddress)) {
7949322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Removed client " + deviceAddress);
7959322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            sendP2pPeersChangedBroadcast();
7969322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        } else {
7979322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            if (DBG) logd("Failed to remove client " + deviceAddress);
7989322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            for (WifiP2pDevice c : mGroup.getClientList()) {
7999322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                                if (DBG) logd("client " + c.deviceAddress);
8009322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                            }
80155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
8029322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        if (DBG) loge(getName() + " ap sta disconnected");
8039322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    } else {
8049322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                        loge("Disconnect on unknown device address : " + interfaceAddress);
80555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
80655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
807aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                case DhcpStateMachine.CMD_POST_DHCP_ACTION:
808aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
809ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
810ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            dhcpInfo != null) {
811ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
812ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
813aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        sendP2pConnectionChangedBroadcast();
814ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
815ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        WifiNative.p2pGroupRemove(mGroup.getInterface());
816aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
817aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    break;
81855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
819ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " remove group");
820ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (WifiNative.p2pGroupRemove(mGroup.getInterface())) {
821ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
822ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
823ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
824ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
82555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
82655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
827ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (DBG) loge(getName() + " group removed");
82855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
82955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    boolean changed = false;
83055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
83155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
83255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            d.status = Status.AVAILABLE;
83355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            changed = true;
83455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
83555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
836aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
837aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    if (mGroup.isGroupOwner()) {
838aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        stopDhcpServer();
839aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    } else {
840ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd("stop DHCP client");
841aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
842aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine.quit();
843aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        mDhcpStateMachine = null;
844aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                    }
845aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
84655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup = null;
84755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (changed) sendP2pPeersChangedBroadcast();
84855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
84955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
85055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
85155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
85255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (device.equals(mGroup.getOwner())) {
853ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        logd("Lost the group owner, killing p2p connection");
854aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                        WifiNative.p2pGroupRemove(mGroup.getInterface());
855ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
856ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        mGroup.removeClient(device);
85755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
85855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED; // Do the regular device lost handling
85955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
86055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.REMOVE_GROUP);
86155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
86255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
86355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
86455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pConfig config = (WifiP2pConfig) message.obj;
865ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("Inviting device : " + config.deviceAddress);
866ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    if (WifiNative.p2pInvite(mGroup, config.deviceAddress)) {
867ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        updateDeviceStatus(config.deviceAddress, Status.INVITED);
868ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        sendP2pPeersChangedBroadcast();
869ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
870ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    } else {
871ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
872ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    }
87355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: figure out updating the status to declined when invitation is rejected
87455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
87555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
876ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                    logd("===> INVITATION RESULT EVENT : " + message.obj);
87755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
87855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
87955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pProvDiscPbcRequest((WifiP2pDevice) message.obj);
88055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
88155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
88255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
88355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
8849322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
8859322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    Slog.e(TAG, "Duplicate group creation event notice, ignore");
8869322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff                    break;
88755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.WPS_PBC:
8882b8edd0c485f74067605c19983e3e7f44b20ec50repo sync                    WifiNative.wpsPbc();
88955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
89055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.WPS_PIN:
8912b8edd0c485f74067605c19983e3e7f44b20ec50repo sync                    WifiNative.wpsPin((String) message.obj);
89255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
89355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
89455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
89555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
89655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
89755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
898aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
899aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        public void exit() {
900ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            setWifiP2pInfoOnGroupTermination();
901aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
902ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            sendP2pConnectionChangedBroadcast();
903aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
90455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
90555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
90655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pStateChangedBroadcast(boolean enabled) {
90755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
90855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
90955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (enabled) {
91055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
91155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_ENABLED);
91255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
91355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
91455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_DISABLED);
91555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
91655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendStickyBroadcast(intent);
91755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
91855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
91955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pPeersChangedBroadcast() {
92055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
92155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
92255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendBroadcast(intent);
92355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
92455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
925aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void sendP2pConnectionChangedBroadcast() {
926ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (DBG) logd("sending p2p connection changed broadcast");
927aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
928aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
929aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
930ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
931aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
932aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        mContext.sendStickyBroadcast(intent);
933aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
934aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
935aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void startDhcpServer(String intf) {
936aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        InterfaceConfiguration ifcg = null;
937aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
938aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            ifcg = mNwService.getInterfaceConfig(intf);
939aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
940859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff                        SERVER_ADDRESS), 24);
941aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            ifcg.interfaceFlags = "[up]";
942aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.setInterfaceConfig(intf, ifcg);
943aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            /* This starts the dnsmasq server */
944859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff            mNwService.startTethering(DHCP_RANGE);
945aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
946ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error configuring interface " + intf + ", :" + e);
947aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
948aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
949aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
950ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Started Dhcp server on " + intf);
951859e7de2359420dcc5275bdce588b96dcc9203f0Irfan Sheriff   }
952aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
953aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    private void stopDhcpServer() {
954aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        try {
955aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            mNwService.stopTethering();
956aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        } catch (Exception e) {
957ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff            loge("Error stopping Dhcp server" + e);
958aea743aaa43a833fd8ff3dc56205197583152d5frepo sync            return;
959aea743aaa43a833fd8ff3dc56205197583152d5frepo sync        }
960aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
961ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        logd("Stopped Dhcp server");
962aea743aaa43a833fd8ff3dc56205197583152d5frepo sync    }
963aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
96455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pEnableFailure() {
96555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
96655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
96755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
96855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_failed_message))
96955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
97055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
97155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
97255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
97355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
97455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
97555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyWpsPin(String pin, String peerAddress) {
97655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
97755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
97855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
97955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_pin_display_message, pin, peerAddress))
98055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
98155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
98255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
98355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
98455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
98555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
98655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pGoNegotationRequest(WifiP2pConfig config) {
98755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
98855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        WpsConfiguration wpsConfig = config.wpsConfig;
98955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
99055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
99155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
99255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
99355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
99455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
99555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
99655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
99755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
998ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            if (DBG) logd(getName() + " connect " + pin.getText());
999aea743aaa43a833fd8ff3dc56205197583152d5frepo sync
1000aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                            if (pin.getVisibility() == View.GONE) {
1001aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                                mSavedGoNegotiationConfig.wpsConfig.setup = Setup.PBC;
1002aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                            } else {
100355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedGoNegotiationConfig.wpsConfig.setup = Setup.KEYPAD;
100455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedGoNegotiationConfig.wpsConfig.pin = pin.getText().toString();
1005aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                            }
1006aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                            sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
1007aea743aaa43a833fd8ff3dc56205197583152d5frepo sync                            mSavedGoNegotiationConfig = null;
100855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
100955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
101055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {
101155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        @Override
101255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
1013ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            if (DBG) logd(getName() + " ignore connect");
1014ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                            mSavedGoNegotiationConfig = null;
101555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
101655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
101755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
101855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
101955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (wpsConfig.setup == Setup.PBC) {
102055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pin.setVisibility(View.GONE);
102155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
102255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        config.deviceAddress));
102355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
102455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message,
102555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        config.deviceAddress));
102655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
102755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
102855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
102955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
103055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
103155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
103255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pProvDiscPbcRequest(WifiP2pDevice peer) {
103355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
103455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
103555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
103655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
103755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
103855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
103955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
104055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
104155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
104255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
1043ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                                if (DBG) logd(getName() + " wps_pbc");
104455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WifiP2pManager.WPS_PBC);
104555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
104655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
104755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), null)
104855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
104955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
105055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        pin.setVisibility(View.GONE);
105155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
105255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        peer.deviceAddress));
105355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
105455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
105555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
105655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
105755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
105855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pProvDiscPinRequest(WifiP2pDevice peer) {
105955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
106055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
106155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
106255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
106355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
106455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
106555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
106655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
106755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
106855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    public void onClick(DialogInterface dialog, int which) {
1069ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                        if (DBG) logd(getName() + " wps_pin");
107055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        sendMessage(WifiP2pManager.WPS_PIN, pin.getText().toString());
107155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
107255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
107355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), null)
107455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
107555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
107655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message,
107755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        peer.deviceAddress));
107855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
107955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
108055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
108155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
108255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
108355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pInvitationReceived(WifiP2pGroup group) {
108455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mSavedP2pGroup = group;
108555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
108655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
108755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
108855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
108955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
109055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
109155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
109255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
109355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
109455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
109555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                WifiP2pConfig config = new WifiP2pConfig();
109655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                config.deviceAddress = mSavedP2pGroup.getOwner().deviceAddress;
1097ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff                                if (DBG) logd(getName() + " connect to invited group");
109855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WifiP2pManager.CONNECT, config);
109955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedP2pGroup = null;
110055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
110155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
110255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), null)
110355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
110455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
110555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        pin.setVisibility(View.GONE);
110655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
110755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        group.getOwner().deviceAddress));
110855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
110955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
111055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
111155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
111255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
111355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void updateDeviceStatus(String deviceAddress, Status status) {
111455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
11158c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            if (d.deviceAddress.equals(deviceAddress)) {
111655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                d.status = status;
111755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
111855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
111955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
11208c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync
1121ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //TODO: implement when wpa_supplicant is fixed
1122ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private int configuredNetworkId(String deviceAddress) {
1123ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        return -1;
1124ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1125ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1126ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
1127ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = true;
1128ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
1129ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
1130ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1131ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1132ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void setWifiP2pInfoOnGroupTermination() {
1133ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupFormed = false;
1134ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.isGroupOwner = false;
1135ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mWifiP2pInfo.groupOwnerAddress = null;
1136ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1137ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
11388c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync    private String getDeviceAddress(String interfaceAddress) {
11398c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
11408c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            if (interfaceAddress.equals(WifiNative.p2pGetInterfaceAddress(d.deviceAddress))) {
11418c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync                return d.deviceAddress;
11428c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync            }
11438c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync        }
11448c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync        return null;
11458c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync    }
11468c57bcdbc6b360ee27d59b957a53e64c03257c9drepo sync
11479322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    private void initializeP2pSettings() {
11489322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        WifiNative.setPersistentReconnect(true);
11499322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        WifiNative.setDeviceName(mDeviceName);
11509322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff        WifiNative.setDeviceType(mDeviceType);
11519322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff    }
11529322687d98ec425da03cc10ab64ea19ad7fe2d69Irfan Sheriff
1153ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //State machine initiated requests can have replyTo set to null indicating
1154ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    //there are no recepients, we ignore those reply actions
1155ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what) {
1156ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1157ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mReplyChannel.replyToMessage(msg, what);
1158ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1159ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1160ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void replyToMessage(Message msg, int what, Object obj) {
1161ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        if (msg.replyTo == null) return;
1162ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        mReplyChannel.replyToMessage(msg, what, obj);
1163ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1164ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1165ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void logd(String s) {
1166ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.d(TAG, s);
1167ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1168ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
1169ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    private void loge(String s) {
1170ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff        Slog.e(TAG, s);
1171ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff    }
1172ea5b16ac5751022de73e8f1225407eb01e7f1824Irfan Sheriff
117355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
117455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync}
1175