Merge "DO NOT MERGE Action bar config changes" into honeycomb-mr2
diff --git a/api/current.xml b/api/current.xml
index a906d24..393e542 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -31483,6 +31483,25 @@
 <parameter name="exit" type="int">
 </parameter>
 </method>
+<method name="setCustomAnimations"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enter" type="int">
+</parameter>
+<parameter name="exit" type="int">
+</parameter>
+<parameter name="popEnter" type="int">
+</parameter>
+<parameter name="popExit" type="int">
+</parameter>
+</method>
 <method name="setTransition"
  return="android.app.FragmentTransaction"
  abstract="true"
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 09e3d76..e5a7980 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -43,7 +43,7 @@
             if (op.removed != null) numRemoved += op.removed.size();
             op = op.next;
         }
-        mOps = new int[bse.mNumOp*5 + numRemoved];
+        mOps = new int[bse.mNumOp*7 + numRemoved];
 
         if (!bse.mAddToBackStack) {
             throw new IllegalStateException("Not on back stack");
@@ -56,6 +56,8 @@
             mOps[pos++] = op.fragment.mIndex;
             mOps[pos++] = op.enterAnim;
             mOps[pos++] = op.exitAnim;
+            mOps[pos++] = op.popEnterAnim;
+            mOps[pos++] = op.popExitAnim;
             if (op.removed != null) {
                 final int N = op.removed.size();
                 mOps[pos++] = N;
@@ -101,6 +103,8 @@
             op.fragment = f;
             op.enterAnim = mOps[pos++];
             op.exitAnim = mOps[pos++];
+            op.popEnterAnim = mOps[pos++];
+            op.popExitAnim = mOps[pos++];
             final int N = mOps[pos++];
             if (N > 0) {
                 op.removed = new ArrayList<Fragment>(N);
@@ -179,6 +183,8 @@
         Fragment fragment;
         int enterAnim;
         int exitAnim;
+        int popEnterAnim;
+        int popExitAnim;
         ArrayList<Fragment> removed;
     }
 
@@ -187,6 +193,8 @@
     int mNumOp;
     int mEnterAnim;
     int mExitAnim;
+    int mPopEnterAnim;
+    int mPopExitAnim;
     int mTransition;
     int mTransitionStyle;
     boolean mAddToBackStack;
@@ -243,6 +251,11 @@
                     writer.print(prefix); writer.print("enterAnim="); writer.print(op.enterAnim);
                             writer.print(" exitAnim="); writer.println(op.exitAnim);
                 }
+                if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
+                    writer.print(prefix);
+                            writer.print("popEnterAnim="); writer.print(op.popEnterAnim);
+                            writer.print(" popExitAnim="); writer.println(op.popExitAnim);
+                }
                 if (op.removed != null && op.removed.size() > 0) {
                     for (int i=0; i<op.removed.size(); i++) {
                         writer.print(innerPrefix);
@@ -301,6 +314,8 @@
         }
         op.enterAnim = mEnterAnim;
         op.exitAnim = mExitAnim;
+        op.popEnterAnim = mPopEnterAnim;
+        op.popExitAnim = mPopExitAnim;
         mNumOp++;
     }
 
@@ -430,8 +445,15 @@
     }
 
     public FragmentTransaction setCustomAnimations(int enter, int exit) {
+        return setCustomAnimations(enter, exit, 0, 0);
+    }
+
+    public FragmentTransaction setCustomAnimations(int enter, int exit,
+            int popEnter, int popExit) {
         mEnterAnim = enter;
         mExitAnim = exit;
+        mPopEnterAnim = popEnter;
+        mPopExitAnim = popExit;
         return this;
     }
 
@@ -631,6 +653,7 @@
             switch (op.cmd) {
                 case OP_ADD: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popExitAnim;
                     f.mImmediateActivity = null;
                     mManager.removeFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition),
@@ -638,6 +661,7 @@
                 } break;
                 case OP_REPLACE: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popExitAnim;
                     f.mImmediateActivity = null;
                     mManager.removeFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition),
