WifiP2pService.java revision f6d09845be2d58b1de7af9f6edc8b9ee216520a5
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;
2855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiManager;
2955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiMonitor;
3055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiNative;
3155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WifiStateMachine;
3255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WpsConfiguration;
3355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.WpsConfiguration.Setup;
3455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.p2p.WifiP2pDevice.Status;
3555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Binder;
3655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.IBinder;
3755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Handler;
3855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.HandlerThread;
3955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.os.Message;
40f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffimport android.os.Messenger;
4155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.util.Slog;
4255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.LayoutInflater;
4355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.View;
4455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.view.WindowManager;
4555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.widget.EditText;
4655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
4755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport java.io.FileDescriptor;
4855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport java.io.PrintWriter;
4955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport java.util.Collection;
5055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
51f6d09845be2d58b1de7af9f6edc8b9ee216520a5Irfan Sheriffimport com.android.internal.R;
5255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.AsyncChannel;
5355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.Protocol;
5455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.State;
5555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport com.android.internal.util.StateMachine;
5655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
5755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync/**
5855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications
5955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * communicate with this service to issue device discovery and connectivity requests
6055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * through the WifiP2pManager interface. The state machine communicates with the wifi
6155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * driver through wpa_supplicant and handles the event responses through WifiMonitor.
6255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync *
6355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * Note that the term Wifi when used without a p2p suffix refers to the client mode
6455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * of Wifi operation
6555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync * @hide
6655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync */
6755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncpublic class WifiP2pService extends IWifiP2pManager.Stub {
6855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final String TAG = "WifiP2pService";
6955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final boolean DBG = true;
7055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
7155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private Context mContext;
7255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
7355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    // Tracked to notify the user about wifi client/hotspot being shut down
7455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    // during p2p bring up
7555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
7655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
7755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
7855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private P2pStateMachine mP2pStateMachine;
7955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private AsyncChannel mReplyChannel = new AsyncChannel();;
8055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private AsyncChannel mWifiChannel;
8155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
8255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
8355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
8455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /* Message sent to WifiStateMachine to indicate p2p enable is pending */
8555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public static final int P2P_ENABLE_PENDING              =   BASE + 1;
8655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
8755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public static final int WIFI_ENABLE_PROCEED             =   BASE + 2;
8855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
8955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /* User accepted to disable Wi-Fi in order to enable p2p */
9055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private static final int WIFI_DISABLE_USER_ACCEPT       =   BASE + 11;
9155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
9255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private final boolean mP2pSupported;
9355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
9455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public WifiP2pService(Context context) {
9555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext = context;
9655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
9755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pSupported = mContext.getResources().getBoolean(
9855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                com.android.internal.R.bool.config_wifi_p2p_support);
9955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
10055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
10155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mP2pStateMachine.start();
10255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
10355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // broadcasts
10455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        IntentFilter filter = new IntentFilter();
10555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
10655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
10755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.registerReceiver(new WifiStateReceiver(), filter);
10855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
10955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync   }
11055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
11155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class WifiStateReceiver extends BroadcastReceiver {
11255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
11355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void onReceive(Context context, Intent intent) {
11455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
11555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
11655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        WifiManager.WIFI_STATE_DISABLED);
11755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else if (intent.getAction().equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
11855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                mWifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
11955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        WifiManager.WIFI_AP_STATE_DISABLED);
12055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
12155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
12255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
12355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
12455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceAccessPermission() {
12555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
12655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
12755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
12855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
12955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void enforceChangePermission() {
13055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
13155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                "WifiP2pService");
13255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
13355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
13455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
13555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Get a reference to handler. This is used by a client to establish
13655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * an AsyncChannel communication with WifiP2pService
13755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
13855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public Messenger getMessenger() {
13955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceAccessPermission();
14055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceChangePermission();
14155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        return new Messenger(mP2pStateMachine.getHandler());
14255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
14355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
14455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
14555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Return if p2p is supported
14655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
14755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    public boolean isP2pSupported() {
14855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        enforceAccessPermission();
14955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        return mP2pSupported;
15055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
15155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
15255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    @Override
15355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
15455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
15555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                != PackageManager.PERMISSION_GRANTED) {
15655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pw.println("Permission Denial: can't dump WifiP2pService from from pid="
15755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + Binder.getCallingPid()
15855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    + ", uid=" + Binder.getCallingUid());
15955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return;
16055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
16155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
16255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
16355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
16455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    /**
16555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     * Handles interaction with WifiStateMachine
16655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync     */
16755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private class P2pStateMachine extends StateMachine {
16855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
16955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private DefaultState mDefaultState = new DefaultState();
17055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
17155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
17255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
17355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
17455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
17555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
17655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Inactive is when p2p is enabled with no connectivity
17755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private InactiveState mInactiveState = new InactiveState();
17855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
17955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
18055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
18155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiMonitor mWifiMonitor = new WifiMonitor(this);
18255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
18355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
18455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mGroup;
18555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
18655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved enable request message so the state machine can send an appropriate response
18755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private Message mSavedEnableRequestMessage;
18855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
18955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pConfig from GO negotiation request
19055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pConfig mSavedGoNegotiationConfig;
19155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
19255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pConfig from connect request
19355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pConfig mSavedConnectConfig;
19455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
19555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        // Saved WifiP2pGroup from invitation request
19655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        private WifiP2pGroup mSavedP2pGroup;
19755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
19855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        P2pStateMachine(String name, boolean p2pSupported) {
19955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            super(name);
20055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
20155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            addState(mDefaultState);
20255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pNotSupportedState, mDefaultState);
20355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisablingState, mDefaultState);
20455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pDisabledState, mDefaultState);
20555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mWaitForWifiDisableState, mDefaultState);
20655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnablingState, mDefaultState);
20755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                addState(mP2pEnabledState, mDefaultState);
20855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mInactiveState, mP2pEnabledState);
20955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupNegotiationState, mP2pEnabledState);
21055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    addState(mGroupCreatedState, mP2pEnabledState);
21155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (p2pSupported) {
21355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pDisabledState);
21455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            } else {
21555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                setInitialState(mP2pNotSupportedState);
21655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
21755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
21855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
21955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    // TODO: Respond to every p2p request with success/failure
22055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class DefaultState extends State {
22155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
22255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
22355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
22455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
22555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
22655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
22755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (DBG) Slog.d(TAG, "Full connection with WifiStateMachine established");
22855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = (AsyncChannel) message.obj;
22955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
23055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Slog.e(TAG, "Full connection failure, error = " + message.arg1);
23155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel = null;
23255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
23355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
23455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
23555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
23655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
23755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Slog.e(TAG, "Send failed, client connection lost");
23855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
23955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Slog.e(TAG, "Client connection lost with reason: " + message.arg1);
24055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
24155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel = null;
24255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
24355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
24455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
24555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    AsyncChannel ac = new AsyncChannel();
24655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    ac.connect(mContext, getHandler(), message.replyTo);
24755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
24855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.WIFI_ENABLE_PENDING:
24955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // Disable p2p operation before we can respond
25055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.DISABLE_P2P);
25155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
25255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
25355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.ENABLE_P2P:
25455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
25555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
25655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
25755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
25855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
25955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.START_LISTEN_MODE:
26055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
26155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
26255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
26355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
26455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
26555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CANCEL_DISCOVER_PEERS:
26655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message,
26755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.CANCEL_DISCOVER_PEERS_FAILED);
26855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
26955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
27055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
27155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
27255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CANCEL_CONNECT:
27355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED);
27455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
27555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REJECT:
27655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.REJECT_FAILED);
27755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
27855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
27955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
28055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
28155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
28255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
28355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
28455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // TODO: fix
28555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_SETTINGS:
28655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_PEERS:
28755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_CONNECTION_STATUS:
28855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
28955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // Ignore
29055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WIFI_DISABLE_USER_ACCEPT:
29155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
29255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
29355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Slog.e(TAG, "Unhandled message " + message);
29455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
29555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
29655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
29755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
29855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
29955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
30055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pNotSupportedState extends State {
30155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
30255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
30355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
30455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // Allow Wi-Fi to proceed
30555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.WIFI_ENABLE_PENDING:
30655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
30755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
30855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.ENABLE_P2P:
30955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
31055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
31155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
31255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
31355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
31455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.P2P_UNSUPPORTED);
31555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
31655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
31755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
31855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
31955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
32055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
32155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
32255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
32355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisablingState extends State {
32455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
32555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
32655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
32755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            // TODO: fix later
32855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            WifiNative.unloadDriver();
32955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            transitionTo(mP2pDisabledState);
33055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
33155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
33255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
33355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
33455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
33555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
33655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_DISCONNECTION_EVENT:
33755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.unloadDriver();
33855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisabledState);
33955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
34055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
34155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
34255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
34355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
34455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
34555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
34655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
34755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
34855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pDisabledState extends State {
34955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync       @Override
35055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
35155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
35255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
35355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
35455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
35555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
35655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
35755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
35855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.ENABLE_P2P:
35955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedEnableRequestMessage = Message.obtain(message);
36055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    OnClickListener listener = new OnClickListener() {
36155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        @Override
36255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
36355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            if (which == DialogInterface.BUTTON_POSITIVE) {
36455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WIFI_DISABLE_USER_ACCEPT);
36555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            } else {
36655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
36755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                        WifiP2pManager.ENABLE_P2P_FAILED);
36855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            }
36955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
37055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    };
37155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
37255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // Show a user request dialog if we know Wi-Fi client/hotspot is in operation
37355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mWifiState != WifiManager.WIFI_STATE_DISABLED ||
37455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED) {
37555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Resources r = Resources.getSystem();
37655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        AlertDialog dialog = new AlertDialog.Builder(mContext)
37755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
37855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setMessage(r.getString(R.string.wifi_p2p_turnon_message))
37955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setPositiveButton(r.getString(R.string.ok), listener)
38055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .setNegativeButton(r.getString(R.string.cancel), listener)
38155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            .create();
38255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
38355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        dialog.show();
38455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
38555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
38655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        transitionTo(mWaitForWifiDisableState);
38755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
38855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
38955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WIFI_DISABLE_USER_ACCEPT:
39055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
39155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mWaitForWifiDisableState);
39255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
39355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.WIFI_ENABLE_PENDING:
39455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
39555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
39655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
39755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
39855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
39955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
40055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
40155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
40255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
40355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class WaitForWifiDisableState extends State {
40455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
40555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
40655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
40755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
40855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
40955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
41055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
41155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
41255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
41355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiStateMachine.P2P_ENABLE_PROCEED:
41455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: fix this for p2p
41555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (WifiNative.loadDriver() &&
41655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiNative.startSupplicant()) {
41755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Slog.d(TAG, "Wi-fi Direct start successful");
41855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mWifiMonitor.startMonitoring();
41955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        transitionTo(mP2pEnablingState);
42055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
42155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        notifyP2pEnableFailure();
42255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
42355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                WifiP2pManager.ENABLE_P2P_FAILED);
42455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        transitionTo(mP2pDisabledState);
42555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
42655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
42755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
42855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
42955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
43055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
43155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
43255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
43355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
43455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnablingState extends State {
43555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
43655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
43755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
43855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
43955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
44055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
44155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
44255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
44355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
44455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUP_CONNECTION_EVENT:
44555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
44655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            WifiP2pManager.ENABLE_P2P_SUCCEEDED);
44755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
44855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
44955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
45055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
45155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
45255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
45355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
45455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
45555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
45655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class P2pEnabledState extends State {
45755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
45855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
45955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
46055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(true);
46155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
46255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
46355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
46455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
46555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
46655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
46755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
46855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: use stopSupplicant after control channel fixed
46955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.killSupplicant();
47055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mP2pDisablingState);
47155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
47255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
47355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    int timeout = message.arg1;
47455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pFlush();
47555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pFind(timeout);
47655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                   break;
47755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REQUEST_PEERS:
47855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mReplyChannel.replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
47955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
48055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
48155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
48255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mPeers.add(device);
48355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
48455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
48555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
48655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    device = (WifiP2pDevice) message.obj;
48755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
48855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
48955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
49055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.d(TAG, getName() + " sending connect");
49155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedConnectConfig = (WifiP2pConfig) message.obj;
49255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    String pin = WifiNative.p2pConnect(mSavedConnectConfig);
49355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    try {
49455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Integer.parseInt(pin);
49555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
49655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } catch (NumberFormatException ignore) {
49755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        // do nothing if p2pConnect did not return a pin
49855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
49955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.INVITED);
50055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
50155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
50255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
50355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REJECT:
50455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.d(TAG, getName() + " sending reject");
50555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pReject((String) message.obj);
50655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
50755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
50855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
50955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
51055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
51155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
51255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
51355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
51455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void exit() {
51555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            sendP2pStateChangedBroadcast(false);
51655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
51755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
51855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
51955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class InactiveState extends State {
52055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override public void enter() {
52155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
52255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
52355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
52455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
52555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
52655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
52755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
52855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
52955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedGoNegotiationConfig = (WifiP2pConfig) message.obj;
53055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig);
53155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
53255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CREATE_GROUP:
53355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pGroupAdd();
53455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupNegotiationState);
53555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
53655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
53755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pGroup group = (WifiP2pGroup) message.obj;
53855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pInvitationReceived(group);
53955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
54055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync               default:
54155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
54255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
54355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
54455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
54555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
54655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
54755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupNegotiationState extends State {
54855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override public void enter() {
54955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
55055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
55155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
55255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
55355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
55455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
55555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
55655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // We ignore these right now, since we get a GROUP_STARTED notification
55755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // afterwards
55855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
55955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
56055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.d(TAG, getName() + " go success");
56155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
56255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
56355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
56455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.d(TAG, getName() + " go failure");
56555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
56655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mSavedConnectConfig = null;
56755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
56855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
56955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
57055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup = (WifiP2pGroup) message.obj;
57155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.d(TAG, getName() + " group started");
57255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // If this device is GO, do nothing since there is a follow up
57355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // AP_STA_CONNECTED event
57455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (!mGroup.isGroupOwner()) {
57555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        WifiP2pDevice groupOwner = mGroup.getOwner();
57655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
57755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        sendP2pPeersChangedBroadcast();
57855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
57955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mGroupCreatedState);
58055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
58155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync               case WifiP2pManager.CANCEL_CONNECT:
58255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: fix
58355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
58455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
58555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
58655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
58755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
58855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
58955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
59055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
59155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    class GroupCreatedState extends State {
59255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
59355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public void enter() {
59455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName());
59555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
59655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
59755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        @Override
59855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        public boolean processMessage(Message message) {
59955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (DBG) Slog.d(TAG, getName() + message.toString());
60055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            switch (message.what) {
60155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_CONNECTED_EVENT:
60255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    String address = (String) message.obj;
60355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup.addClient(address);
60455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(address, Status.CONNECTED);
60555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.d(TAG, getName() + " ap sta connected");
60655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
60755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
60855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
60955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    address = (String) message.obj;
61055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(address, Status.AVAILABLE);
61155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (mGroup.removeClient(address)) {
61255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (DBG) Slog.d(TAG, "Removed client " + address);
61355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (mGroup.isClientListEmpty()) {
61455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            Slog.d(TAG, "Client list empty, killing p2p connection");
61555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            sendMessage(WifiP2pManager.REMOVE_GROUP);
61655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        } else {
61755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            // Just send a notification
61855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            sendP2pPeersChangedBroadcast();
61955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
62055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else {
62155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (DBG) Slog.d(TAG, "Failed to remove client " + address);
62255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        for (WifiP2pDevice c : mGroup.getClientList()) {
62355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            if (DBG) Slog.d(TAG,"client " + c.deviceAddress);
62455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
62555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
62655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.e(TAG, getName() + " ap sta disconnected");
62755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
62855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                // Disconnect & remove group have same effect when connected
62955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CANCEL_CONNECT:
63055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.REMOVE_GROUP:
63155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.e(TAG, getName() + " remove group");
63255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pFlush();
63355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pGroupRemove(mGroup.getInterface());
63455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
63555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
63655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (DBG) Slog.e(TAG, getName() + " group removed");
63755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Collection <WifiP2pDevice> devices = mGroup.getClientList();
63855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    boolean changed = false;
63955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    for (WifiP2pDevice d : mPeers.getDeviceList()) {
64055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (devices.contains(d) || mGroup.getOwner().equals(d)) {
64155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            d.status = Status.AVAILABLE;
64255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                            changed = true;
64355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
64455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
64555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    mGroup = null;
64655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (changed) sendP2pPeersChangedBroadcast();
64755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    transitionTo(mInactiveState);
64855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
64955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
65055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
65155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    if (device.equals(mGroup.getOwner())) {
65255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Slog.d(TAG, "Lost the group owner, killing p2p connection");
65355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        sendMessage(WifiP2pManager.REMOVE_GROUP);
65455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    } else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) {
65555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        Slog.d(TAG, "Client list empty, killing p2p connection");
65655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        sendMessage(WifiP2pManager.REMOVE_GROUP);
65755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
65855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED; // Do the regular device lost handling
65955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISABLE_P2P:
66055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendMessage(WifiP2pManager.REMOVE_GROUP);
66155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    deferMessage(message);
66255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
66355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.DISCOVER_PEERS:
66455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    int timeout = message.arg1;
66555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pFind(timeout);
66655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
66755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.CONNECT:
66855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pConfig config = (WifiP2pConfig) message.obj;
66955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Slog.d(TAG, "Inviting device : " + config.deviceAddress);
67055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pInvite(mGroup, config.deviceAddress);
67155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    updateDeviceStatus(config.deviceAddress, Status.INVITED);
67255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    sendP2pPeersChangedBroadcast();
67355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    // TODO: figure out updating the status to declined when invitation is rejected
67455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
67555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
67655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    Slog.d(TAG,"===> INVITATION RESULT EVENT : " + message.obj);
67755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
67855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
67955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pProvDiscPbcRequest((WifiP2pDevice) message.obj);
68055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
68155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
68255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
68355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
68455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.WPS_PBC:
68555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pWpsPbc();
68655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
68755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiP2pManager.WPS_PIN:
68855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiNative.p2pWpsPin((String) message.obj);
68955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    break;
69055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                default:
69155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    return NOT_HANDLED;
69255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
69355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            return HANDLED;
69455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
69555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
69655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
69755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pStateChangedBroadcast(boolean enabled) {
69855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
69955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
70055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (enabled) {
70155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
70255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_ENABLED);
70355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
70455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
70555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    WifiP2pManager.WIFI_P2P_STATE_DISABLED);
70655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
70755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendStickyBroadcast(intent);
70855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
70955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
71055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void sendP2pPeersChangedBroadcast() {
71155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
71255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
71355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mContext.sendBroadcast(intent);
71455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
71555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
71655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pEnableFailure() {
71755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
71855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
71955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
72055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_failed_message))
72155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
72255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
72355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
72455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
72555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
72655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
72755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyWpsPin(String pin, String peerAddress) {
72855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
72955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
73055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
73155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setMessage(r.getString(R.string.wifi_p2p_pin_display_message, pin, peerAddress))
73255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), null)
73355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
73455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
73555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
73655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
73755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
73855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pGoNegotationRequest(WifiP2pConfig config) {
73955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
74055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        WpsConfiguration wpsConfig = config.wpsConfig;
74155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
74255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
74355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
74455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
74555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
74655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
74755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
74855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
74955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
75055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
75155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedGoNegotiationConfig.wpsConfig.setup = Setup.KEYPAD;
75255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedGoNegotiationConfig.wpsConfig.pin = pin.getText().toString();
75355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
75455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedGoNegotiationConfig = null;
75555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
75655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
75755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {
75855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        @Override
75955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
76055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                if (DBG) Slog.d(TAG, getName() + " reject");
76155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WifiP2pManager.REJECT,
76255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                        mSavedGoNegotiationConfig.deviceAddress);
76355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedGoNegotiationConfig = null;
76455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
76555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
76655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
76755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
76855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        if (wpsConfig.setup == Setup.PBC) {
76955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            pin.setVisibility(View.GONE);
77055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
77155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        config.deviceAddress));
77255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        } else {
77355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message,
77455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        config.deviceAddress));
77555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
77655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
77755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
77855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
77955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
78055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
78155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pProvDiscPbcRequest(WifiP2pDevice peer) {
78255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
78355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
78455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
78555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
78655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
78755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
78855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
78955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
79055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
79155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
79255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                if (DBG) Slog.d(TAG, getName() + " wps_pbc");
79355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WifiP2pManager.WPS_PBC);
79455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
79555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
79655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), null)
79755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
79855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
79955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        pin.setVisibility(View.GONE);
80055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
80155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        peer.deviceAddress));
80255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
80355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
80455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
80555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
80655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
80755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pProvDiscPinRequest(WifiP2pDevice peer) {
80855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
80955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
81055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
81155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
81255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
81355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
81455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
81555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
81655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
81755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    public void onClick(DialogInterface dialog, int which) {
81855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        if (DBG) Slog.d(TAG, getName() + " wps_pin");
81955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        sendMessage(WifiP2pManager.WPS_PIN, pin.getText().toString());
82055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    }
82155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
82255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), null)
82355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
82455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
82555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message,
82655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        peer.deviceAddress));
82755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
82855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
82955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
83055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
83155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
83255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void notifyP2pInvitationReceived(WifiP2pGroup group) {
83355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        mSavedP2pGroup = group;
83455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        Resources r = Resources.getSystem();
83555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final View textEntryView = LayoutInflater.from(mContext)
83655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null);
83755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin);
83855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
83955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        AlertDialog dialog = new AlertDialog.Builder(mContext)
84055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
84155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setView(textEntryView)
84255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
84355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        public void onClick(DialogInterface dialog, int which) {
84455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                WifiP2pConfig config = new WifiP2pConfig();
84555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                config.deviceAddress = mSavedP2pGroup.getOwner().deviceAddress;
84655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                config.joinExistingGroup = true;
84755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                if (DBG) Slog.d(TAG, getName() + " connect to invited group");
84855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                sendMessage(WifiP2pManager.CONNECT, config);
84955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                                mSavedP2pGroup = null;
85055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        }
85155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                    })
85255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .setNegativeButton(r.getString(R.string.cancel), null)
85355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            .create();
85455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
85555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        pin.setVisibility(View.GONE);
85655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message,
85755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                        group.getOwner().deviceAddress));
85855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
85955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
86055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        dialog.show();
86155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
86255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync
86355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    private void updateDeviceStatus(String deviceAddress, Status status) {
86455bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        for (WifiP2pDevice d : mPeers.getDeviceList()) {
86555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync           // TODO: fix later
86655bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync           // if (d.deviceAddress.equals(deviceAddress)) {
86755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            if (d.deviceAddress.startsWith(deviceAddress.substring(0, 8))) {
86855bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                d.status = status;
86955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync            }
87055bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync        }
87155bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
87255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync    }
87355bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync}
874