summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server')
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java138
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java2
-rw-r--r--services/java/com/android/server/NsdService.java497
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java41
-rwxr-xr-xservices/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/java/com/android/server/net/NetworkStatsRecorder.java37
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java4
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java111
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java4
-rw-r--r--services/java/com/android/server/wm/WindowAnimator.java9
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java39
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java50
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