@@ -645,6 +669,7 @@
                     if (op.removed != null) {
                         for (int i=0; i<op.removed.size(); i++) {
                             Fragment old = op.removed.get(i);
+                            old.mNextAnim = op.popEnterAnim;
                             f.mImmediateActivity = mManager.mActivity;
                             mManager.addFragment(old, false);
                         }
@@ -652,16 +677,19 @@
                 } break;
                 case OP_REMOVE: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popEnterAnim;
                     f.mImmediateActivity = mManager.mActivity;
                     mManager.addFragment(f, false);
                 } break;
                 case OP_HIDE: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popEnterAnim;
                     mManager.showFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
                 } break;
                 case OP_SHOW: {
                     Fragment f = op.fragment;
+                    f.mNextAnim = op.popExitAnim;
                     mManager.hideFragment(f,
                             FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
                 } break;
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 15b873b..c1f3cd6 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -141,10 +141,20 @@
 
     /**
      * Set specific animation resources to run for the fragments that are
-     * entering and exiting in this transaction.
+     * entering and exiting in this transaction. These animations will not be
+     * played when popping the back stack.
      */
     public abstract FragmentTransaction setCustomAnimations(int enter, int exit);
-    
+
+    /**
+     * Set specific animation resources to run for the fragments that are
+     * entering and exiting in this transaction. The <code>popEnter</code>
+     * and <code>popExit</code> animations will be played for enter/exit
+     * operations specifically when popping the back stack.
+     */
+    public abstract FragmentTransaction setCustomAnimations(int enter, int exit,
+            int popEnter, int popExit);
+
     /**
      * Select a standard transition animation for this transaction.  May be
      * one of {@link #TRANSIT_NONE}, {@link #TRANSIT_FRAGMENT_OPEN},
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 0000237..6acc32f 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -559,31 +559,10 @@
      * @param wifiConfig SSID, security and channel details as
      *        part of WifiConfiguration
      * @param enabled true to enable and false to disable
-     * @return {@code true} if the start operation was
-     *         started or is already in the queue.
      */
-    public synchronized boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
+    public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         enforceChangePermission();
-
-        if (enabled) {
-            /* Use default config if there is no existing config */
-            if (wifiConfig == null && ((wifiConfig = getWifiApConfiguration()) == null)) {
-                wifiConfig = new WifiConfiguration();
-                wifiConfig.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
-                wifiConfig.allowedKeyManagement.set(KeyMgmt.NONE);
-            }
-            /*
-             * Caller might not have WRITE_SECURE_SETTINGS,
-             * only CHANGE_WIFI_STATE is enforced
-             */
-            long ident = Binder.clearCallingIdentity();
-            setWifiApConfiguration(wifiConfig);
-            Binder.restoreCallingIdentity(ident);
-        }
-
         mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);
-
-        return true;
     }
 
     /**
@@ -603,38 +582,20 @@
      * see {@link WifiManager#getWifiApConfiguration()}
      * @return soft access point configuration
      */
-    public synchronized WifiConfiguration getWifiApConfiguration() {
-        final ContentResolver cr = mContext.getContentResolver();
-        WifiConfiguration wifiConfig = new WifiConfiguration();
-        int authType;
-        try {
-            wifiConfig.SSID = Settings.Secure.getString(cr, Settings.Secure.WIFI_AP_SSID);
-            if (wifiConfig.SSID == null)
-                return null;
-            authType = Settings.Secure.getInt(cr, Settings.Secure.WIFI_AP_SECURITY);
-            wifiConfig.allowedKeyManagement.set(authType);
-            wifiConfig.preSharedKey = Settings.Secure.getString(cr, Settings.Secure.WIFI_AP_PASSWD);
-            return wifiConfig;
-        } catch (Settings.SettingNotFoundException e) {
-            Slog.e(TAG,"AP settings not found, returning");
-            return null;
-        }
+    public WifiConfiguration getWifiApConfiguration() {
+        enforceAccessPermission();
+        return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel);
     }
 
     /**
      * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)}
      * @param wifiConfig WifiConfiguration details for soft access point
      */
