diff options
Diffstat (limited to 'services/java/com/android')
12 files changed, 613 insertions, 323 deletions
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 8e3b825..a49ccf7 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1142,6 +1142,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (mCurToken != null) { try { if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken); + if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0) { + // The current IME is shown. Hence an IME switch (transition) is happening. + mWindowManagerService.saveLastInputMethodWindowForTransition(); + } mIWindowManager.removeWindowToken(mCurToken); } catch (RemoteException e) { } @@ -2410,17 +2414,63 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - private static class ImeSubtypeListItem { + private static class ImeSubtypeListItem implements Comparable<ImeSubtypeListItem> { public final CharSequence mImeName; public final CharSequence mSubtypeName; public final InputMethodInfo mImi; public final int mSubtypeId; + private final boolean mIsSystemLocale; + private final boolean mIsSystemLanguage; + public ImeSubtypeListItem(CharSequence imeName, CharSequence subtypeName, - InputMethodInfo imi, int subtypeId) { + InputMethodInfo imi, int subtypeId, String subtypeLocale, String systemLocale) { mImeName = imeName; mSubtypeName = subtypeName; mImi = imi; mSubtypeId = subtypeId; + if (TextUtils.isEmpty(subtypeLocale)) { + mIsSystemLocale = false; + mIsSystemLanguage = false; + } else { + mIsSystemLocale = subtypeLocale.equals(systemLocale); + mIsSystemLanguage = mIsSystemLocale + || subtypeLocale.startsWith(systemLocale.substring(0, 2)); + } + } + + @Override + public int compareTo(ImeSubtypeListItem other) { + if (TextUtils.isEmpty(mImeName)) { + return 1; + } + if (TextUtils.isEmpty(other.mImeName)) { + return -1; + } + if (!TextUtils.equals(mImeName, other.mImeName)) { + return mImeName.toString().compareTo(other.mImeName.toString()); + } + if (TextUtils.equals(mSubtypeName, other.mSubtypeName)) { + return 0; + } + if (mIsSystemLocale) { + return -1; + } + if (other.mIsSystemLocale) { + return 1; + } + if (mIsSystemLanguage) { + return -1; + } + if (other.mIsSystemLanguage) { + return 1; + } + if (TextUtils.isEmpty(mSubtypeName)) { + return 1; + } + if (TextUtils.isEmpty(other.mSubtypeName)) { + return -1; + } + return mSubtypeName.toString().compareTo(other.mSubtypeName.toString()); } } @@ -2619,7 +2669,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return getSubtypeIdFromHashCode(imi, subtypeId); } - private int getSubtypeIdFromHashCode(InputMethodInfo imi, int subtypeHashCode) { + private static boolean isValidSubtypeId(InputMethodInfo imi, int subtypeHashCode) { + return getSubtypeIdFromHashCode(imi, subtypeHashCode) != NOT_A_SUBTYPE_ID; + } + + private static int getSubtypeIdFromHashCode(InputMethodInfo imi, int subtypeHashCode) { if (imi != null) { final int subtypeCount = imi.getSubtypeCount(); for (int i = 0; i < subtypeCount; ++i) { @@ -2844,6 +2898,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ @Override public InputMethodSubtype getCurrentInputMethodSubtype() { + if (mCurMethodId == null) { + return null; + } boolean subtypeIsSelected = false; try { subtypeIsSelected = Settings.Secure.getInt(mContext.getContentResolver(), @@ -2851,36 +2908,35 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } catch (SettingNotFoundException e) { } synchronized (mMethodMap) { - if (!subtypeIsSelected || mCurrentSubtype == null) { - String lastInputMethodId = Settings.Secure.getString( - mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); - int subtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId); + final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + if (imi == null || imi.getSubtypeCount() == 0) { + return null; + } + if (!subtypeIsSelected || mCurrentSubtype == null + || !isValidSubtypeId(imi, mCurrentSubtype.hashCode())) { + int subtypeId = getSelectedInputMethodSubtypeId(mCurMethodId); if (subtypeId == NOT_A_SUBTYPE_ID) { - InputMethodInfo imi = mMethodMap.get(lastInputMethodId); - if (imi != null) { - // If there are no selected subtypes, the framework will try to find - // the most applicable subtype from explicitly or implicitly enabled - // subtypes. - List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes = - getEnabledInputMethodSubtypeList(imi, true); - // If there is only one explicitly or implicitly enabled subtype, - // just returns it. - if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) { - mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0); - } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) { + // If there are no selected subtypes, the framework will try to find + // the most applicable subtype from explicitly or implicitly enabled + // subtypes. + List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes = + getEnabledInputMethodSubtypeList(imi, true); + // If there is only one explicitly or implicitly enabled subtype, + // just returns it. + if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) { + mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0); + } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) { + mCurrentSubtype = findLastResortApplicableSubtypeLocked( + mRes, explicitlyOrImplicitlyEnabledSubtypes, + SUBTYPE_MODE_KEYBOARD, null, true); + if (mCurrentSubtype == null) { mCurrentSubtype = findLastResortApplicableSubtypeLocked( - mRes, explicitlyOrImplicitlyEnabledSubtypes, - SUBTYPE_MODE_KEYBOARD, null, true); - if (mCurrentSubtype == null) { - mCurrentSubtype = findLastResortApplicableSubtypeLocked( - mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null, - true); - } + mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null, + true); } } } else { - mCurrentSubtype = - getSubtypes(mMethodMap.get(lastInputMethodId)).get(subtypeId); + mCurrentSubtype = getSubtypes(imi).get(subtypeId); } } return mCurrentSubtype; @@ -2946,10 +3002,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final Context mContext; private final PackageManager mPm; private final InputMethodManagerService mImms; + private final String mSystemLocaleStr; public InputMethodAndSubtypeListManager(Context context, InputMethodManagerService imms) { mContext = context; mPm = context.getPackageManager(); mImms = imms; + mSystemLocaleStr = + imms.mLastSystemLocale != null ? imms.mLastSystemLocale.toString() : ""; } private final TreeMap<InputMethodInfo, List<InputMethodSubtype>> mSortedImmis = @@ -2979,7 +3038,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } final int N = imList.size(); final int currentSubtypeId = subtype != null - ? mImms.getSubtypeIdFromHashCode(imi, subtype.hashCode()) + ? getSubtypeIdFromHashCode(imi, subtype.hashCode()) : NOT_A_SUBTYPE_ID; for (int i = 0; i < N; ++i) { final ImeSubtypeListItem isli = imList.get(i); @@ -3037,7 +3096,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub subtype.overridesImplicitlyEnabledSubtype() ? null : subtype.getDisplayName(mContext, imi.getPackageName(), imi.getServiceInfo().applicationInfo); - imList.add(new ImeSubtypeListItem(imeLabel, subtypeLabel, imi, j)); + imList.add(new ImeSubtypeListItem(imeLabel, subtypeLabel, imi, j, + subtype.getLocale(), mSystemLocaleStr)); // Removing this subtype from enabledSubtypeSet because we no longer // need to add an entry of this subtype to imList to avoid duplicated @@ -3046,9 +3106,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } else { - imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID)); + imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID, + null, mSystemLocaleStr)); } } + Collections.sort(imList); return imList; } } @@ -3356,10 +3418,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub for (Pair<String, ArrayList<String>> enabledIme: enabledImes) { if (enabledIme.first.equals(imeId)) { final ArrayList<String> explicitlyEnabledSubtypes = enabledIme.second; + final InputMethodInfo imi = mMethodMap.get(imeId); if (explicitlyEnabledSubtypes.size() == 0) { // If there are no explicitly enabled subtypes, applicable subtypes are // enabled implicitly. - InputMethodInfo imi = mMethodMap.get(imeId); // If IME is enabled and no subtypes are enabled, applicable subtypes // are enabled implicitly, so needs to treat them to be enabled. if (imi != null && imi.getSubtypeCount() > 0) { @@ -3379,7 +3441,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub for (String s: explicitlyEnabledSubtypes) { if (s.equals(subtypeHashCode)) { // If both imeId and subtypeId are enabled, return subtypeId. - return s; + try { + final int hashCode = Integer.valueOf(subtypeHashCode); + // Check whether the subtype id is valid or not + if (isValidSubtypeId(imi, hashCode)) { + return s; + } else { + return NOT_A_SUBTYPE_ID_STR; + } + } catch (NumberFormatException e) { + return NOT_A_SUBTYPE_ID_STR; + } } } } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 663a031..52ba665 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -1046,7 +1046,7 @@ public class NotificationManagerService extends INotificationManager.Stub final boolean useDefaultVibrate = (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; if ((useDefaultVibrate || notification.vibrate != null) - && audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_NOTIFICATION)) { + && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; mVibrator.vibrate(useDefaultVibrate ? DEFAULT_VIBRATE_PATTERN diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java index f33bf8b..cc8e6a4 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/java/com/android/server/NsdService.java @@ -20,7 +20,7 @@ import android.content.Context; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.nsd.DnsSdServiceInfo; +import android.net.nsd.NsdServiceInfo; import android.net.nsd.DnsSdTxtRecord; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; @@ -32,6 +32,7 @@ import android.os.Messenger; import android.os.IBinder; import android.provider.Settings; import android.util.Slog; +import android.util.SparseArray; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -72,13 +73,16 @@ public class NsdService extends INsdManager.Stub { */ private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(); + /* A map from unique id to client info */ + private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>(); + private AsyncChannel mReplyChannel = new AsyncChannel(); private int INVALID_ID = 0; private int mUniqueId = 1; private static final int BASE = Protocol.BASE_NSD_MANAGER; - private static final int CMD_TO_STRING_COUNT = NsdManager.STOP_RESOLVE - BASE + 1; + private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1; private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; static { @@ -87,7 +91,6 @@ public class NsdService extends INsdManager.Stub { sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; - sCmdToString[NsdManager.STOP_RESOLVE - BASE] = "STOP-RESOLVE"; } private static String cmdToString(int cmd) { @@ -101,9 +104,9 @@ public class NsdService extends INsdManager.Stub { private class NsdStateMachine extends StateMachine { - private DefaultState mDefaultState = new DefaultState(); - private DisabledState mDisabledState = new DisabledState(); - private EnabledState mEnabledState = new EnabledState(); + private final DefaultState mDefaultState = new DefaultState(); + private final DisabledState mDisabledState = new DisabledState(); + private final EnabledState mEnabledState = new EnabledState(); @Override protected String getMessageInfo(Message msg) { @@ -151,29 +154,26 @@ public class NsdService extends INsdManager.Stub { ac.connect(mContext, getHandler(), msg.replyTo); break; case NsdManager.DISCOVER_SERVICES: - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.BUSY); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.STOP_DISCOVERY: - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.REGISTER_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.UNREGISTER_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.RESOLVE_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NsdManager.STOP_RESOLVE: - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; + case NsdManager.NATIVE_DAEMON_EVENT: default: Slog.e(TAG, "Unhandled " + msg); return NOT_HANDLED; @@ -217,11 +217,30 @@ public class NsdService extends INsdManager.Stub { } } + private boolean requestLimitReached(ClientInfo clientInfo) { + if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) { + if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo); + return true; + } + return false; + } + + private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { + clientInfo.mClientIds.put(clientId, globalId); + mIdToClientInfoMap.put(globalId, clientInfo); + } + + private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { + clientInfo.mClientIds.remove(clientId); + mIdToClientInfoMap.remove(globalId); + } + @Override public boolean processMessage(Message msg) { ClientInfo clientInfo; - DnsSdServiceInfo servInfo; + NsdServiceInfo servInfo; boolean result = HANDLED; + int id; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: //First client @@ -244,111 +263,112 @@ public class NsdService extends INsdManager.Stub { break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); - servInfo = (DnsSdServiceInfo) msg.obj; + servInfo = (NsdServiceInfo) msg.obj; clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mDiscoveryId != INVALID_ID) { - //discovery already in progress - if (DBG) Slog.d(TAG, "discovery in progress"); - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ALREADY_ACTIVE); + + if (requestLimitReached(clientInfo)) { + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_MAX_LIMIT); break; } - clientInfo.mDiscoveryId = getUniqueId(); - if (discoverServices(clientInfo.mDiscoveryId, servInfo.getServiceType())) { - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED); + + id = getUniqueId(); + if (discoverServices(id, servInfo.getServiceType())) { + if (DBG) { + Slog.d(TAG, "Discover " + msg.arg2 + " " + id + + servInfo.getServiceType()); + } + storeRequestMap(msg.arg2, id, clientInfo); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); } else { - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ERROR); - clientInfo.mDiscoveryId = INVALID_ID; + stopServiceDiscovery(id); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.STOP_DISCOVERY: if (DBG) Slog.d(TAG, "Stop service discovery"); clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mDiscoveryId == INVALID_ID) { - //already stopped - if (DBG) Slog.d(TAG, "discovery already stopped"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ALREADY_ACTIVE); + + try { + id = clientInfo.mClientIds.get(msg.arg2).intValue(); + } catch (NullPointerException e) { + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; } - if (stopServiceDiscovery(clientInfo.mDiscoveryId)) { - clientInfo.mDiscoveryId = INVALID_ID; - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); + removeRequestMap(msg.arg2, id, clientInfo); + if (stopServiceDiscovery(id)) { + replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); } else { - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.REGISTER_SERVICE: if (DBG) Slog.d(TAG, "Register service"); clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mRegisteredIds.size() >= ClientInfo.MAX_REG) { - if (DBG) Slog.d(TAG, "register service exceeds limit"); - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.MAX_REGS_REACHED); + if (requestLimitReached(clientInfo)) { + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_MAX_LIMIT); + break; } - int id = getUniqueId(); - if (registerService(id, (DnsSdServiceInfo) msg.obj)) { - clientInfo.mRegisteredIds.add(id); + id = getUniqueId(); + if (registerService(id, (NsdServiceInfo) msg.obj)) { + if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); + storeRequestMap(msg.arg2, id, clientInfo); + // Return success after mDns reports success } else { - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); + unregisterService(id); + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.UNREGISTER_SERVICE: if (DBG) Slog.d(TAG, "unregister service"); clientInfo = mClients.get(msg.replyTo); - int regId = msg.arg1; - if (clientInfo.mRegisteredIds.remove(new Integer(regId)) && - unregisterService(regId)) { - mReplyChannel.replyToMessage(msg, - NsdManager.UNREGISTER_SERVICE_SUCCEEDED); + try { + id = clientInfo.mClientIds.get(msg.arg2).intValue(); + } catch (NullPointerException e) { + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); + break; + } + removeRequestMap(msg.arg2, id, clientInfo); + if (unregisterService(id)) { + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); } else { - mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; - case NsdManager.UPDATE_SERVICE: - if (DBG) Slog.d(TAG, "Update service"); - //TODO: implement - mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED); - break; case NsdManager.RESOLVE_SERVICE: if (DBG) Slog.d(TAG, "Resolve service"); - servInfo = (DnsSdServiceInfo) msg.obj; + servInfo = (NsdServiceInfo) msg.obj; clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mResolveId != INVALID_ID) { - //first cancel existing resolve - stopResolveService(clientInfo.mResolveId); - } - clientInfo.mResolveId = getUniqueId(); - if (!resolveService(clientInfo.mResolveId, servInfo)) { - mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - clientInfo.mResolveId = INVALID_ID; - } - break; - case NsdManager.STOP_RESOLVE: - if (DBG) Slog.d(TAG, "Stop resolve"); - clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mResolveId == INVALID_ID) { - //already stopped - if (DBG) Slog.d(TAG, "resolve already stopped"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ALREADY_ACTIVE); + + if (clientInfo.mResolvedService != null) { + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_ALREADY_ACTIVE); break; } - if (stopResolveService(clientInfo.mResolveId)) { - clientInfo.mResolveId = INVALID_ID; - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_SUCCEEDED); + + id = getUniqueId(); + if (resolveService(id, servInfo)) { + clientInfo.mResolvedService = new NsdServiceInfo(); + storeRequestMap(msg.arg2, id, clientInfo); } else { - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; + case NsdManager.NATIVE_DAEMON_EVENT: + NativeEvent event = (NativeEvent) msg.obj; + handleNativeEvent(event.code, event.raw, + NativeDaemonEvent.unescapeArgs(event.raw)); + break; default: result = NOT_HANDLED; break; @@ -439,121 +459,144 @@ public class NsdService extends INsdManager.Stub { public static final int SERVICE_GET_ADDR_SUCCESS = 612; } + private class NativeEvent { + int code; + String raw; + + NativeEvent(int code, String raw) { + this.code = code; + this.raw = raw; + } + } + class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { public void onDaemonConnected() { mNativeDaemonConnected.countDown(); } public boolean onEvent(int code, String raw, String[] cooked) { - ClientInfo clientInfo; - DnsSdServiceInfo servInfo; - int id = Integer.parseInt(cooked[1]); - switch (code) { - case NativeResponseCode.SERVICE_FOUND: - /* NNN uniqueId serviceName regType domain */ - if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, servInfo); - break; - case NativeResponseCode.SERVICE_LOST: - /* NNN uniqueId serviceName regType domain */ - if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, servInfo); - break; - case NativeResponseCode.SERVICE_DISCOVERY_FAILED: - /* NNN uniqueId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_REGISTERED: - /* NNN regId serviceName regType */ - if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); - clientInfo = getClientByRegistration(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], null, null); - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, - id, 0, servInfo); - break; - case NativeResponseCode.SERVICE_REGISTRATION_FAILED: - /* NNN regId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); - clientInfo = getClientByRegistration(id); - if (clientInfo == null) break; - - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_UPDATED: - /* NNN regId */ - break; - case NativeResponseCode.SERVICE_UPDATE_FAILED: - /* NNN regId errorCode */ - break; - case NativeResponseCode.SERVICE_RESOLVED: - /* NNN resolveId fullName hostName port txtlen txtdata */ - if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null) break; - - int index = cooked[2].indexOf("."); - if (index == -1) { - Slog.e(TAG, "Invalid service found " + raw); - break; - } - String name = cooked[2].substring(0, index); - String rest = cooked[2].substring(index); - String type = rest.replace(".local.", ""); + // TODO: NDC translates a message to a callback, we could enhance NDC to + // directly interact with a state machine through messages + NativeEvent event = new NativeEvent(code, raw); + mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event); + return true; + } + } - clientInfo.mResolvedService = new DnsSdServiceInfo(name, type, null); - clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + private void handleNativeEvent(int code, String raw, String[] cooked) { + NsdServiceInfo servInfo; + int id = Integer.parseInt(cooked[1]); + ClientInfo clientInfo = mIdToClientInfoMap.get(id); + if (clientInfo == null) { + Slog.e(TAG, "Unique id with no client mapping: " + id); + return; + } - stopResolveService(id); - getAddrInfo(id, cooked[3]); + /* This goes in response as msg.arg2 */ + int clientId = -1; + int keyId = clientInfo.mClientIds.indexOfValue(id); + if (keyId != -1) { + clientId = clientInfo.mClientIds.keyAt(keyId); + } + switch (code) { + case NativeResponseCode.SERVICE_FOUND: + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, + clientId, servInfo); + break; + case NativeResponseCode.SERVICE_LOST: + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, + clientId, servInfo); + break; + case NativeResponseCode.SERVICE_DISCOVERY_FAILED: + /* NNN uniqueId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_REGISTERED: + /* NNN regId serviceName regType */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], null, null); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, + id, clientId, servInfo); + break; + case NativeResponseCode.SERVICE_REGISTRATION_FAILED: + /* NNN regId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_UPDATED: + /* NNN regId */ + break; + case NativeResponseCode.SERVICE_UPDATE_FAILED: + /* NNN regId errorCode */ + break; + case NativeResponseCode.SERVICE_RESOLVED: + /* NNN resolveId fullName hostName port txtlen txtdata */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); + int index = cooked[2].indexOf("."); + if (index == -1) { + Slog.e(TAG, "Invalid service found " + raw); break; - case NativeResponseCode.SERVICE_RESOLUTION_FAILED: - case NativeResponseCode.SERVICE_GET_ADDR_FAILED: - /* NNN resolveId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null) break; + } + String name = cooked[2].substring(0, index); + String rest = cooked[2].substring(index); + String type = rest.replace(".local.", ""); + + clientInfo.mResolvedService.setServiceName(name); + clientInfo.mResolvedService.setServiceType(type); + clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + stopResolveService(id); + if (!getAddrInfo(id, cooked[3])) { clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: - /* NNN resolveId hostname ttl addr */ - if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null || clientInfo.mResolvedService == null) break; - - try { - clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, - clientInfo.mResolvedService); - clientInfo.mResolvedService = null; - clientInfo.mResolveId = INVALID_ID; - } catch (java.net.UnknownHostException e) { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - } - stopGetAddrInfo(id); - break; - default: - break; - } - return false; + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + } + break; + case NativeResponseCode.SERVICE_RESOLUTION_FAILED: + /* NNN resolveId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + stopResolveService(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_GET_ADDR_FAILED: + /* NNN resolveId errorCode */ + stopGetAddrInfo(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: + /* NNN resolveId hostname ttl addr */ + if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); + try { + clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, + 0, clientId, clientInfo.mResolvedService); + } catch (java.net.UnknownHostException e) { + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + } + stopGetAddrInfo(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + break; + default: + break; } } @@ -579,7 +622,7 @@ public class NsdService extends INsdManager.Stub { return true; } - private boolean registerService(int regId, DnsSdServiceInfo service) { + private boolean registerService(int regId, NsdServiceInfo service) { if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service); try { //Add txtlen and txtdata @@ -637,7 +680,7 @@ public class NsdService extends INsdManager.Stub { return true; } - private boolean resolveService(int resolveId, DnsSdServiceInfo service) { + private boolean resolveService(int resolveId, NsdServiceInfo service) { if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service); try { mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(), @@ -700,49 +743,52 @@ public class NsdService extends INsdManager.Stub { mNsdStateMachine.dump(fd, pw, args); } - private ClientInfo getClientByDiscovery(int discoveryId) { - for (ClientInfo c: mClients.values()) { - if (c.mDiscoveryId == discoveryId) { - return c; - } - } - return null; + /* arg2 on the source message has an id that needs to be retained in replies + * see NsdManager for details */ + private Message obtainMessage(Message srcMsg) { + Message msg = Message.obtain(); + msg.arg2 = srcMsg.arg2; + return msg; } - private ClientInfo getClientByResolve(int resolveId) { - for (ClientInfo c: mClients.values()) { - if (c.mResolveId == resolveId) { - return c; - } - } - return null; + private void replyToMessage(Message msg, int what) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + mReplyChannel.replyToMessage(msg, dstMsg); } - private ClientInfo getClientByRegistration(int regId) { - for (ClientInfo c: mClients.values()) { - if (c.mRegisteredIds.contains(regId)) { - return c; - } - } - return null; + private void replyToMessage(Message msg, int what, int arg1) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + dstMsg.arg1 = arg1; + mReplyChannel.replyToMessage(msg, dstMsg); + } + + private void replyToMessage(Message msg, int what, Object obj) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + dstMsg.obj = obj; + mReplyChannel.replyToMessage(msg, dstMsg); } /* Information tracked per client */ private class ClientInfo { - private static final int MAX_REG = 5; + private static final int MAX_LIMIT = 10; private AsyncChannel mChannel; private Messenger mMessenger; - private int mDiscoveryId; - private int mResolveId; /* Remembers a resolved service until getaddrinfo completes */ - private DnsSdServiceInfo mResolvedService; - private ArrayList<Integer> mRegisteredIds = new ArrayList<Integer>(); + private NsdServiceInfo mResolvedService; + + /* A map from client id to unique id sent to mDns */ + private SparseArray<Integer> mClientIds = new SparseArray<Integer>(); private ClientInfo(AsyncChannel c, Messenger m) { mChannel = c; mMessenger = m; - mDiscoveryId = mResolveId = INVALID_ID; if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); } @@ -751,11 +797,10 @@ public class NsdService extends INsdManager.Stub { StringBuffer sb = new StringBuffer(); sb.append("mChannel ").append(mChannel).append("\n"); sb.append("mMessenger ").append(mMessenger).append("\n"); - sb.append("mDiscoveryId ").append(mDiscoveryId).append("\n"); - sb.append("mResolveId ").append(mResolveId).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); - for(int regId : mRegisteredIds) { - sb.append("regId ").append(regId).append("\n"); + for(int i = 0; i< mClientIds.size(); i++) { + sb.append("clientId ").append(mClientIds.keyAt(i)); + sb.append(" mDnsId ").append(mClientIds.valueAt(i)).append("\n"); } return sb.toString(); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 0f8d151..aa7de82 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1567,6 +1567,31 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + if (code == SYSPROPS_TRANSACTION) { + // We need to tell all apps about the system property change. + ArrayList<IBinder> procs = new ArrayList<IBinder>(); + synchronized(this) { + for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) { + final int NA = apps.size(); + for (int ia=0; ia<NA; ia++) { + ProcessRecord app = apps.valueAt(ia); + if (app.thread != null) { + procs.add(app.thread.asBinder()); + } + } + } + } + + int N = procs.size(); + for (int i=0; i<N; i++) { + Parcel data2 = Parcel.obtain(); + try { + procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null, 0); + } catch (RemoteException e) { + } + data2.recycle(); + } + } try { return super.onTransact(code, data, reply, flags); } catch (RuntimeException e) { @@ -4098,6 +4123,10 @@ public final class ActivityManagerService extends ActivityManagerNative EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN, SystemClock.uptimeMillis()); mWindowManager.enableScreenAfterBoot(); + + synchronized (this) { + updateEventDispatchingLocked(); + } } public void showBootMessage(final CharSequence msg, final boolean always) { @@ -6686,7 +6715,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { mWentToSleep = true; - mWindowManager.setEventDispatching(false); + updateEventDispatchingLocked(); if (!mSleeping) { mSleeping = true; @@ -6712,7 +6741,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { mShuttingDown = true; - mWindowManager.setEventDispatching(false); + updateEventDispatchingLocked(); if (mMainStack.mResumedActivity != null) { mMainStack.stopIfSleepingLocked(); @@ -6776,11 +6805,15 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { mWentToSleep = false; - mWindowManager.setEventDispatching(true); + updateEventDispatchingLocked(); comeOutOfSleepIfNeededLocked(); } } + private void updateEventDispatchingLocked() { + mWindowManager.setEventDispatching(mBooted && !mWentToSleep && !mShuttingDown); + } + public void setLockScreenShown(boolean shown) { if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER) != PackageManager.PERMISSION_GRANTED) { @@ -11049,7 +11082,7 @@ public final class ActivityManagerService extends ActivityManagerNative updateOomAdjLocked(r.app); } int flags = 0; - if (si.deliveryCount > 0) { + if (si.deliveryCount > 1) { flags |= Service.START_FLAG_RETRY; } if (si.doneExecutingCount > 0) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 1e14f5b..c300411 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1794,10 +1794,6 @@ final class ActivityStack { mService.mWindowManager.prepareAppTransition( WindowManagerPolicy.TRANSIT_NONE, keepCurTransition); mNoAnimActivities.add(r); - } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { - mService.mWindowManager.prepareAppTransition( - WindowManagerPolicy.TRANSIT_TASK_OPEN, keepCurTransition); - mNoAnimActivities.remove(r); } else { mService.mWindowManager.prepareAppTransition(newTask ? WindowManagerPolicy.TRANSIT_TASK_OPEN diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java index 2ce7771..c3ecf54 100644 --- a/services/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/java/com/android/server/net/NetworkStatsRecorder.java @@ -26,6 +26,7 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.os.DropBoxManager; import android.util.Log; import android.util.MathUtils; import android.util.Slog; @@ -34,6 +35,7 @@ import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; import com.google.android.collect.Sets; +import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; @@ -43,6 +45,8 @@ import java.lang.ref.WeakReference; import java.util.HashSet; import java.util.Map; +import libcore.io.IoUtils; + /** * Logic to record deltas between periodic {@link NetworkStats} snapshots into * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. @@ -56,8 +60,14 @@ public class NetworkStatsRecorder { private static final boolean LOGD = false; private static final boolean LOGV = false; + private static final String TAG_NETSTATS_DUMP = "netstats_dump"; + + /** Dump before deleting in {@link #recoverFromWtf()}. */ + private static final boolean DUMP_BEFORE_DELETE = true; + private final FileRotator mRotator; private final NonMonotonicObserver<String> mObserver; + private final DropBoxManager mDropBox; private final String mCookie; private final long mBucketDuration; @@ -74,9 +84,10 @@ public class NetworkStatsRecorder { private WeakReference<NetworkStatsCollection> mComplete; public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer, - String cookie, long bucketDuration, boolean onlyTags) { + DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) { mRotator = checkNotNull(rotator, "missing FileRotator"); mObserver = checkNotNull(observer, "missing NonMonotonicObserver"); + mDropBox = checkNotNull(dropBox, "missing DropBoxManager"); mCookie = cookie; mBucketDuration = bucketDuration; @@ -122,6 +133,7 @@ public class NetworkStatsRecorder { mComplete = new WeakReference<NetworkStatsCollection>(complete); } catch (IOException e) { Log.wtf(TAG, "problem completely reading network stats", e); + recoverFromWtf(); } } return complete; @@ -212,6 +224,7 @@ public class NetworkStatsRecorder { mPending.reset(); } catch (IOException e) { Log.wtf(TAG, "problem persisting pending stats", e); + recoverFromWtf(); } } } @@ -226,6 +239,7 @@ public class NetworkStatsRecorder { mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uid)); } catch (IOException e) { Log.wtf(TAG, "problem removing UID " + uid, e); + recoverFromWtf(); } // clear UID from current stats snapshot @@ -355,4 +369,25 @@ public class NetworkStatsRecorder { mSinceBoot.dump(pw); } } + + /** + * Recover from {@link FileRotator} failure by dumping state to + * {@link DropBoxManager} and deleting contents. + */ + private void recoverFromWtf() { + if (DUMP_BEFORE_DELETE) { + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + mRotator.dumpAll(os); + } catch (IOException e) { + // ignore partial contents + os.reset(); + } finally { + IoUtils.closeQuietly(os); + } + mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0); + } + + mRotator.deleteAll(); + } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 1a56b80..e710b33 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -338,9 +338,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStatsRecorder buildRecorder( String prefix, NetworkStatsSettings.Config config, boolean includeTags) { + final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService( + Context.DROPBOX_SERVICE); return new NetworkStatsRecorder(new FileRotator( mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis), - mNonMonotonicObserver, prefix, config.bucketDuration, includeTags); + mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags); } private void shutdownLocked() { diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 4ae3c57..7c14d49 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -1050,7 +1050,7 @@ public class PackageManagerService extends IPackageManager.Stub { mSystemInstallObserver.startWatching(); scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); - + // Collect all vendor packages. mVendorAppDir = new File("/vendor/app"); mVendorInstallObserver = new AppDirObserver( @@ -1068,8 +1068,30 @@ public class PackageManagerService extends IPackageManager.Stub { Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); while (psit.hasNext()) { PackageSetting ps = psit.next(); - if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0 - || mPackages.containsKey(ps.name)) { + + /* + * If this is not a system app, it can't be a + * disable system app. + */ + if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { + continue; + } + + /* + * If the package is scanned, it's not erased. + */ + if (mPackages.containsKey(ps.name)) { + /* + * If the system app is both scanned and in the + * disabled packages list, then it must have been + * added via OTA. Remove it from the currently + * scanned package so the previously user-installed + * application can be scanned. + */ + if (mSettings.isDisabledSystemPackageLPr(ps.name)) { + mPackages.remove(ps.name); + } + continue; } @@ -3096,15 +3118,21 @@ public class PackageManagerService extends IPackageManager.Stub { + "reverting from " + ps.codePathString + ": new version " + pkg.mVersionCode + " better than installed " + ps.versionCode); - InstallArgs args = new FileInstallArgs(ps.codePathString, + InstallArgs args = createInstallArgs(ps.pkgFlags, ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); - args.cleanUpResourcesLI(); - mSettings.enableSystemPackageLPw(ps.name); + synchronized (mInstaller) { + args.cleanUpResourcesLI(); + } + synchronized (mPackages) { + mSettings.enableSystemPackageLPw(ps.name); + } } } } + if (updatedPkg != null) { - // An updated system app will not have the PARSE_IS_SYSTEM flag set initially + // An updated system app will not have the PARSE_IS_SYSTEM flag set + // initially parseFlags |= PackageParser.PARSE_IS_SYSTEM; } // Verify certificates against what was last scanned @@ -3112,6 +3140,49 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName); return null; } + + /* + * A new system app appeared, but we already had a non-system one of the + * same name installed earlier. + */ + boolean shouldHideSystemApp = false; + if (updatedPkg == null && ps != null + && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) { + /* + * Check to make sure the signatures match first. If they don't, + * wipe the installed application and its data. + */ + if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures) + != PackageManager.SIGNATURE_MATCH) { + deletePackageLI(pkg.packageName, true, 0, null, false); + ps = null; + } else { + /* + * If the newly-added system app is an older version than the + * already installed version, hide it. It will be scanned later + * and re-added like an update. + */ + if (pkg.mVersionCode < ps.versionCode) { + shouldHideSystemApp = true; + } else { + /* + * The newly found system app is a newer version that the + * one previously installed. Simply remove the + * already-installed application and replace it with our own + * while keeping the application data. + */ + Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from " + + ps.codePathString + ": new version " + pkg.mVersionCode + + " better than installed " + ps.versionCode); + InstallArgs args = createInstallArgs(ps.pkgFlags, ps.codePathString, + ps.resourcePathString, ps.nativeLibraryPathString); + synchronized (mInstaller) { + args.cleanUpResourcesLI(); + } + } + } + } + // The apk is forward locked (not public) if its code and resources // are kept in different files. // TODO grab this value from PackageSettings @@ -3135,7 +3206,27 @@ public class PackageManagerService extends IPackageManager.Stub { // Set application objects path explicitly. setApplicationInfoPaths(pkg, codePath, resPath); // Note that we invoke the following method only if we are about to unpack an application - return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime); + PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode + | SCAN_UPDATE_SIGNATURE, currentTime); + + /* + * If the system app should be overridden by a previously installed + * data, hide the system app now and let the /data/app scan pick it up + * again. + */ + if (shouldHideSystemApp) { + synchronized (mPackages) { + /* + * We have to grant systems permissions before we hide, because + * grantPermissions will assume the package update is trying to + * expand its permissions. + */ + grantPermissionsLPw(pkg, true); + mSettings.disableSystemPackageLPw(pkg.packageName); + } + } + + return scannedPkg; } private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath, @@ -7177,6 +7268,10 @@ public class PackageManagerService extends IPackageManager.Stub { return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + private static boolean isSystemApp(PackageSetting ps) { + return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + private static boolean isUpdatedSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; } diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index c28cfa2..c4bb519 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -41,7 +41,9 @@ final class InputMonitor implements InputManagerService.Callbacks { private boolean mInputDispatchFrozen; // When true, input dispatch proceeds normally. Otherwise all events are dropped. - private boolean mInputDispatchEnabled = true; + // Initially false, so that input does not get dispatched until boot is finished at + // which point the ActivityManager will enable dispatching. + private boolean mInputDispatchEnabled; // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 2e817ca..5536559 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -85,6 +85,15 @@ public class WindowAnimator { mPolicy = policy; } + void hideWallpapersLocked() { + for (final WindowToken token : mService.mWallpaperTokens) { + for (final WindowState wallpaper : token.windows) { + wallpaper.mWinAnimator.hide(); + } + token.hidden = true; + } + } + private void testWallpaperAndBackgroundLocked() { if (mWindowDetachedWallpaper != mDetachedWallpaper) { if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 8eda9ca..8957edf 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -3430,9 +3430,6 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { WindowToken wtoken = mTokenMap.remove(token); if (wtoken != null) { - if (wtoken.windowType == TYPE_INPUT_METHOD && mInputMethodWindow != null) { - mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); - } boolean delayed = false; if (!wtoken.hidden) { wtoken.hidden = true; @@ -3825,7 +3822,8 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Prepare app transition: transit=" + transit - + " mNextAppTransition=" + mNextAppTransition); + + " mNextAppTransition=" + mNextAppTransition + + "\nCallers=" + Debug.getCallers(3)); if (okToDisplay()) { if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) { @@ -4237,7 +4235,7 @@ public class WindowManagerService extends IWindowManager.Stub e = new RuntimeException(); e.fillInStackTrace(); } - Slog.v(TAG, "setAppVisibility(" + token + ", " + visible + Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible + "): mNextAppTransition=" + mNextAppTransition + " hidden=" + wtoken.hidden + " hiddenRequested=" + wtoken.hiddenRequested, e); @@ -5149,7 +5147,7 @@ public class WindowManagerService extends IWindowManager.Stub //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); Parcel data = Parcel.obtain(); data.writeInterfaceToken("android.ui.ISurfaceComposer"); - surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, + surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED data, null, 0); data.recycle(); } @@ -6673,8 +6671,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2; public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3; - public static final int SET_MOVE_ANIMATION = ANIMATOR_WHAT_OFFSET + 4; - public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 5; + public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 4; private Session mLastReportedHold; @@ -7158,18 +7155,6 @@ public class WindowManagerService extends IWindowManager.Stub break; } - case SET_MOVE_ANIMATION: { - WindowAnimator.SetAnimationParams params = - (WindowAnimator.SetAnimationParams) msg.obj; - WindowStateAnimator winAnimator = params.mWinAnimator; - winAnimator.setAnimation(params.mAnimation); - winAnimator.mAnimDw = params.mAnimDw; - winAnimator.mAnimDh = params.mAnimDh; - - scheduleAnimationLocked(); - break; - } - case CLEAR_PENDING_ACTIONS: { mAnimator.clearPendingActions(); break; @@ -7866,8 +7851,10 @@ public class WindowManagerService extends IWindowManager.Stub mToTopApps.clear(); } + // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper WindowState oldWallpaper = mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() + && !mWallpaperTarget.mWinAnimator.isDummyAnimation() ? null : mWallpaperTarget; adjustWallpaperWindowsLocked(); @@ -8415,9 +8402,6 @@ public class WindowManagerService extends IWindowManager.Stub winAnimator.setAnimation(a); winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; - } else { - winAnimator.mAnimDw = innerDw; - winAnimator.mAnimDh = innerDh; } //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); @@ -9266,6 +9250,15 @@ public class WindowManagerService extends IWindowManager.Stub } } + // It is assumed that this method is called only by InputMethodManagerService. + public void saveLastInputMethodWindowForTransition() { + synchronized (mWindowMap) { + if (mInputMethodWindow != null) { + mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); + } + } + } + @Override public boolean hasNavigationBar() { return mPolicy.hasNavigationBar(); diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 4f08d92..642de73 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -177,6 +177,13 @@ class WindowStateAnimator { || atoken.inPendingTransaction)); } + /** Is the window animating the DummyAnimation? */ + boolean isDummyAnimation() { + final AppWindowToken atoken = mWin.mAppToken; + return atoken != null + && atoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation; + } + /** Is this window currently animating? */ boolean isWindowAnimating() { return mAnimation != null; @@ -363,19 +370,33 @@ class WindowStateAnimator { mWin.mDestroying = true; if (WindowState.SHOW_TRANSACTIONS) WindowManagerService.logSurface( mWin, "HIDE (finishExit)", null); - mSurfaceShown = false; - try { - mSurface.hide(); - } catch (RuntimeException e) { - Slog.w(TAG, "Error hiding surface in " + this, e); - } - mLastHidden = true; + hide(); } mWin.mExiting = false; if (mWin.mRemoveOnExit) { mService.mPendingRemove.add(mWin); mWin.mRemoveOnExit = false; } + if (mService.mWallpaperTarget == mWin) { + mAnimator.hideWallpapersLocked(); + } + } + + void hide() { + if (!mLastHidden) { + //dump(); + mLastHidden = true; + if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, + "HIDE (performLayout)", null); + if (mSurface != null) { + mSurfaceShown = false; + try { + mSurface.hide(); + } catch (RuntimeException e) { + Slog.w(TAG, "Exception hiding surface in " + mWin); + } + } + } } boolean finishDrawingLocked() { @@ -987,20 +1008,7 @@ class WindowStateAnimator { setSurfaceBoundaries(recoveringMemory); if (w.mAttachedHidden || !w.isReadyForDisplay()) { - if (!mLastHidden) { - //dump(); - mLastHidden = true; - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, - "HIDE (performLayout)", null); - if (mSurface != null) { - mSurfaceShown = false; - try { - mSurface.hide(); - } catch (RuntimeException e) { - Slog.w(TAG, "Exception hiding surface in " + w); - } - } - } + hide(); // If we are waiting for this window to handle an // orientation change, well, it is hidden, so // doesn't really matter. Note that this does |