summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/app/FragmentManager.java1
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java43
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl4
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl28
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java13
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp10
-rw-r--r--core/res/res/values-mcc204-mnc12/config.xml25
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java12
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java36
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java2
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java138
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java22
-rw-r--r--services/core/jni/Android.mk7
-rw-r--r--services/core/jni/com_android_server_am_ActivityManagerService.cpp151
-rw-r--r--services/core/jni/onload.cpp3
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java46
28 files changed, 575 insertions, 74 deletions
diff --git a/Android.mk b/Android.mk
index 6f5f8f9..9ddb777 100644
--- a/Android.mk
+++ b/Android.mk
@@ -160,6 +160,7 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/fingerprint/IFingerprintDaemon.aidl \
core/java/android/hardware/fingerprint/IFingerprintDaemonCallback.aidl \
core/java/android/hardware/fingerprint/IFingerprintService.aidl \
+ core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl \
core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \
core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \
core/java/android/hardware/hdmi/IHdmiControlService.aidl \
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 3b026d2..132ffef 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2196,6 +2196,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = this;
+ fragment.mHost = mHost;
fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
addFragment(fragment, true);
} else if (fragment.mInLayout) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 7cff11b..1f23c0a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -392,6 +392,18 @@ public class FingerprintManager {
};
/**
+ * @hide
+ */
+ public static abstract class LockoutResetCallback {
+
+ /**
+ * Called when lockout period expired and clients are allowed to listen for fingerprint
+ * again.
+ */
+ public void onLockoutReset() { }
+ };
+
+ /**
* Request authentication of a crypto object. This call warms up the fingerprint hardware
* and starts scanning for a fingerprint. It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
@@ -680,10 +692,37 @@ public class FingerprintManager {
try {
mService.resetTimeout(token);
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
+ Log.v(TAG, "Remote exception in resetTimeout(): ", e);
}
} else {
- Log.w(TAG, "getAuthenticatorId(): Service not connected!");
+ Log.w(TAG, "resetTimeout(): Service not connected!");
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void addLockoutResetCallback(final LockoutResetCallback callback) {
+ if (mService != null) {
+ try {
+ mService.addLockoutResetCallback(
+ new IFingerprintServiceLockoutResetCallback.Stub() {
+
+ @Override
+ public void onLockoutReset(long deviceId) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onLockoutReset();
+ }
+ });
+ }
+ });
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
+ }
+ } else {
+ Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
}
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 3356354..690a751 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,6 +17,7 @@ package android.hardware.fingerprint;
import android.os.Bundle;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.hardware.fingerprint.Fingerprint;
import java.util.List;
@@ -71,4 +72,7 @@ interface IFingerprintService {
// Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
void resetTimeout(in byte [] cryptoToken);
+
+ // Add a callback which gets notified when the fingerprint lockout period expired.
+ void addLockoutResetCallback(IFingerprintServiceLockoutResetCallback callback);
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl
new file mode 100644
index 0000000..c9a5d59
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.fingerprint;
+
+import android.hardware.fingerprint.Fingerprint;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+/**
+ * Callback when lockout period expired and clients are allowed to authenticate again.
+ * @hide
+ */
+oneway interface IFingerprintServiceLockoutResetCallback {
+ void onLockoutReset(long deviceId);
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d24b10b..a3a01da 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1174,7 +1174,7 @@ public class LockPatternUtils {
* @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
*/
public void requireCredentialEntry(int userId) {
- requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
+ requireStrongAuth(StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
}
/**
@@ -1251,7 +1251,7 @@ public class LockPatternUtils {
value = { STRONG_AUTH_NOT_REQUIRED,
STRONG_AUTH_REQUIRED_AFTER_BOOT,
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
- SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
+ STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST})
@Retention(RetentionPolicy.SOURCE)
public @interface StrongAuthFlags {}
@@ -1266,14 +1266,14 @@ public class LockPatternUtils {
public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
/**
- * Strong authentication is required because a device admin has requested it.
+ * Strong authentication is required because a device admin has temporarily requested it.
*/
public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
/**
- * Some authentication is required because the user has temporarily disabled trust.
+ * Strong authentication is required because the user has temporarily requested it.
*/
- public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
+ public static final int STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
/**
* Strong authentication is required because the user has been locked out after too many
@@ -1282,7 +1282,6 @@ public class LockPatternUtils {
public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
- private static final int ALLOWING_FINGERPRINT = SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
@@ -1324,7 +1323,7 @@ public class LockPatternUtils {
* current strong authentication requirements.
*/
public boolean isFingerprintAllowedForUser(int userId) {
- return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
+ return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
}
/**
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4c920dc..b431a3f 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -83,6 +83,14 @@ static void SigChldHandler(int /*signal_number*/) {
pid_t pid;
int status;
+ // It's necessary to save and restore the errno during this function.
+ // Since errno is stored per thread, changing it here modifies the errno
+ // on the thread on which this signal handler executes. If a signal occurs
+ // between a call and an errno check, it's possible to get the errno set
+ // here.
+ // See b/23572286 for extra information.
+ int saved_errno = errno;
+
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
// Log process-death status that we care about. In general it is
// not safe to call LOG(...) from a signal handler because of
@@ -118,6 +126,8 @@ static void SigChldHandler(int /*signal_number*/) {
if (pid < 0 && errno != ECHILD) {
ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
}
+
+ errno = saved_errno;
}
// Configures the SIGCHLD handler for the zygote process. This is configured
diff --git a/core/res/res/values-mcc204-mnc12/config.xml b/core/res/res/values-mcc204-mnc12/config.xml
new file mode 100644
index 0000000..80432d7
--- /dev/null
+++ b/core/res/res/values-mcc204-mnc12/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>20408</item>
+ </string-array>
+</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index ce2d11a..f51e10f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -64,7 +64,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
@Override
protected void resetState() {
- mPasswordEntry.setEnabled(true);
+ setPasswordEntryEnabled(true);
}
@Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fc6117f..cfc232c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,6 +29,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.graphics.Bitmap;
+import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -472,6 +473,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
+ private void handleFingerprintLockoutReset() {
+ updateFingerprintListeningState();
+ }
+
private void setFingerprintRunningState(int fingerprintRunningState) {
boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
@@ -681,6 +686,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
};
+ private final FingerprintManager.LockoutResetCallback mLockoutResetCallback
+ = new FingerprintManager.LockoutResetCallback() {
+ @Override
+ public void onLockoutReset() {
+ handleFingerprintLockoutReset();
+ }
+ };
+
private FingerprintManager.AuthenticationCallback mAuthenticationCallback
= new AuthenticationCallback() {
@@ -1003,6 +1016,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
updateFingerprintListeningState();
+ if (mFpm != null) {
+ mFpm.addLockoutResetCallback(mLockoutResetCallback);
+ }
}
private void updateFingerprintListeningState() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index c14f215..eecac63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1636,11 +1636,13 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void handleVisibleToUserChanged(boolean visibleToUser) {
try {
if (visibleToUser) {
- boolean clearNotificationEffects = !isPanelFullyCollapsed() &&
- (mShowLockscreenNotifications ||
- (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED));
+ boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
+ boolean clearNotificationEffects =
+ ((mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD) ||
+ (!pinnedHeadsUp && (mState == StatusBarState.SHADE
+ || mState == StatusBarState.SHADE_LOCKED)));
int notificationLoad = mNotificationData.getActiveNotifications().size();
- if (mHeadsUpManager.hasPinnedHeadsUp() && isPanelFullyCollapsed()) {
+ if (pinnedHeadsUp && isPanelFullyCollapsed()) {
notificationLoad = 1;
} else {
MetricsLogger.histogram(mContext, "note_load", notificationLoad);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index d30411a..f4439bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -262,14 +262,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
+ /**
+ * Resolves the intent to launch the camera application.
+ */
+ public ResolveInfo resolveCameraIntent() {
+ return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
+ PackageManager.MATCH_DEFAULT_ONLY,
+ KeyguardUpdateMonitor.getCurrentUser());
+ }
+
private void updateCameraVisibility() {
if (mCameraImageView == null) {
// Things are not set up yet; reply hazy, ask again later
return;
}
- ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
- PackageManager.MATCH_DEFAULT_ONLY,
- KeyguardUpdateMonitor.getCurrentUser());
+ ResolveInfo resolved = resolveCameraIntent();
boolean visible = !isCameraDisabledByDpm() && resolved != null
&& getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
&& mUserSetupComplete;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 93ecb06..d0a7f8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -166,10 +166,13 @@ public class LockIcon extends KeyguardAffordanceView {
if (mAccessibilityController == null) {
return;
}
+ boolean trustManagedOrFingerprintAllowed = mUnlockMethodCache.isTrustManaged()
+ || KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed();
+
boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
- boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
+ boolean clickToForceLock = trustManagedOrFingerprintAllowed
&& !mAccessibilityController.isAccessibilityEnabled();
- boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
+ boolean longClickToForceLock = trustManagedOrFingerprintAllowed
&& !clickToForceLock;
setClickable(clickToForceLock || clickToUnlock);
setLongClickable(longClickToForceLock);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 950b162..310625e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -78,6 +78,13 @@ public class NotificationGroupManager {
Notification notif = sbn.getNotification();
String groupKey = sbn.getGroupKey();
final NotificationGroup group = mGroupMap.get(groupKey);
+ if (group == null) {
+ // When an app posts 2 different notifications as summary of the same group, then a
+ // cancellation of the first notification removes this group.
+ // This situation is not supported and we will not allow such notifications anymore in
+ // the close future. See b/23676310 for reference.
+ return;
+ }
if (notif.isGroupSummary()) {
group.summary = null;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5557f9c..b93586e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -21,7 +21,10 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -61,6 +64,8 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
+import java.util.List;
+
public class NotificationPanelView extends PanelView implements
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
@@ -2425,7 +2430,28 @@ public class NotificationPanelView extends PanelView implements
getCenterIcon().setLaunchingAffordance(launchingAffordance);
}
- public boolean canCameraGestureBeLaunched() {
- return !mAfforanceHelper.isSwipingInProgress();
+ /**
+ * Whether the camera application can be launched for the camera launch gesture.
+ *
+ * @param keyguardIsShowing whether keyguard is being shown
+ */
+ public boolean canCameraGestureBeLaunched(boolean keyguardIsShowing) {
+ ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent();
+ String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
+ ? null : resolveInfo.activityInfo.packageName;
+ return packageToLaunch != null &&
+ (keyguardIsShowing || !isForegroundApp(packageToLaunch)) &&
+ !mAfforanceHelper.isSwipingInProgress();
+ }
+
+ /**
+ * Return true if the applications with the package name is running in foreground.
+ *
+ * @param pkgName application package name.
+ */
+ private boolean isForegroundApp(String pkgName) {
+ ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+ return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 8063bbe..55b1127 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3742,12 +3742,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// down on the lockscreen), clear notification LED, vibration,
// ringing.
// Other transitions are covered in handleVisibleToUserChanged().
- if (state != mState && mVisible && state == StatusBarState.SHADE_LOCKED) {
- try {
- mBarService.clearNotificationEffects();
- } catch (RemoteException e) {
- // Ignore.
- }
+ if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED
+ || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) {
+ clearNotificationEffects();
}
mState = state;
mGroupManager.setStatusBarState(state);
@@ -4090,7 +4087,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void onCameraLaunchGestureDetected() {
- if (!mNotificationPanel.canCameraGestureBeLaunched()) {
+ if (!mNotificationPanel.canCameraGestureBeLaunched(
+ mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) {
return;
}
if (!mDeviceInteractive) {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index d58d372..e3d5d38 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -177,7 +177,7 @@ class AlarmManagerService extends SystemService {
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
- private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = 60*1000;
+ private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 191bf99..3738d1e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -400,6 +400,17 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final int PERSISTENT_MASK =
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
+
+ // Delay to disable app launch boost
+ static final int APP_BOOST_MESSAGE_DELAY = 3000;
+ // Lower delay than APP_BOOST_MESSAGE_DELAY to disable the boost
+ static final int APP_BOOST_TIMEOUT = 2500;
+
+ private static native int nativeMigrateToBoost();
+ private static native int nativeMigrateFromBoost();
+ private boolean mIsBoosted = false;
+ private long mBoostStartTime = 0;
+
/** All system services */
SystemServiceManager mSystemServiceManager;
@@ -1356,6 +1367,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int REPORT_TIME_TRACKER_MSG = 55;
static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
+ static final int APP_BOOST_DEACTIVATE_MSG = 58;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2031,6 +2043,20 @@ public final class ActivityManagerService extends ActivityManagerNative
// it is finished we make sure it is reset to its default.
mUserIsMonkey = false;
} break;
+ case APP_BOOST_DEACTIVATE_MSG : {
+ synchronized(ActivityManagerService.this) {
+ if (mIsBoosted) {
+ if (mBoostStartTime < (SystemClock.uptimeMillis() - APP_BOOST_TIMEOUT)) {
+ nativeMigrateFromBoost();
+ mIsBoosted = false;
+ mBoostStartTime = 0;
+ } else {
+ Message newmsg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
+ mHandler.sendMessageDelayed(newmsg, APP_BOOST_TIMEOUT);
+ }
+ }
+ }
+ } break;
}
}
};
@@ -3114,6 +3140,16 @@ public final class ActivityManagerService extends ActivityManagerNative
app = null;
}
+ // app launch boost for big.little configurations
+ // use cpusets to migrate freshly launched tasks to big cores
+ synchronized(ActivityManagerService.this) {
+ nativeMigrateToBoost();
+ mIsBoosted = true;
+ mBoostStartTime = SystemClock.uptimeMillis();
+ Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
+ mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
+ }
+
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a956c56..960cbf1 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -509,7 +509,7 @@ public final class BroadcastQueue {
break;
}
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
- if (appOp != r.appOp
+ if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.mAppOpsService.noteOperation(appOp,
filter.receiverList.uid, filter.packageName)
!= AppOpsManager.MODE_ALLOWED) {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7e46db8..67c9ee8 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -18,13 +18,18 @@ package com.android.server.fingerprint;
import android.Manifest;
import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.app.IUserSwitchObserver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.os.Binder;
+import android.os.DeadObjectException;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
@@ -51,8 +56,8 @@ import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintDaemon;
import android.hardware.fingerprint.IFingerprintDaemonCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.view.Display;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
import static android.Manifest.permission.USE_FINGERPRINT;
@@ -60,6 +65,7 @@ import static android.Manifest.permission.USE_FINGERPRINT;
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -83,12 +89,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
private ClientMonitor mAuthClient = null;
private ClientMonitor mEnrollClient = null;
private ClientMonitor mRemoveClient = null;
+ private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
+ new ArrayList<>();
private final AppOpsManager mAppOps;
private static final long MS_PER_SEC = 1000;
private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
private static final int MAX_FAILED_ATTEMPTS = 5;
private static final int FINGERPRINT_ACQUIRED_GOOD = 0;
+ private final String mKeyguardPackage;
Handler mHandler = new Handler() {
@Override
@@ -121,6 +130,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
public FingerprintService(Context context) {
super(context);
mContext = context;
+ mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
+ com.android.internal.R.string.config_keyguardComponent)).getPackageName();
mAppOps = context.getSystemService(AppOpsManager.class);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
}
@@ -259,6 +270,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
// If we're asked to reset failed attempts externally (i.e. from Keyguard), the runnable
// may still be in the queue; remove it.
mHandler.removeCallbacks(mLockoutReset);
+ notifyLockoutResetMonitors();
}
private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
@@ -493,10 +505,67 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
return false;
}
- private boolean canUseFingerprint(String opPackageName) {
+ private boolean isForegroundActivity(int uid, int pid) {
+ try {
+ List<RunningAppProcessInfo> procs =
+ ActivityManagerNative.getDefault().getRunningAppProcesses();
+ int N = procs.size();
+ for (int i = 0; i < N; i++) {
+ RunningAppProcessInfo proc = procs.get(i);
+ if (proc.pid == pid && proc.uid == uid
+ && proc.importance == IMPORTANCE_FOREGROUND) {
+ return true;
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "am.getRunningAppProcesses() failed");
+ }
+ return false;
+ }
+
+ /**
+ * @param opPackageName name of package for caller
+ * @param foregroundOnly only allow this call while app is in the foreground
+ * @return true if caller can use fingerprint API
+ */
+ private boolean canUseFingerprint(String opPackageName, boolean foregroundOnly) {
checkPermission(USE_FINGERPRINT);
- return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(),
- opPackageName) == AppOpsManager.MODE_ALLOWED;
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+ if (opPackageName.equals(mKeyguardPackage)) {
+ return true; // Keyguard is always allowed
+ }
+ if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {
+ Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile");
+ return false;
+ }
+ if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.v(TAG, "Rejecting " + opPackageName + " ; permission denied");
+ return false;
+ }
+ if (foregroundOnly && !isForegroundActivity(uid, pid)) {
+ Slog.v(TAG, "Rejecting " + opPackageName + " ; not in foreground");
+ return false;
+ }
+ return true;
+ }
+
+ private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) {
+ if (!mLockoutMonitors.contains(monitor)) {
+ mLockoutMonitors.add(monitor);
+ }
+ }
+
+ private void removeLockoutResetCallback(
+ FingerprintServiceLockoutResetMonitor monitor) {
+ mLockoutMonitors.remove(monitor);
+ }
+
+ private void notifyLockoutResetMonitors() {
+ for (int i = 0; i < mLockoutMonitors.size(); i++) {
+ mLockoutMonitors.get(i).sendLockoutReset();
+ }
}
private class ClientMonitor implements IBinder.DeathRecipient {
@@ -614,7 +683,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
FingerprintUtils.vibrateFingerprintSuccess(getContext());
}
result |= true; // we have a valid fingerprint
- mLockoutReset.run();
+ mHandler.post(mLockoutReset);
}
return result;
}
@@ -654,6 +723,36 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
}
}
+ private class FingerprintServiceLockoutResetMonitor {
+
+ private final IFingerprintServiceLockoutResetCallback mCallback;
+
+ public FingerprintServiceLockoutResetMonitor(
+ IFingerprintServiceLockoutResetCallback callback) {
+ mCallback = callback;
+ }
+
+ public void sendLockoutReset() {
+ if (mCallback != null) {
+ try {
+ mCallback.onLockoutReset(mHalDeviceId);
+ } catch (DeadObjectException e) {
+ Slog.w(TAG, "Death object while invoking onLockoutReset: ", e);
+ mHandler.post(mRemoveCallbackRunnable);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
+ }
+ }
+ }
+
+ private final Runnable mRemoveCallbackRunnable = new Runnable() {
+ @Override
+ public void run() {
+ removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
+ }
+ };
+ }
+
private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {
@Override
@@ -782,12 +881,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags,
final String opPackageName) {
- if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {
- Slog.w(TAG, "Can't authenticate non-current user");
- return;
- }
- if (!canUseFingerprint(opPackageName)) {
- Slog.w(TAG, "Calling not granted permission to use fingerprint");
+ if (!canUseFingerprint(opPackageName, true /* foregroundOnly */)) {
return;
}
@@ -807,7 +901,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
@Override // Binder call
public void cancelAuthentication(final IBinder token, String opPackageName) {
- if (!canUseFingerprint(opPackageName)) {
+ if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
return;
}
mHandler.post(new Runnable() {
@@ -838,7 +932,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
@Override // Binder call
public boolean isHardwareDetected(long deviceId, String opPackageName) {
- if (!canUseFingerprint(opPackageName)) {
+ if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
return false;
}
return mHalDeviceId != 0;
@@ -862,7 +956,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
@Override // Binder call
public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
- if (!canUseFingerprint(opPackageName)) {
+ if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
return Collections.emptyList();
}
int effectiveUserId = getEffectiveUserId(userId);
@@ -872,7 +966,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
@Override // Binder call
public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
- if (!canUseFingerprint(opPackageName)) {
+ if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
return false;
}
@@ -922,7 +1016,19 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
public void resetTimeout(byte [] token) {
checkPermission(RESET_FINGERPRINT_LOCKOUT);
// TODO: confirm security token when we move timeout management into the HAL layer.
- mLockoutReset.run();
+ mHandler.post(mLockoutReset);
+ }
+
+ @Override
+ public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)
+ throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ addLockoutResetMonitor(
+ new FingerprintServiceLockoutResetMonitor(callback));
+ }
+ });
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d7c9c02..34737c1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4417,7 +4417,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mAppsToBeHidden.isEmpty()) {
if (dismissKeyguard && !mKeyguardSecure) {
mAppsThatDismissKeyguard.add(appToken);
- } else if (win.isDrawnLw()) {
+ } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
mWinShowWhenLocked = win;
mHideLockScreen = true;
mForceStatusBarFromKeyguard = false;
@@ -4451,7 +4451,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWinDismissingKeyguard = win;
mSecureDismissingKeyguard = mKeyguardSecure;
mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
- } else if (mAppsToBeHidden.isEmpty() && showWhenLocked && win.isDrawnLw()) {
+ } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
+ && (win.isDrawnLw() || win.hasAppShownWindows())) {
if (DEBUG_LAYOUT) Slog.v(TAG,
"Setting mHideLockScreen to true by win " + win);
mHideLockScreen = true;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 794b49c..985bbfb 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -375,7 +375,10 @@ public class TaskStack {
for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
- mService.removeWindowInnerLocked(appWindows.get(winNdx));
+ // We are in the middle of changing the state of displays/stacks/tasks. We need
+ // to finish that, before we let layout interfere with it.
+ mService.removeWindowInnerLocked(appWindows.get(winNdx),
+ false /* performLayout */);
doAnotherLayoutPass = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 36cb7f2..e903e4f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2793,6 +2793,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
void removeWindowInnerLocked(WindowState win) {
+ removeWindowInnerLocked(win, true);
+ }
+
+ void removeWindowInnerLocked(WindowState win, boolean performLayout) {
if (win.mRemoved) {
// Nothing to do.
return;
@@ -2890,7 +2894,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (displayContent != null) {
displayContent.layoutNeeded = true;
}
- performLayoutAndPlaceSurfacesLocked();
+ if (performLayout) {
+ performLayoutAndPlaceSurfacesLocked();
+ }
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
}
@@ -5193,7 +5199,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
public void removeStack(int stackId) {
- mStackIdToStack.remove(stackId);
+ synchronized (mWindowMap) {
+ mStackIdToStack.remove(stackId);
+ }
}
public void removeTask(int taskId) {
@@ -5267,10 +5275,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
public void getStackBounds(int stackId, Rect bounds) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack != null) {
- stack.getBounds(bounds);
- return;
+ synchronized (mWindowMap) {
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack != null) {
+ stack.getBounds(bounds);
+ return;
+ }
}
bounds.setEmpty();
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 9556b08..98d8d08 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -4,9 +4,16 @@ LOCAL_REL_DIR := core/jni
LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
+ifneq ($(ENABLE_CPUSETS),)
+ifneq ($(ENABLE_SCHED_BOOST),)
+LOCAL_CFLAGS += -DUSE_SCHED_BOOST
+endif
+endif
+
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_am_ActivityManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
diff --git a/services/core/jni/com_android_server_am_ActivityManagerService.cpp b/services/core/jni/com_android_server_am_ActivityManagerService.cpp
new file mode 100644
index 0000000..52217b9
--- /dev/null
+++ b/services/core/jni/com_android_server_am_ActivityManagerService.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ActivityManagerService"
+//#define LOG_NDEBUG 0
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+
+#include <ScopedLocalRef.h>
+#include <ScopedPrimitiveArray.h>
+
+#include <cutils/log.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android
+{
+
+ // migrate from foreground to foreground_boost
+ static jint migrateToBoost(JNIEnv *env, jobject _this)
+ {
+#ifdef USE_SCHED_BOOST
+ // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error
+ FILE* fg_cpuset_file = NULL;
+ int boost_cpuset_fd = 0;
+ if (!access("/dev/cpuset/tasks", F_OK)) {
+ fg_cpuset_file = fopen("/dev/cpuset/foreground/tasks", "r+");
+ if (ferror(fg_cpuset_file)) {
+ return 0;
+ }
+ boost_cpuset_fd = open("/dev/cpuset/foreground/boost/tasks", O_WRONLY);
+ if (boost_cpuset_fd < 0) {
+ fclose(fg_cpuset_file);
+ return 0;
+ }
+
+ }
+ if (!fg_cpuset_file || !boost_cpuset_fd) {
+ fclose(fg_cpuset_file);
+ close(boost_cpuset_fd);
+ return 0;
+ }
+ char buf[17];
+ while (fgets(buf, 16, fg_cpuset_file)) {
+ int i = 0;
+ for (; i < 16; i++) {
+ if (buf[i] == '\n') {
+ buf[i] = 0;
+ break;
+ }
+ }
+ if (write(boost_cpuset_fd, buf, i) < 0) {
+ // ignore error
+ }
+ if (feof(fg_cpuset_file))
+ break;
+ }
+ fclose(fg_cpuset_file);
+ close(boost_cpuset_fd);
+#endif
+ return 0;
+ }
+
+ // migrate from foreground_boost to foreground
+ static jint migrateFromBoost(JNIEnv *env, jobject _this)
+ {
+#ifdef USE_SCHED_BOOST
+ // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error
+ int fg_cpuset_fd = 0;
+ FILE* boost_cpuset_file = NULL;
+ if (!access("/dev/cpuset/tasks", F_OK)) {
+ boost_cpuset_file = fopen("/dev/cpuset/foreground/boost/tasks", "r+");
+ if (ferror(boost_cpuset_file)) {
+ return 0;
+ }
+ fg_cpuset_fd = open("/dev/cpuset/foreground/tasks", O_WRONLY);
+ if (fg_cpuset_fd < 0) {
+ fclose(boost_cpuset_file);
+ return 0;
+ }
+
+ }
+ if (!boost_cpuset_file || !fg_cpuset_fd) {
+ fclose(boost_cpuset_file);
+ close(fg_cpuset_fd);
+ return 0;
+ }
+ char buf[17];
+ char *curBuf = buf;
+ while (fgets(buf, 16, boost_cpuset_file)) {
+ //ALOGE("Appending FD %s to fg", buf);
+ int i = 0;
+ for (; i < 16; i++) {
+ if (buf[i] == '\n') {
+ buf[i] = 0;
+ break;
+ }
+ }
+ if (write(fg_cpuset_fd, buf, i) < 0) {
+ //ALOGE("Appending FD %s to fg ERROR", buf);
+ // handle error?
+ }
+ if (feof(boost_cpuset_file))
+ break;
+ }
+
+ close(fg_cpuset_fd);
+ fclose(boost_cpuset_file);
+
+#endif
+ return 0;
+
+ }
+
+
+ static JNINativeMethod method_table[] = {
+ { "nativeMigrateToBoost", "()I", (void*)migrateToBoost },
+ { "nativeMigrateFromBoost", "()I", (void*)migrateFromBoost },
+ };
+
+ int register_android_server_ActivityManagerService(JNIEnv *env)
+ {
+ return jniRegisterNativeMethods(env, "com/android/server/am/ActivityManagerService",
+ method_table, NELEM(method_table));
+ }
+
+}
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 67872da..1f3fde6 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -20,6 +20,7 @@
#include "utils/misc.h"
namespace android {
+int register_android_server_ActivityManagerService(JNIEnv* env);
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_AssetAtlasService(JNIEnv* env);
int register_android_server_BatteryStatsService(JNIEnv* env);
@@ -57,6 +58,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
}
ALOG_ASSERT(env, "Could not retrieve the env!");
+ register_android_server_ActivityManagerService(env);
register_android_server_PowerManagerService(env);
register_android_server_SerialService(env);
register_android_server_InputApplicationHandle(env);
@@ -80,5 +82,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_PersistentDataBlockService(env);
register_android_server_Watchdog(env);
+
return JNI_VERSION_1_4;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6a0bf64..df8affe 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -404,6 +404,15 @@ public class CarrierConfigManager {
public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
+ /**
+ * Determines whether the carrier supports making non-emergency phone calls while the phone is
+ * in emergency callback mode. Default value is {@code true}, meaning that non-emergency calls
+ * are allowed in emergency callback mode.
+ * @hide
+ */
+ public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL =
+ "allow_non_emergency_calls_in_ecm_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -496,6 +505,7 @@ public class CarrierConfigManager {
sDefaults.putString(KEY_MMS_UA_PROF_TAG_NAME_STRING, "x-wap-profile");
sDefaults.putString(KEY_MMS_UA_PROF_URL_STRING, "");
sDefaults.putString(KEY_MMS_USER_AGENT_STRING, "");
+ sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true);
}
/**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 1f3802e..689e359 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -36,8 +36,8 @@ import com.android.util.Pair;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.annotation.Nullable;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -139,8 +139,9 @@ public final class BridgeContext extends Context {
private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
- // cache for TypedArray generated from IStyleResourceValue object
- private Map<int[], Map<Integer, BridgeTypedArray>> mTypedArrayCache;
+ // cache for TypedArray generated from StyleResourceValue object
+ private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>
+ mTypedArrayCache;
private BridgeInflater mBridgeInflater;
private BridgeContentResolver mContentResolver;
@@ -621,31 +622,38 @@ public final class BridgeContext extends Context {
}
}
+ // The map is from
+ // attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array.
if (mTypedArrayCache == null) {
- mTypedArrayCache = new HashMap<int[], Map<Integer,BridgeTypedArray>>();
-
- Map<Integer, BridgeTypedArray> map = new HashMap<Integer, BridgeTypedArray>();
- mTypedArrayCache.put(attrs, map);
-
- BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs);
- map.put(resid, ta);
-
- return ta;
+ mTypedArrayCache = new IdentityHashMap<int[],
+ Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>();
}
// get the 2nd map
- Map<Integer, BridgeTypedArray> map = mTypedArrayCache.get(attrs);
- if (map == null) {
- map = new HashMap<Integer, BridgeTypedArray>();
- mTypedArrayCache.put(attrs, map);
+ Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 =
+ mTypedArrayCache.get(attrs);
+ if (map2 == null) {
+ map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>();
+ mTypedArrayCache.put(attrs, map2);
+ }
+
+ // get the 3rd map
+ List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
+ Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes);
+ if (map3 == null) {
+ map3 = new HashMap<Integer, BridgeTypedArray>();
+ // Create a copy of the list before adding it to the map. This allows reusing the
+ // existing list.
+ currentThemes = new ArrayList<StyleResourceValue>(currentThemes);
+ map2.put(currentThemes, map3);
}
- // get the array from the 2nd map
- BridgeTypedArray ta = map.get(resid);
+ // get the array from the 3rd map
+ BridgeTypedArray ta = map3.get(resid);
if (ta == null) {
ta = createStyleBasedTypedArray(style, attrs);
- map.put(resid, ta);
+ map3.put(resid, ta);
}
return ta;