diff options
| -rw-r--r-- | api/current.xml | 19 | ||||
| -rw-r--r-- | core/java/android/app/BackStackRecord.java | 30 | ||||
| -rw-r--r-- | core/java/android/app/FragmentTransaction.java | 14 | ||||
| -rw-r--r-- | services/java/com/android/server/WifiService.java | 51 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/IWifiManager.aidl | 2 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiApConfigStore.java | 181 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiManager.java | 3 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 102 |
8 files changed, 317 insertions, 85 deletions
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 @@ final class BackStackState implements Parcelable { 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 @@ final class BackStackState implements Parcelable { 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 @@ final class BackStackState implements Parcelable { 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 @@ final class BackStackRecord extends FragmentTransaction implements Fragment fragment; int enterAnim; int exitAnim; + int popEnterAnim; + int popExitAnim; ArrayList<Fragment> removed; } @@ -187,6 +193,8 @@ final class BackStackRecord extends FragmentTransaction implements int mNumOp; int mEnterAnim; int mExitAnim; + int mPopEnterAnim; + int mPopExitAnim; int mTransition; int mTransitionStyle; boolean mAddToBackStack; @@ -243,6 +251,11 @@ final class BackStackRecord extends FragmentTransaction implements 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 @@ final class BackStackRecord extends FragmentTransaction implements } op.enterAnim = mEnterAnim; op.exitAnim = mExitAnim; + op.popEnterAnim = mPopEnterAnim; + op.popExitAnim = mPopExitAnim; mNumOp++; } @@ -430,8 +445,15 @@ final class BackStackRecord extends FragmentTransaction implements } 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 @@ final class BackStackRecord extends FragmentTransaction implements 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 @@ final class BackStackRecord extends FragmentTransaction implements } 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 @@ final class BackStackRecord extends FragmentTransaction implements 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 @@ final class BackStackRecord extends FragmentTransaction implements } 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 @@ public abstract class FragmentTransaction { /** * 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 @@ public class WifiService extends IWifiManager.Stub { * @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 @@ public class WifiService extends IWifiManager.Stub { * 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 @@ interface IWifiManager 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 class WifiManager { */ 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..0c0e253 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -200,8 +200,12 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 class WifiStateMachine extends HierarchicalStateMachine { } } + 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { */ 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { // 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { } 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 */ |