-    public synchronized void setWifiApConfiguration(WifiConfiguration wifiConfig) {
+    public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
         enforceChangePermission();
-        final ContentResolver cr = mContext.getContentResolver();
         if (wifiConfig == null)
             return;
-        int authType = wifiConfig.getAuthType();
-        Settings.Secure.putString(cr, Settings.Secure.WIFI_AP_SSID, wifiConfig.SSID);
-        Settings.Secure.putInt(cr, Settings.Secure.WIFI_AP_SECURITY, authType);
-        if (authType != KeyMgmt.NONE)
-            Settings.Secure.putString(cr, Settings.Secure.WIFI_AP_PASSWD, wifiConfig.preSharedKey);
+        mWifiStateMachine.setWifiApConfiguration(wifiConfig);
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 16a61db..0757efd 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -87,7 +87,7 @@
 
     void releaseMulticastLock();
 
-    boolean setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
+    void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
 
     int getWifiApEnabledState();
 
diff --git a/wifi/java/android/net/wifi/WifiApConfigStore.java b/wifi/java/android/net/wifi/WifiApConfigStore.java
new file mode 100644
index 0000000..bb5427d
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiApConfigStore.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.Environment;
+import android.os.Message;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.UUID;
+
+import com.android.internal.R;
+
+
+/**
+ * Provides API to the WifiStateMachine for doing read/write access
+ * to soft access point configuration
+ */
+class WifiApConfigStore {
+
+    private static Context sContext;
+    private static final String TAG = "WifiApConfigStore";
+
+    private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
+        "/misc/wifi/softap.conf";
+
+    private static final int AP_CONFIG_FILE_VERSION = 1;
+
+    private static WifiConfiguration sApConfig = new WifiConfiguration();
+    private static final Object sApConfigLock = new Object();
+
+    private static FileReadWriteHandler sFileReadWriteHandler;
+    private static final int READ_AP_CONFIG               = 1;
+    private static final int WRITE_AP_CONFIG              = 2;
+
+    static void initialize(Context context) {
+        sContext = context;
+
+        /* File operations happen on a seperate thread */
+        HandlerThread configThread = new HandlerThread("WifiApConfigStore");
+        configThread.start();
+        sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper());
+        Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget();
+    }
+
+
+    static void setApConfiguration(WifiConfiguration config) {
+        synchronized (sApConfigLock) {
+            sApConfig = config;
+        }
+        Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config))
+            .sendToTarget();
+    }
+
+    static WifiConfiguration getApConfiguration() {
+        synchronized (sApConfigLock) {
+            return new WifiConfiguration(sApConfig);
+        }
+    }
+
+    /**
+     * File read/write handler
+     */
+    private static class FileReadWriteHandler extends Handler {
+
+        public FileReadWriteHandler(android.os.Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case WRITE_AP_CONFIG:
+                    writeApConfiguration((WifiConfiguration) msg.obj);
+                    break;
+                case READ_AP_CONFIG:
+                    readApConfiguration();
+                    break;
+                default:
+                    Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg);
+                    break;
+            }
+        }
+
+        private static void writeApConfiguration(final WifiConfiguration config) {
+            DataOutputStream out = null;
+            try {
+                out = new DataOutputStream(new BufferedOutputStream(
+                            new FileOutputStream(AP_CONFIG_FILE)));
+
+                out.writeInt(AP_CONFIG_FILE_VERSION);
+                out.writeUTF(config.SSID);
+                int authType = config.getAuthType();
+                out.writeInt(authType);
+                if(authType != KeyMgmt.NONE) {
+                    out.writeUTF(config.preSharedKey);
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "Error writing hotspot configuration" + e);
+            } finally {
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException e) {}
+                }
+            }
+        }
+
+        private static void readApConfiguration() {
+            DataInputStream in = null;
+            try {
+                WifiConfiguration config = new WifiConfiguration();
+                in = new DataInputStream(new BufferedInputStream(new FileInputStream(
+                                AP_CONFIG_FILE)));
+
+                int version = in.readInt();
+                if (version != 1) {
+                    Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
+                    setDefaultApConfiguration();
+                    return;
+                }
+                config.SSID = in.readUTF();
+                int authType = in.readInt();
+                config.allowedKeyManagement.set(authType);
+                if (authType != KeyMgmt.NONE) {
+                    config.preSharedKey = in.readUTF();
+                }
+                synchronized (sApConfigLock) {
+                    sApConfig = config;
+                }
+            } catch (IOException ignore) {
+                setDefaultApConfiguration();
+            } finally {
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException e) {}
+                }
+            }
+        }
+
+        /* Generate a default WPA2 based configuration with a random password.
+           We are changing the Wifi Ap configuration storage from secure settings to a
+           flat file accessible only by the system. A WPA2 based default configuration
+           will keep the device secure after the update */
+        private static void setDefaultApConfiguration() {
+            WifiConfiguration config = new WifiConfiguration();
+            config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default);
+            config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+            String randomUUID = UUID.randomUUID().toString();
+            //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+            config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
+            setApConfiguration(config);
+        }
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 2e49a77..949e80f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -898,7 +898,8 @@
      */
     public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         try {
-            return mService.setWifiApEnabled(wifiConfig, enabled);
+            mService.setWifiApEnabled(wifiConfig, enabled);
+            return true;
         } catch (RemoteException e) {
             return false;
         }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index a87ee9a..0c0e2534 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -200,8 +200,12 @@
     static final int CMD_START_AP                         = BASE + 21;
     /* Stop the soft access point */
     static final int CMD_STOP_AP                          = BASE + 22;
