diff options
19 files changed, 143 insertions, 82 deletions
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 43a163d..6382cee 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -858,6 +858,9 @@ public class SearchManager */ public Intent getAssistIntent(Context context, int userHandle) { try { + if (mService == null) { + return null; + } ComponentName comp = mService.getAssistIntent(userHandle); if (comp == null) { return null; diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index f07002e..6f1cc94 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -930,11 +930,13 @@ public class InputMethodService extends AbstractInputMethodService { */ public void onConfigureWindow(Window win, boolean isFullscreen, boolean isCandidatesOnly) { - if (isFullscreen) { - mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT); - } else { - mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT); + final int currentHeight = mWindow.getWindow().getAttributes().height; + final int newHeight = isFullscreen ? MATCH_PARENT : WRAP_CONTENT; + if (mIsInputViewShown && currentHeight != newHeight) { + Log.w(TAG, "Window size has been changed. This may cause jankiness of resizing window: " + + currentHeight + " -> " + newHeight); } + mWindow.getWindow().setLayout(MATCH_PARENT, newHeight); } /** @@ -997,10 +999,11 @@ public class InputMethodService extends AbstractInputMethodService { } void updateExtractFrameVisibility() { - int vis; + final int vis; if (isFullscreenMode()) { vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE; - mExtractFrame.setVisibility(View.VISIBLE); + // "vis" should be applied for the extract frame as well in the fullscreen mode. + mExtractFrame.setVisibility(vis); } else { vis = View.VISIBLE; mExtractFrame.setVisibility(View.GONE); diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java index 874e80a..8dc900e 100644 --- a/core/java/android/net/DhcpStateMachine.java +++ b/core/java/android/net/DhcpStateMachine.java @@ -351,6 +351,8 @@ public class DhcpStateMachine extends StateMachine { DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); if (dhcpAction == DhcpAction.START) { + /* Stop any existing DHCP daemon before starting new */ + NetworkUtils.stopDhcp(mInterfaceName); if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName); success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal); mDhcpInfo = dhcpInfoInternal; diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index ed51818..0ca9183 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -44,6 +44,7 @@ public final class Trace { public static final long TRACE_TAG_AUDIO = 1L << 8; public static final long TRACE_TAG_VIDEO = 1L << 9; public static final long TRACE_TAG_CAMERA = 1L << 10; + private static final long TRACE_TAG_NOT_READY = 1L << 63; public static final int TRACE_FLAGS_START_BIT = 1; public static final String[] TRACE_TAGS = { @@ -53,11 +54,8 @@ public final class Trace { public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags"; - // This works as a "not ready" flag because TRACE_TAG_ALWAYS is always set. - private static final long TRACE_FLAGS_NOT_READY = 0; - // Must be volatile to avoid word tearing. - private static volatile long sEnabledTags = TRACE_FLAGS_NOT_READY; + private static volatile long sEnabledTags = TRACE_TAG_NOT_READY; private static native long nativeGetEnabledTags(); private static native void nativeTraceCounter(long tag, String name, int value); @@ -99,7 +97,7 @@ public final class Trace { */ private static long cacheEnabledTags() { long tags = nativeGetEnabledTags(); - if (tags == TRACE_FLAGS_NOT_READY) { + if (tags == TRACE_TAG_NOT_READY) { Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags); // keep going } @@ -115,7 +113,7 @@ public final class Trace { */ public static boolean isTagEnabled(long traceTag) { long tags = sEnabledTags; - if (tags == TRACE_FLAGS_NOT_READY) { + if (tags == TRACE_TAG_NOT_READY) { tags = cacheEnabledTags(); } return (tags & traceTag) != 0; diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp index e7c4c23..9537ac4 100644 --- a/core/jni/android_net_wifi_Wifi.cpp +++ b/core/jni/android_net_wifi_Wifi.cpp @@ -122,9 +122,9 @@ static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0); } -static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject) +static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p2pSupported) { - return (jboolean)(::wifi_stop_supplicant() == 0); + return (jboolean)(::wifi_stop_supplicant(p2pSupported) == 0); } static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface) @@ -204,7 +204,7 @@ static JNINativeMethod gWifiMethods[] = { { "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded }, { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant }, - { "killSupplicant", "()Z", (void *)android_net_wifi_killSupplicant }, + { "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant }, { "connectToSupplicant", "(Ljava/lang/String;)Z", (void *)android_net_wifi_connectToSupplicant }, { "closeSupplicantConnection", "(Ljava/lang/String;)V", diff --git a/core/res/res/drawable-hdpi/ic_coins_l.png b/core/res/res/drawable-hdpi/ic_coins_l.png Binary files differnew file mode 100644 index 0000000..e1e3e2a --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_coins_l.png diff --git a/core/res/res/drawable-mdpi/ic_coins_l.png b/core/res/res/drawable-mdpi/ic_coins_l.png Binary files differnew file mode 100644 index 0000000..a6d7abb --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_coins_l.png diff --git a/core/res/res/drawable-xhdpi/ic_coins_l.png b/core/res/res/drawable-xhdpi/ic_coins_l.png Binary files differnew file mode 100644 index 0000000..84e7e72 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_coins_l.png diff --git a/core/res/res/layout/sms_short_code_confirmation_dialog.xml b/core/res/res/layout/sms_short_code_confirmation_dialog.xml index ec39d97..d82f560 100644 --- a/core/res/res/layout/sms_short_code_confirmation_dialog.xml +++ b/core/res/res/layout/sms_short_code_confirmation_dialog.xml @@ -30,9 +30,9 @@ style="?android:attr/textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingLeft="16dip" - android:paddingRight="16dip" - android:paddingTop="8dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" + android:paddingTop="16dip" android:paddingBottom="16dip" /> <TableLayout android:id="@+id/sms_short_code_detail_layout" @@ -51,7 +51,7 @@ android:layout_height="wrap_content" android:paddingLeft="8dip" android:paddingRight="8dip" - android:src="@null" /> + android:src="@drawable/ic_coins_l" /> <TextView android:id="@+id/sms_short_code_detail_message" android:layout_width="match_parent" android:layout_height="wrap_content" /> @@ -60,14 +60,19 @@ <TableRow android:layout_width="wrap_content" android:layout_height="wrap_content" > - + <RelativeLayout android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="12dip" + android:paddingLeft="8dip" > <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox" + android:paddingTop="11dip" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingRight="8dip" /> + android:layout_height="wrap_content" /> + </RelativeLayout> <TextView android:id="@+id/sms_short_code_remember_choice_text" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:paddingTop="18dip" android:text="@string/sms_short_code_remember_choice" /> </TableRow> @@ -77,6 +82,7 @@ <Space android:layout_gravity="fill" /> <TextView android:id="@+id/sms_short_code_remember_undo_instruction" + android:paddingTop="10dip" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 315196e..22f699f 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -436,6 +436,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished { private boolean mDockAudioMediaEnabled = true; + private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; + /////////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////////// @@ -3324,6 +3326,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished { mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); } + + synchronized (mSettingsLock) { + AudioSystem.setForceUse(AudioSystem.FOR_DOCK, + mDockAudioMediaEnabled ? + AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); + } + // indicate the end of reconfiguration phase to audio HAL AudioSystem.setParameters("restarting=false"); break; @@ -3751,13 +3760,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { config = AudioSystem.FORCE_BT_CAR_DOCK; break; case Intent.EXTRA_DOCK_STATE_LE_DESK: - synchronized (mSettingsLock) { - if (mDockAudioMediaEnabled) { - config = AudioSystem.FORCE_ANALOG_DOCK; - } else { - config = AudioSystem.FORCE_NONE; - } - } + config = AudioSystem.FORCE_ANALOG_DOCK; break; case Intent.EXTRA_DOCK_STATE_HE_DESK: config = AudioSystem.FORCE_DIGITAL_DOCK; @@ -3766,8 +3769,14 @@ public class AudioService extends IAudioService.Stub implements OnFinished { default: config = AudioSystem.FORCE_NONE; } - - AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); + // Low end docks have a menu to enable or disable audio + // (see mDockAudioMediaEnabled) + if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || + ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && + (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { + AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); + } + mDockState = dockState; } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index df4c661..c227619 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -22,6 +22,7 @@ import android.app.Activity; import android.app.ActivityManagerNative; import android.app.AlarmManager; import android.app.PendingIntent; +import android.app.SearchManager; import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -166,6 +167,9 @@ public class KeyguardViewMediator { /** UserManager for querying number of users */ private UserManager mUserManager; + /** SearchManager for determining whether or not search assistant is available */ + private SearchManager mSearchManager; + /** * Used to keep the device awake while to ensure the keyguard finishes opening before * we sleep. @@ -527,6 +531,7 @@ public class KeyguardViewMediator { * Let us know that the system is ready after startup. */ public void onSystemReady() { + mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); synchronized (this) { if (DEBUG) Log.d(TAG, "onSystemReady"); mSystemReady = true; @@ -1313,6 +1318,9 @@ public class KeyguardViewMediator { // showing secure lockscreen; disable ticker. flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER; } + if (!isAssistantAvailable()) { + flags |= StatusBarManager.DISABLE_SEARCH; + } } if (DEBUG) { @@ -1410,4 +1418,8 @@ public class KeyguardViewMediator { mKeyguardViewManager.showAssistant(); } + private boolean isAssistantAvailable() { + return mSearchManager != null + && mSearchManager.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null; + } } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index ad1dfb2..a7c4d73 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -2686,18 +2686,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { state + "/" + info.getDetailedState()); } - // Connectivity state changed: - // [31-14] Reserved for future use - // [13-10] Network subtype (for mobile network, as defined - // by TelephonyManager) - // [9-4] Detailed state ordinal (as defined by - // NetworkInfo.DetailedState) - // [3-0] Network type (as defined by ConnectivityManager) - int eventLogParam = (info.getType() & 0xf) | - ((info.getDetailedState().ordinal() & 0x3f) << 4) | - (info.getSubtype() << 10); - EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED, - eventLogParam); + EventLogTags.writeConnectivityStateChanged( + info.getType(), info.getSubtype(), info.getDetailedState().ordinal()); if (info.getDetailedState() == NetworkInfo.DetailedState.FAILED) { diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags index 0fe66fc..8bc2da2 100644 --- a/services/java/com/android/server/EventLogTags.logtags +++ b/services/java/com/android/server/EventLogTags.logtags @@ -135,12 +135,8 @@ option java_package com.android.server # --------------------------- # ConnectivityService.java # --------------------------- -# Connectivity state changed: -# [31-14] Reserved for future use -# [13-10] Network subtype (for mobile network, as defined by TelephonyManager) -# [ 9- 4] Detailed state ordinal (as defined by NetworkInfo.DetailedState) -# [ 3- 0] Network type (as defined by ConnectivityManager) -50020 connectivity_state_changed (custom|1|5) +# Connectivity state changed +50020 connectivity_state_changed (type|1),(subtype|1),(state|1) # --------------------------- diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index d2cd646..db64a9a 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -14229,6 +14229,7 @@ public final class ActivityManagerService extends ActivityManagerNative startHomeActivityLocked(userId); } + EventLogTags.writeAmSwitchUser(userId); getUserManagerLocked().userForeground(userId); sendUserSwitchBroadcastsLocked(oldUserId, userId); if (needStart) { diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/java/com/android/server/am/EventLogTags.logtags index 6ee7507..88c0c03 100644 --- a/services/java/com/android/server/am/EventLogTags.logtags +++ b/services/java/com/android/server/am/EventLogTags.logtags @@ -83,3 +83,6 @@ option java_package com.android.server.am 30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5) # Log.wtf() called 30040 am_wtf (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3) + +# User switched +30041 am_switch_user (id|1|5) diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java index e05442b..66c3ce9 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/java/com/android/server/pm/UserManagerService.java @@ -16,8 +16,7 @@ package com.android.server.pm; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.FastXmlSerializer; +import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import android.app.Activity; import android.app.ActivityManager; @@ -26,7 +25,6 @@ import android.app.IStopUserCallback; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.graphics.Bitmap; @@ -34,6 +32,7 @@ import android.graphics.BitmapFactory; import android.os.Binder; import android.os.Environment; import android.os.FileUtils; +import android.os.Handler; import android.os.IUserManager; import android.os.Process; import android.os.RemoteException; @@ -42,9 +41,17 @@ import android.os.UserManager; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.Xml; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.FastXmlSerializer; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + import java.io.BufferedOutputStream; import java.io.File; import java.io.FileDescriptor; @@ -54,13 +61,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - public class UserManagerService extends IUserManager.Stub { private static final String LOG_TAG = "UserManagerService"; @@ -95,19 +97,24 @@ public class UserManagerService extends IUserManager.Stub { private final Object mInstallLock; private final Object mPackagesLock; + private final Handler mHandler; + private final File mUsersDir; private final File mUserListFile; private final File mBaseUserPath; - private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); - private HashSet<Integer> mRemovingUserIds = new HashSet<Integer>(); + private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); + + /** + * Set of user IDs being actively removed. Removed IDs linger in this set + * for several seconds to work around a VFS caching issue. + */ + // @GuardedBy("mPackagesLock") + private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray(); private int[] mUserIds; private boolean mGuestEnabled; private int mNextSerialNumber; - // This resets on a reboot. Otherwise it keeps incrementing so that user ids are - // not reused in quick succession - private int mNextUserId = MIN_USER_ID; private int mUserVersion = 0; private static UserManagerService sInstance; @@ -147,6 +154,7 @@ public class UserManagerService extends IUserManager.Stub { mPm = pm; mInstallLock = installLock; mPackagesLock = packagesLock; + mHandler = new Handler(); synchronized (mInstallLock) { synchronized (mPackagesLock) { mUsersDir = new File(dataDir, USER_INFO_DIR); @@ -190,7 +198,7 @@ public class UserManagerService extends IUserManager.Stub { if (ui.partial) { continue; } - if (!excludeDying || !mRemovingUserIds.contains(ui.id)) { + if (!excludeDying || !mRemovingUserIds.get(ui.id)) { users.add(ui); } } @@ -212,7 +220,7 @@ public class UserManagerService extends IUserManager.Stub { private UserInfo getUserInfoLocked(int userId) { UserInfo ui = mUsers.get(userId); // If it is partial and not in the process of being removed, return as unknown user. - if (ui != null && ui.partial && !mRemovingUserIds.contains(userId)) { + if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) { Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId); return null; } @@ -502,7 +510,7 @@ public class UserManagerService extends IUserManager.Stub { private void fallbackToSingleUserLocked() { // Create the primary user - UserInfo primary = new UserInfo(0, + UserInfo primary = new UserInfo(0, mContext.getResources().getString(com.android.internal.R.string.owner_name), null, UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED); mUsers.put(0, primary); @@ -749,7 +757,7 @@ public class UserManagerService extends IUserManager.Stub { if (userHandle == 0 || user == null) { return false; } - mRemovingUserIds.add(userHandle); + mRemovingUserIds.put(userHandle, true); // Set this to a partially created user, so that the user will be purged // on next startup, in case the runtime stops now before stopping and // removing the user completely. @@ -813,13 +821,25 @@ public class UserManagerService extends IUserManager.Stub { } } - private void removeUserStateLocked(int userHandle) { + private void removeUserStateLocked(final int userHandle) { // Cleanup package manager settings mPm.cleanUpUserLILPw(userHandle); // Remove this user from the list mUsers.remove(userHandle); - mRemovingUserIds.remove(userHandle); + + // Have user ID linger for several seconds to let external storage VFS + // cache entries expire. This must be greater than the 'entry_valid' + // timeout used by the FUSE daemon. + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + synchronized (mPackagesLock) { + mRemovingUserIds.delete(userHandle); + } + } + }, MINUTE_IN_MILLIS); + // Remove user file AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml")); userFile.delete(); @@ -906,14 +926,13 @@ public class UserManagerService extends IUserManager.Stub { */ private int getNextAvailableIdLocked() { synchronized (mPackagesLock) { - int i = mNextUserId; + int i = MIN_USER_ID; while (i < Integer.MAX_VALUE) { - if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.contains(i)) { + if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) { break; } i++; } - mNextUserId = i + 1; return i; } } @@ -938,7 +957,7 @@ public class UserManagerService extends IUserManager.Stub { UserInfo user = mUsers.valueAt(i); if (user == null) continue; pw.print(" "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber); - if (mRemovingUserIds.contains(mUsers.keyAt(i))) pw.print(" <removing> "); + if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> "); if (user.partial) pw.print(" <partial>"); pw.println(); pw.print(" Created: "); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index b871cdc..0e29882 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -508,6 +508,10 @@ public class WifiManager { private Messenger mWifiServiceMessenger; private final CountDownLatch mConnected = new CountDownLatch(1); + private static Object sThreadRefLock = new Object(); + private static int sThreadRefCount; + private static HandlerThread sHandlerThread; + /** * Create a new WifiManager instance. * Applications will almost always want to use @@ -1365,9 +1369,14 @@ public class WifiManager { return; } - HandlerThread t = new HandlerThread("WifiManager"); - t.start(); - mHandler = new ServiceHandler(t.getLooper()); + synchronized (sThreadRefLock) { + if (++sThreadRefCount == 1) { + sHandlerThread = new HandlerThread("WifiManager"); + sHandlerThread.start(); + } + } + + mHandler = new ServiceHandler(sHandlerThread.getLooper()); mAsyncChannel.connect(mContext, mHandler, mWifiServiceMessenger); try { mConnected.await(); @@ -1983,8 +1992,10 @@ public class WifiManager { protected void finalize() throws Throwable { try { - if (mHandler != null && mHandler.getLooper() != null) { - mHandler.getLooper().quit(); + synchronized (sThreadRefLock) { + if (--sThreadRefCount == 0 && sHandlerThread != null) { + sHandlerThread.getLooper().quit(); + } } } finally { super.finalize(); diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 4c5fc5d..5e25623 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -61,7 +61,7 @@ public class WifiNative { /* Sends a kill signal to supplicant. To be used when we have lost connection or when the supplicant is hung */ - public native static boolean killSupplicant(); + public native static boolean killSupplicant(boolean p2pSupported); private native boolean connectToSupplicant(String iface); diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 040ff24..dafa8e8 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -1944,6 +1944,7 @@ public class WifiStateMachine extends StateMachine { case CMD_STOP_DRIVER: case CMD_DELAYED_STOP_DRIVER: case CMD_DRIVER_START_TIMED_OUT: + case CMD_CAPTIVE_CHECK_COMPLETE: case CMD_START_AP: case CMD_START_AP_SUCCESS: case CMD_START_AP_FAILURE: @@ -2189,6 +2190,13 @@ public class WifiStateMachine extends StateMachine { loge("Unable to change interface settings: " + ie); } + /* Stop a running supplicant after a runtime restart + * Avoids issues with drivers that do not handle interface down + * on a running supplicant properly. + */ + if (DBG) log("Kill any running supplicant"); + mWifiNative.killSupplicant(mP2pSupported); + if(mWifiNative.startSupplicant(mP2pSupported)) { if (DBG) log("Supplicant start successful"); mWifiMonitor.startMonitoring(); @@ -2384,7 +2392,7 @@ public class WifiStateMachine extends StateMachine { case WifiMonitor.SUP_DISCONNECTION_EVENT: if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { loge("Failed to setup control channel, restart supplicant"); - mWifiNative.killSupplicant(); + mWifiNative.killSupplicant(mP2pSupported); transitionTo(mDriverLoadedState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); } else { @@ -2451,7 +2459,7 @@ public class WifiStateMachine extends StateMachine { break; case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ loge("Connection lost, restart supplicant"); - mWifiNative.killSupplicant(); + mWifiNative.killSupplicant(mP2pSupported); mWifiNative.closeSupplicantConnection(); mNetworkInfo.setIsAvailable(false); handleNetworkDisconnect(); @@ -2605,14 +2613,14 @@ public class WifiStateMachine extends StateMachine { /* Socket connection can be lost when we do a graceful shutdown * or when the driver is hung. Ensure supplicant is stopped here. */ - mWifiNative.killSupplicant(); + mWifiNative.killSupplicant(mP2pSupported); mWifiNative.closeSupplicantConnection(); transitionTo(mDriverLoadedState); break; case CMD_STOP_SUPPLICANT_FAILED: if (message.arg1 == mSupplicantStopFailureToken) { loge("Timed out on a supplicant stop, kill and proceed"); - mWifiNative.killSupplicant(); + mWifiNative.killSupplicant(mP2pSupported); mWifiNative.closeSupplicantConnection(); transitionTo(mDriverLoadedState); } |