+    /* Set the soft access point configuration */
+    static final int CMD_SET_AP_CONFIG                    = BASE + 23;
+    /* Get the soft access point configuration */
+    static final int CMD_GET_AP_CONFIG                    = BASE + 24;
 
-    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 23;
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 25;
 
     /* Supplicant events */
     /* Connection to supplicant established */
@@ -355,6 +359,10 @@
     private static final int MIN_RSSI = -200;
     private static final int MAX_RSSI = 256;
 
+    /* Constants to indicate if soft ap is running or stopped */
+    private static final int SOFT_AP_STOPPED = 0;
+    private static final int SOFT_AP_RUNNING = 1;
+
     /* Default parent state */
     private HierarchicalState mDefaultState = new DefaultState();
     /* Temporary initial state */
@@ -593,6 +601,17 @@
         }
     }
 
+    public void setWifiApConfiguration(WifiConfiguration config) {
+        sendMessage(obtainMessage(CMD_SET_AP_CONFIG, config));
+    }
+
+    public WifiConfiguration syncGetWifiApConfiguration(AsyncChannel channel) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_GET_AP_CONFIG);
+        WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
+        resultMsg.recycle();
+        return ret;
+    }
+
     /**
      * TODO: doc
      */
@@ -1517,7 +1536,31 @@
          */
         WifiNative.disconnectCommand();
         WifiNative.reconnectCommand();
+    }
 
+    private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) {
+        if (config == null) {
+            config = WifiApConfigStore.getApConfiguration();
+        } else {
+            WifiApConfigStore.setApConfiguration(config);
+        }
+        try {
+            if (currentStatus == SOFT_AP_STOPPED) {
+                nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+            } else if (currentStatus == SOFT_AP_RUNNING) {
+                nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Exception in softap start " + e);
+            try {
+                nwService.stopAccessPoint();
+                nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+            } catch (Exception ee) {
+                Log.e(TAG, "Exception during softap restart : " + ee);
+                return false;
+            }
+        }
+        return true;
     }
 
 
@@ -1655,6 +1698,13 @@
                 case CMD_ENABLE_BACKGROUND_SCAN:
                     mEnableBackgroundScan = (message.arg1 == 1);
                     break;
+                case CMD_SET_AP_CONFIG:
+                    WifiApConfigStore.setApConfiguration((WifiConfiguration) message.obj);
+                    break;
+                case CMD_GET_AP_CONFIG:
+                    WifiConfiguration config = WifiApConfigStore.getApConfiguration();
+                    mReplyChannel.replyToMessage(message, message.what, config);
+                    break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
                 case CMD_UNLOAD_DRIVER:
@@ -1717,6 +1767,8 @@
             // 50021 wifi_state_changed (custom|1|5)
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
+            WifiApConfigStore.initialize(mContext);
+
             if (WifiNative.isDriverLoaded()) {
                 transitionTo(mDriverLoadedState);
             }
@@ -1829,26 +1881,14 @@
                     }
                     break;
                 case CMD_START_AP:
-                    try {
-                        nwService.startAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Exception in softap start " + e);
-                        try {
-                            nwService.stopAccessPoint();
-                            nwService.startAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                        } catch (Exception ee) {
-                            Log.e(TAG, "Exception during softap restart : " + ee);
-                            sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
-                            break;
-                        }
+                    if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_STOPPED)) {
+                        Log.d(TAG, "Soft AP start successful");
+                        setWifiApState(WIFI_AP_STATE_ENABLED);
+                        transitionTo(mSoftApStartedState);
+                    } else {
+                        Log.d(TAG, "Soft AP start failed");
+                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
                     }
-                    Log.d(TAG, "Soft AP start successful");
-                    setWifiApState(WIFI_AP_STATE_ENABLED);
-                    transitionTo(mSoftApStartedState);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -2999,21 +3039,13 @@
                     break;
                 case CMD_START_AP:
                     Log.d(TAG,"SoftAP set on a running access point");
-                    try {
-                        nwService.setAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                    } catch(Exception e) {
-                        Log.e(TAG, "Exception in softap set " + e);
-                        try {
-                            nwService.stopAccessPoint();
-                            nwService.startAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                        } catch (Exception ee) {
-                            Log.e(TAG, "Could not restart softap after set failed " + ee);
-                            sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
-                        }
+                    if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_RUNNING)) {
+                        Log.d(TAG, "Soft AP start successful");
+                        setWifiApState(WIFI_AP_STATE_ENABLED);
+                        transitionTo(mSoftApStartedState);
+                    } else {
+                        Log.d(TAG, "Soft AP start failed");
+                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
                     }
                     break;
                 /* Fail client mode operation when soft AP is enabled */