Merge "Injecting system calls into alarm manager"
diff --git a/Android.bp b/Android.bp
index dd49a67..2ab91a1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -381,6 +381,7 @@
"core/java/com/android/internal/backup/IBackupTransport.aidl",
"core/java/com/android/internal/backup/IObbBackupService.aidl",
"core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
+ "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
"core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
"core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
"core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
@@ -554,6 +555,7 @@
"telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
"telephony/java/com/android/internal/telephony/ISms.aidl",
"telephony/java/com/android/internal/telephony/ISub.aidl",
+ "telephony/java/com/android/internal/telephony/IAnas.aidl",
"telephony/java/com/android/internal/telephony/ITelephony.aidl",
"telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
"telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index 66a2600d..d8d4a6e 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -23,8 +23,7 @@
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal.CallSession;
-
-import java.util.Random;
+import com.android.internal.os.CachedDeviceState;
import org.junit.After;
import org.junit.Before;
@@ -32,8 +31,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertNull;
-
/**
* Performance tests for {@link BinderCallsStats}
@@ -49,6 +46,8 @@
@Before
public void setUp() {
mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
+ CachedDeviceState deviceState = new CachedDeviceState(false, false);
+ mBinderCallsStats.setDeviceState(deviceState.getReadonlyClient());
}
@After
diff --git a/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java
new file mode 100644
index 0000000..0f880b7
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 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.os;
+
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.os.LooperStats;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Performance tests for {@link LooperStats}.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class LooperStatsPerfTest {
+ private static final int DISTINCT_MESSAGE_COUNT = 1000;
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ private LooperStats mStats;
+ private CachedDeviceState mDeviceState;
+ private HandlerThread mThread;
+ private Message[] mMessages = new Message[DISTINCT_MESSAGE_COUNT];
+
+ @Before
+ public void setUp() {
+ mStats = new LooperStats(1, DISTINCT_MESSAGE_COUNT - 1);
+ mDeviceState = new CachedDeviceState(false, false);
+ mStats.setDeviceState(mDeviceState.getReadonlyClient());
+ // The tests are all single-threaded. HandlerThread is created to allow creating Handlers.
+ mThread = new HandlerThread("UnusedThread");
+ mThread.start();
+ for (int i = 0; i < DISTINCT_MESSAGE_COUNT; i++) {
+ mMessages[i] = mThread.getThreadHandler().obtainMessage(i);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ mThread.quit();
+ }
+
+ @Test
+ public void timeHundredPercentSampling() {
+ mStats.setSamplingInterval(1);
+ runScenario();
+ }
+
+ @Test
+ public void timeOnePercentSampling() {
+ mStats.setSamplingInterval(100);
+ runScenario();
+ }
+
+ @Test
+ public void timeCollectionDisabled() {
+ // We do not collect data on charger.
+ mDeviceState.setCharging(true);
+ runScenario();
+ }
+
+ private void runScenario() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < DISTINCT_MESSAGE_COUNT; i++) {
+ Object token = mStats.messageDispatchStarting();
+ mStats.messageDispatched(token, mMessages[i]);
+ }
+ }
+ }
+}
diff --git a/api/current.txt b/api/current.txt
index 8bdafa9..7389855 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -13986,6 +13986,8 @@
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
method public android.graphics.Shader getShader();
+ method public float getStrikeThruPosition();
+ method public float getStrikeThruThickness();
method public android.graphics.Paint.Cap getStrokeCap();
method public android.graphics.Paint.Join getStrokeJoin();
method public float getStrokeMiter();
@@ -14006,6 +14008,9 @@
method public int getTextWidths(java.lang.String, int, int, float[]);
method public int getTextWidths(java.lang.String, float[]);
method public android.graphics.Typeface getTypeface();
+ method public float getUnderlinePosition();
+ method public float getUnderlineThickness();
+ method public float getWordSpacing();
method public android.graphics.Xfermode getXfermode();
method public boolean hasGlyph(java.lang.String);
method public final boolean isAntiAlias();
@@ -14057,6 +14062,7 @@
method public void setTextSkewX(float);
method public android.graphics.Typeface setTypeface(android.graphics.Typeface);
method public void setUnderlineText(boolean);
+ method public void setWordSpacing(float);
method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
@@ -42617,6 +42623,7 @@
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
method public static int getDefaultVoiceSubscriptionId();
+ method public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions(int);
method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
method public boolean isNetworkRoaming(int);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
@@ -45986,6 +45993,7 @@
method public float getDimension(android.util.DisplayMetrics);
method public final float getFloat();
method public float getFraction(float, float);
+ method public boolean isColorType();
method public void setTo(android.util.TypedValue);
field public static final int COMPLEX_MANTISSA_MASK = 16777215; // 0xffffff
field public static final int COMPLEX_MANTISSA_SHIFT = 8; // 0x8
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 02719e3f8..45e38cf 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -152,8 +152,8 @@
Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V
Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V
Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V
-Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;Landroid/view/InputChannel;)V
-Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;)Z
+Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;ILandroid/view/InputChannel;)V
+Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;I)Z
Landroid/view/IWindowManager;->endProlongedAnimations()V
Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V
Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;Z)V
diff --git a/core/java/android/accessibilityservice/TEST_MAPPING b/core/java/android/accessibilityservice/TEST_MAPPING
new file mode 100644
index 0000000..c7c4c3a
--- /dev/null
+++ b/core/java/android/accessibilityservice/TEST_MAPPING
@@ -0,0 +1,23 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases"
+ },
+ {
+ "name": "CtsAccessibilityTestCases"
+ }
+ ]
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1108f93..225b6cf 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -615,6 +615,13 @@
public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
/**
+ * Value for {@link #privateFlags}: whether this app is signed with the
+ * platform key.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+
+ /**
* Value for {@link #privateFlags}: whether this app is pre-installed on the
* google partition of the system image.
* @hide
@@ -622,11 +629,11 @@
public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
/**
- * Value for {@link #privateFlags}: whether this app is signed with the
- * platform key.
+ * Indicates whether this package requires access to non-SDK APIs.
+ * Only system apps and tests are allowed to use this property.
* @hide
*/
- public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+ public static final int PRIVATE_FLAG_USES_NON_SDK_API = 1 << 22;
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
@@ -1009,13 +1016,6 @@
public String appComponentFactory;
/**
- * Indicates whether this package requires access to non-SDK APIs. Only system apps
- * and tests are allowed to use this property.
- * @hide
- */
- public boolean usesNonSdkApi;
-
- /**
* The category of this app. Categories are used to cluster multiple apps
* together into meaningful groups, such as when summarizing battery,
* network, or disk usage. Apps should only define this value when they fit
@@ -1294,6 +1294,7 @@
pw.println(prefix + "category=" + category);
}
pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
+ pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
}
super.dumpBack(pw, prefix);
}
@@ -1718,11 +1719,18 @@
return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
}
+ /**
+ * @hide
+ */
+ public boolean usesNonSdkApi() {
+ return (privateFlags & PRIVATE_FLAG_USES_NON_SDK_API) != 0;
+ }
+
private boolean isAllowedToUseHiddenApis() {
if (isSignedWithPlatformKey()) {
return true;
} else if (isSystemApp() || isUpdatedSystemApp()) {
- return usesNonSdkApi || isPackageWhitelistedForHiddenApis();
+ return usesNonSdkApi() || isPackageWhitelistedForHiddenApis();
} else {
return false;
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8b058dc..6d49362 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3659,8 +3659,10 @@
ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
}
- ai.usesNonSdkApi = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false);
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
+ ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
+ }
if (outError[0] == null) {
CharSequence pname;
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 2c7e51a..00a1f6f 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -35,6 +35,7 @@
import android.view.inputmethod.InputMethodSession;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputContext;
@@ -60,7 +61,7 @@
private static final String TAG = "InputMethodWrapper";
private static final int DO_DUMP = 1;
- private static final int DO_ATTACH_TOKEN = 10;
+ private static final int DO_INITIALIZE_INTERNAL = 10;
private static final int DO_SET_INPUT_CONTEXT = 20;
private static final int DO_UNSET_INPUT_CONTEXT = 30;
private static final int DO_START_INPUT = 32;
@@ -159,9 +160,15 @@
args.recycle();
return;
}
-
- case DO_ATTACH_TOKEN: {
- inputMethod.attachToken((IBinder)msg.obj);
+
+ case DO_INITIALIZE_INTERNAL: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ inputMethod.initializeInternal((IBinder) args.arg1,
+ (IInputMethodPrivilegedOperations) args.arg2);
+ } finally {
+ args.recycle();
+ }
return;
}
case DO_SET_INPUT_CONTEXT: {
@@ -246,8 +253,9 @@
@BinderThread
@Override
- public void attachToken(IBinder token) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
+ public void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_INITIALIZE_INTERNAL, token, privOps));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 9295bb7..ea7d42e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -42,6 +42,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.provider.Settings;
@@ -79,6 +80,9 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -342,7 +346,8 @@
private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING;
InputMethodManager mImm;
-
+ private IInputMethodPrivilegedOperations mPrivOps;
+
@UnsupportedAppUsage
int mTheme = 0;
@@ -446,14 +451,32 @@
public class InputMethodImpl extends AbstractInputMethodImpl {
/**
* {@inheritDoc}
+ * @hide
+ */
+ @MainThread
+ @Override
+ public final void initializeInternal(IBinder token,
+ IInputMethodPrivilegedOperations privilegedOperations) {
+ if (mToken != null) {
+ throw new IllegalStateException("initializeInternal() must be called at most once."
+ + " privOps=" + privilegedOperations);
+ }
+ mPrivOps = privilegedOperations;
+ attachToken(token);
+ }
+
+ /**
+ * {@inheritDoc}
*/
@MainThread
@Override
public void attachToken(IBinder token) {
- if (mToken == null) {
- mToken = token;
- mWindow.setToken(token);
+ if (mToken != null) {
+ throw new IllegalStateException(
+ "attachToken() must be called at most once. token=" + token);
}
+ mToken = token;
+ mWindow.setToken(token);
}
/**
@@ -468,9 +491,7 @@
mInputConnection = binding.getConnection();
if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
+ " ic=" + mInputConnection);
- if (mImm != null && mToken != null) {
- mImm.reportFullscreenMode(mToken, mIsFullscreen);
- }
+ reportFullscreenMode();
initialize();
onBindInput();
}
@@ -519,7 +540,11 @@
public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
@NonNull IBinder startInputToken) {
- mImm.reportStartInput(mToken, startInputToken);
+ try {
+ mPrivOps.reportStartInput(startInputToken);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
// This needs to be dispatched to interface methods rather than doStartInput().
// Otherwise IME developers who have overridden those interface methods will lose
@@ -561,8 +586,8 @@
}
clearInsetOfPreviousIme();
// If user uses hard keyboard, IME button should always be shown.
- mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()),
- mBackDisposition);
+ setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+
if (resultReceiver != null) {
resultReceiver.send(wasVis != isInputViewShown()
? InputMethodManager.RESULT_SHOWN
@@ -581,6 +606,17 @@
}
}
+ private void setImeWindowStatus(int visibilityFlags, int backDisposition) {
+ if (mPrivOps == null) {
+ return;
+ }
+ try {
+ mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Concrete implementation of
* {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
@@ -1037,8 +1073,7 @@
}
// If user uses hard keyboard, IME button should always be shown.
boolean showing = onEvaluateInputViewShown();
- mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
- mBackDisposition);
+ setImeWindowStatus(IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition);
}
}
@@ -1088,7 +1123,7 @@
return;
}
mBackDisposition = disposition;
- mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+ setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
}
/**
@@ -1186,7 +1221,18 @@
public EditorInfo getCurrentInputEditorInfo() {
return mInputEditorInfo;
}
-
+
+ private void reportFullscreenMode() {
+ if (mPrivOps == null) {
+ return;
+ }
+ try {
+ mPrivOps.reportFullscreenMode(mIsFullscreen);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Re-evaluate whether the input method should be running in fullscreen
* mode, and update its UI if this has changed since the last time it
@@ -1201,9 +1247,7 @@
if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
changed = true;
mIsFullscreen = isFullscreen;
- if (mImm != null && mToken != null) {
- mImm.reportFullscreenMode(mToken, mIsFullscreen);
- }
+ reportFullscreenMode();
mFullscreenApplied = true;
initialize();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
@@ -1821,7 +1865,7 @@
final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());
if (previousImeWindowStatus != nextImeWindowStatus) {
- mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
+ setImeWindowStatus(nextImeWindowStatus, mBackDisposition);
}
if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
if (DEBUG) Log.v(TAG, "showWindow: showing!");
@@ -1846,7 +1890,7 @@
}
private void doHideWindow() {
- mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
+ setImeWindowStatus(0, mBackDisposition);
hideWindow();
}
@@ -1887,11 +1931,31 @@
+ " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
if (!mShouldClearInsetOfPreviousIme) return;
- mImm.clearLastInputMethodWindowForTransition(mToken);
+ clearLastInputMethodWindowForTransition();
mShouldClearInsetOfPreviousIme = false;
}
/**
+ * Tells the system that the IME decided to not show a window and the system no longer needs to
+ * use the previous IME's inset.
+ *
+ * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
+ * is the only expected caller of this method. Do not depend on this anywhere else.</p>
+ *
+ * <p>TODO: We probably need to reconsider how IME should be handled.</p>
+ */
+ private void clearLastInputMethodWindowForTransition() {
+ if (mPrivOps == null) {
+ return;
+ }
+ try {
+ mPrivOps.clearLastInputMethodWindowForTransition();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Called when a new client has bound to the input method. This
* may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
* and {@link #onFinishInput()} calls as the user navigates through its
@@ -2804,7 +2868,40 @@
if (getCurrentInputConnection() != inputConnection) {
return;
}
- mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo());
+ exposeContentInternal(inputContentInfo, getCurrentInputEditorInfo());
+ }
+
+ /**
+ * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+ * permission to the content.
+ *
+ * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
+ * InputConnection)} for details.</p>
+ *
+ * @param inputContentInfo Content to be temporarily exposed from the input method to the
+ * application.
+ * This cannot be {@code null}.
+ * @param editorInfo The editor that receives {@link InputContentInfo}.
+ */
+ private void exposeContentInternal(@NonNull InputContentInfo inputContentInfo,
+ @NonNull EditorInfo editorInfo) {
+ if (mPrivOps == null) {
+ return;
+ }
+ final IInputContentUriToken uriToken;
+ final Uri contentUri = inputContentInfo.getContentUri();
+ try {
+ uriToken = mPrivOps.createInputContentUriToken(contentUri, editorInfo.packageName);
+ if (uriToken == null) {
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
+ + " packageName=" + editorInfo.packageName, e);
+ return;
+ }
+ inputContentInfo.setUriToken(uriToken);
+ return;
}
private static int mapToImeWindowStatus(boolean isInputViewShown) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 71938d2..e007398 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7256,6 +7256,14 @@
private static final Validator DOZE_REACH_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
+ * Gesture that wakes up the display, showing the ambient version of the status bar.
+ * @hide
+ */
+ public static final String DOZE_WAKE_SCREEN_GESTURE = "doze_wake_screen_gesture";
+
+ private static final Validator DOZE_WAKE_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
* The current night mode that has been selected by the user. Owned
* and controlled by UiModeManagerService. Constants are as per
* UiModeManager.
@@ -8158,6 +8166,7 @@
DOZE_PICK_UP_GESTURE,
DOZE_DOUBLE_TAP_GESTURE,
DOZE_REACH_GESTURE,
+ DOZE_WAKE_SCREEN_GESTURE,
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
@@ -8302,6 +8311,7 @@
VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
VALIDATORS.put(DOZE_REACH_GESTURE, DOZE_REACH_GESTURE_VALIDATOR);
+ VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
@@ -13310,6 +13320,19 @@
public static final String BINDER_CALLS_STATS = "binder_calls_stats";
/**
+ * Looper stats settings.
+ *
+ * The following strings are supported as keys:
+ * <pre>
+ * enabled (boolean)
+ * sampling_interval (int)
+ * </pre>
+ *
+ * @hide
+ */
+ public static final String LOOPER_STATS = "looper_stats";
+
+ /**
* Default user id to boot into. They map to user ids, for example, 10, 11, 12.
*
* @hide
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 2c9bb66..9640173 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -232,6 +232,16 @@
};
/**
+ * Determine if a value is a color by comparing {@link type} to {@link #TYPE_FIRST_COLOR_INT}
+ * and {@link #TYPE_LAST_COLOR_INT}.
+ *
+ * @return true if this value is a color
+ */
+ public boolean isColorType() {
+ return (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT);
+ }
+
+ /**
* Retrieve the base value from a complex data integer. This uses the
* {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of
* the data to compute a floating point representation of the number they
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c205af0..bfe1e95 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -391,15 +391,16 @@
void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber);
/**
- * Create an input consumer by name.
+ * Create an input consumer by name and display id.
*/
- void createInputConsumer(IBinder token, String name, out InputChannel inputChannel);
+ void createInputConsumer(IBinder token, String name, int displayId,
+ out InputChannel inputChannel);
/**
- * Destroy an input consumer by name. This method will also dispose the input channels
- * associated with that InputConsumer.
+ * Destroy an input consumer by name and display id.
+ * This method will also dispose the input channels associated with that InputConsumer.
*/
- boolean destroyInputConsumer(String name);
+ boolean destroyInputConsumer(String name, int displayId);
/**
* Return the touch region for the current IME window, or an empty region if there is none.
diff --git a/core/java/android/view/accessibility/TEST_MAPPING b/core/java/android/view/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..d2bd6ea
--- /dev/null
+++ b/core/java/android/view/accessibility/TEST_MAPPING
@@ -0,0 +1,53 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsUiAutomationTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.accessibility"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases"
+ },
+ {
+ "name": "CtsUiAutomationTestCases"
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.accessibility"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java
index 7104a28..0d0fea6 100644
--- a/core/java/android/view/inputmethod/InputContentInfo.java
+++ b/core/java/android/view/inputmethod/InputContentInfo.java
@@ -183,7 +183,15 @@
@Nullable
public Uri getLinkUri() { return mLinkUri; }
- void setUriToken(IInputContentUriToken token) {
+ /**
+ * Update the internal state of this object to be associated with the given token.
+ *
+ * <p>TODO(yukawa): Come up with an idea to make {@link InputContentInfo} immutable.</p>
+ *
+ * @param token special URI token obtained from the system.
+ * @hide
+ */
+ public void setUriToken(IInputContentUriToken token) {
if (mUriToken != null) {
throw new IllegalStateException("URI token is already set");
}
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index ab8886b..f45507c 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -25,6 +25,8 @@
import android.os.IBinder;
import android.os.ResultReceiver;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+
/**
* The InputMethod interface represents an input method which can generate key
* events and text, such as digital, email addresses, CJK characters, other
@@ -79,17 +81,35 @@
public interface SessionCallback {
public void sessionCreated(InputMethodSession session);
}
-
+
+ /**
+ * Called first thing after an input method is created, this supplies a
+ * unique token for the session it has with the system service as well as
+ * IPC endpoint to do some other privileged operations.
+ *
+ * @param token special token for the system to identify
+ * {@link InputMethodService}
+ * @param privilegedOperations IPC endpoint to do some privileged
+ * operations that are allowed only to the
+ * current IME.
+ * @hide
+ */
+ @MainThread
+ default void initializeInternal(IBinder token,
+ IInputMethodPrivilegedOperations privilegedOperations) {
+ attachToken(token);
+ }
+
/**
* Called first thing after an input method is created, this supplies a
* unique token for the session it has with the system service. It is
* needed to identify itself with the service to validate its operations.
* This token <strong>must not</strong> be passed to applications, since
* it grants special priviledges that should not be given to applications.
- *
- * <p>Note: to protect yourself from malicious clients, you should only
- * accept the first token given to you. Any after that may come from the
- * client.
+ *
+ * <p>The system guarantees that this method is called back between
+ * {@link InputMethodService#onCreate()} and {@link InputMethodService#onDestroy()}
+ * at most once.
*/
@MainThread
public void attachToken(IBinder token);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d3fd0cf..baac4cd 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -29,7 +29,6 @@
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -56,7 +55,6 @@
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.autofill.AutofillManager;
-import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputConnectionWrapper;
import com.android.internal.view.IInputContext;
@@ -810,24 +808,6 @@
}
/** @hide */
- public void setImeWindowStatus(IBinder imeToken, int vis, int backDisposition) {
- try {
- mService.setImeWindowStatus(imeToken, vis, backDisposition);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** @hide */
- public void reportStartInput(IBinder imeToken, IBinder startInputToken) {
- try {
- mService.reportStartInput(imeToken, startInputToken);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /** @hide */
@UnsupportedAppUsage
public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
try {
@@ -859,17 +839,6 @@
}
/**
- * @hide
- */
- public void reportFullscreenMode(IBinder token, boolean fullscreen) {
- try {
- mService.reportFullscreenMode(token, fullscreen);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Return true if the given view is the currently active view for the
* input method.
*/
@@ -2333,7 +2302,13 @@
}
/**
- * @return The current height of the input method window.
+ * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
+ *
+ * <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
+ * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
+ * started relying on it.</p>
+ *
+ * @return Something that is not well-defined.
* @hide
*/
@UnsupportedAppUsage
@@ -2348,28 +2323,6 @@
}
/**
- * Tells the system that the IME decided to not show a window and the system no longer needs to
- * use the previous IME's inset.
- *
- * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
- * is the only expected caller of this method. Do not depend on this anywhere else.</p>
- *
- * <p>TODO: We probably need to reconsider how IME should be handled.</p>
- * @hide
- * @param token Supplies the identifying token given to an input method when it was started,
- * which allows it to perform this operation on itself.
- */
- public void clearLastInputMethodWindowForTransition(final IBinder token) {
- synchronized (mH) {
- try {
- mService.clearLastInputMethodWindowForTransition(token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
* Force switch to the last used input method and subtype. If the last input method didn't have
* any subtypes, the framework will simply switch to the last input method with no subtype
* specified.
@@ -2507,40 +2460,6 @@
}
}
- /**
- * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
- * permission to the content.
- *
- * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
- * InputConnection)} for details.</p>
- *
- * @param token Supplies the identifying token given to an input method when it was started,
- * which allows it to perform this operation on itself.
- * @param inputContentInfo Content to be temporarily exposed from the input method to the
- * application.
- * This cannot be {@code null}.
- * @param editorInfo The editor that receives {@link InputContentInfo}.
- * @hide
- */
- public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
- @NonNull EditorInfo editorInfo) {
- final IInputContentUriToken uriToken;
- final Uri contentUri = inputContentInfo.getContentUri();
- try {
- uriToken = mService.createInputContentUriToken(token, contentUri,
- editorInfo.packageName);
- if (uriToken == null) {
- return;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
- + " packageName=" + editorInfo.packageName, e);
- return;
- }
- inputContentInfo.setUriToken(uriToken);
- return;
- }
-
void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
final Printer p = new PrintWriterPrinter(fout);
p.println("Input method client state for " + this + ":");
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 8728367..cb282b6 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -75,6 +75,15 @@
return !TextUtils.isEmpty(reachSensorType());
}
+ public boolean wakeScreenGestureEnabled(int user) {
+ return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
+ && wakeScreenGestureAvailable();
+ }
+
+ public boolean wakeScreenGestureAvailable() {
+ return !TextUtils.isEmpty(wakeScreenSensorType());
+ }
+
public String doubleTapSensorType() {
return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
}
@@ -87,6 +96,10 @@
return mContext.getResources().getString(R.string.config_dozeReachSensorType);
}
+ public String wakeScreenSensorType() {
+ return mContext.getResources().getString(R.string.config_dozeWakeScreenSensorType);
+ }
+
public boolean pulseOnLongPressEnabled(int user) {
return pulseOnLongPressAvailable() && boolSettingDefaultOff(
Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
new file mode 100644
index 0000000..449b4a5
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.inputmethod;
+
+import android.net.Uri;
+
+import com.android.internal.inputmethod.IInputContentUriToken;
+
+/**
+ * Defines priviledged operations that only the current IME is allowed to call.
+ * Actual operations are implemented and handled by InputMethodManagerService.
+ */
+interface IInputMethodPrivilegedOperations {
+ void setImeWindowStatus(int vis, int backDisposition);
+ void reportStartInput(in IBinder startInputToken);
+ void clearLastInputMethodWindowForTransition();
+ IInputContentUriToken createInputContentUriToken(in Uri contentUri, in String packageName);
+ void reportFullscreenMode(boolean fullscreen);
+}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 4aa30f6..c0c358d 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -16,16 +16,9 @@
package com.android.internal.os;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
import android.os.Binder;
-import android.os.OsProtoEnums;
-import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateFormat;
@@ -37,7 +30,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BinderInternal.CallSession;
-import com.android.server.LocalServices;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
@@ -63,7 +55,6 @@
private static final String TAG = "BinderCallsStats";
private static final int CALL_SESSIONS_POOL_SIZE = 100;
- private static final int PERIODIC_SAMPLING_INTERVAL = 10;
private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
@@ -81,25 +72,7 @@
private final Random mRandom;
private long mStartTime = System.currentTimeMillis();
- // State updated by the broadcast receiver below.
- private boolean mScreenInteractive;
- private boolean mCharging;
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case Intent.ACTION_BATTERY_CHANGED:
- mCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
- break;
- case Intent.ACTION_SCREEN_ON:
- mScreenInteractive = true;
- break;
- case Intent.ACTION_SCREEN_OFF:
- mScreenInteractive = false;
- break;
- }
- }
- };
+ private CachedDeviceState.Readonly mDeviceState;
/** Injector for {@link BinderCallsStats}. */
public static class Injector {
@@ -112,65 +85,14 @@
this.mRandom = injector.getRandomGenerator();
}
- public void systemReady(Context context) {
- registerBroadcastReceiver(context);
- setInitialState(queryScreenInteractive(context), queryIsCharging());
- }
-
- /**
- * Listens for screen/battery state changes.
- */
- @VisibleForTesting
- public void registerBroadcastReceiver(Context context) {
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- context.registerReceiver(mBroadcastReceiver, filter);
- }
-
- /**
- * Sets the battery/screen initial state.
- *
- * This has to be updated *after* the broadcast receiver is installed.
- */
- @VisibleForTesting
- public void setInitialState(boolean isScreenInteractive, boolean isCharging) {
- this.mScreenInteractive = isScreenInteractive;
- this.mCharging = isCharging;
- // Data collected previously was not accurate since the battery/screen state was not set.
- reset();
- }
-
- private boolean queryIsCharging() {
- final BatteryManagerInternal batteryManager =
- LocalServices.getService(BatteryManagerInternal.class);
- if (batteryManager == null) {
- Slog.wtf(TAG, "BatteryManager null while starting BinderCallsStatsService");
- // Default to true to not collect any data.
- return true;
- } else {
- return batteryManager.getPlugType() != OsProtoEnums.BATTERY_PLUGGED_NONE;
- }
- }
-
- private boolean queryScreenInteractive(Context context) {
- final PowerManager powerManager = context.getSystemService(PowerManager.class);
- final boolean screenInteractive;
- if (powerManager == null) {
- Slog.wtf(TAG, "PowerManager null while starting BinderCallsStatsService",
- new Throwable());
- return true;
- } else {
- return powerManager.isInteractive();
- }
+ public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
+ mDeviceState = deviceState;
}
@Override
@Nullable
public CallSession callStarted(Binder binder, int code) {
- if (mCharging) {
+ if (mDeviceState == null || mDeviceState.isCharging()) {
return null;
}
@@ -221,7 +143,7 @@
synchronized (mLock) {
// This was already checked in #callStart but check again while synchronized.
- if (mCharging) {
+ if (mDeviceState == null || mDeviceState.isCharging()) {
return;
}
@@ -233,7 +155,7 @@
uidEntry.recordedCallCount++;
final CallStat callStat = uidEntry.getOrCreate(
- s.binderClass, s.transactionCode, mScreenInteractive);
+ s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
callStat.callCount++;
callStat.recordedCallCount++;
callStat.cpuTimeMicros += duration;
@@ -252,7 +174,7 @@
// Only record the total call count if we already track data for this key.
// It helps to keep the memory usage down when sampling is enabled.
final CallStat callStat = uidEntry.get(
- s.binderClass, s.transactionCode, mScreenInteractive);
+ s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
if (callStat != null) {
callStat.callCount++;
}
@@ -319,13 +241,13 @@
public ArrayList<ExportedCallStat> getExportedCallStats() {
// We do not collect all the data if detailed tracking is off.
if (!mDetailedTracking) {
- return new ArrayList<ExportedCallStat>();
+ return new ArrayList<>();
}
ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
synchronized (mLock) {
final int uidEntriesSize = mUidEntries.size();
- for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++){
+ for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++) {
final UidEntry entry = mUidEntries.valueAt(entryIdx);
for (CallStat stat : entry.getCallStatsList()) {
ExportedCallStat exported = new ExportedCallStat();
@@ -387,13 +309,15 @@
}
}
- public void dump(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+ /** Writes the collected statistics to the supplied {@link PrintWriter}.*/
+ public void dump(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap, boolean verbose) {
synchronized (mLock) {
dumpLocked(pw, appIdToPkgNameMap, verbose);
}
}
- private void dumpLocked(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+ private void dumpLocked(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap,
+ boolean verbose) {
long totalCallsCount = 0;
long totalRecordedCallsCount = 0;
long totalCpuTime = 0;
@@ -450,13 +374,13 @@
for (UidEntry entry : summaryEntries) {
String uidStr = uidToString(entry.uid, appIdToPkgNameMap);
pw.println(String.format(" %10d %3.0f%% %8d %8d %s",
- entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
- entry.recordedCallCount, entry.callCount, uidStr));
+ entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
+ entry.recordedCallCount, entry.callCount, uidStr));
}
pw.println();
pw.println(String.format(" Summary: total_cpu_time=%d, "
- + "calls_count=%d, avg_call_cpu_time=%.0f",
- totalCpuTime, totalCallsCount, (double)totalCpuTime / totalRecordedCallsCount));
+ + "calls_count=%d, avg_call_cpu_time=%.0f",
+ totalCpuTime, totalCallsCount, (double) totalCpuTime / totalRecordedCallsCount));
pw.println();
pw.println("Exceptions thrown (exception_count, class_name):");
@@ -723,11 +647,6 @@
return result;
}
- @VisibleForTesting
- public BroadcastReceiver getBroadcastReceiver() {
- return mBroadcastReceiver;
- }
-
private static int compareByCpuDesc(
ExportedCallStat a, ExportedCallStat b) {
return Long.compare(b.cpuTimeMicros, a.cpuTimeMicros);
diff --git a/core/java/com/android/internal/os/CachedDeviceState.java b/core/java/com/android/internal/os/CachedDeviceState.java
new file mode 100644
index 0000000..8c90682
--- /dev/null
+++ b/core/java/com/android/internal/os/CachedDeviceState.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.os;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Stores the device state (e.g. charging/on battery, screen on/off) to be shared with
+ * the System Server telemetry services.
+ *
+ * @hide
+ */
+public class CachedDeviceState {
+ private volatile boolean mScreenInteractive;
+ private volatile boolean mCharging;
+
+ public CachedDeviceState() {
+ mCharging = true;
+ mScreenInteractive = false;
+ }
+
+ @VisibleForTesting
+ public CachedDeviceState(boolean isCharging, boolean isScreenInteractive) {
+ mCharging = isCharging;
+ mScreenInteractive = isScreenInteractive;
+ }
+
+ public void setScreenInteractive(boolean screenInteractive) {
+ mScreenInteractive = screenInteractive;
+ }
+
+ public void setCharging(boolean charging) {
+ mCharging = charging;
+ }
+
+ public Readonly getReadonlyClient() {
+ return new CachedDeviceState.Readonly();
+ }
+
+ /**
+ * Allows for only a readonly access to the device state.
+ */
+ public class Readonly {
+ public boolean isCharging() {
+ return mCharging;
+ }
+
+ public boolean isScreenInteractive() {
+ return mScreenInteractive;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index edf475f..02a8b22 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -37,31 +37,30 @@
*/
public class LooperStats implements Looper.Observer {
private static final int TOKEN_POOL_SIZE = 50;
- private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
- private static final int DEFAULT_SAMPLING_INTERVAL = 100;
@GuardedBy("mLock")
- private final SparseArray<Entry> mEntries = new SparseArray<>(256);
+ private final SparseArray<Entry> mEntries = new SparseArray<>(512);
private final Object mLock = new Object();
private final Entry mOverflowEntry = new Entry("OVERFLOW");
private final Entry mHashCollisionEntry = new Entry("HASH_COLLISION");
private final ConcurrentLinkedQueue<DispatchSession> mSessionPool =
new ConcurrentLinkedQueue<>();
- private final int mSamplingInterval;
private final int mEntriesSizeCap;
-
- public LooperStats() {
- this(DEFAULT_SAMPLING_INTERVAL, DEFAULT_ENTRIES_SIZE_CAP);
- }
+ private int mSamplingInterval;
+ private CachedDeviceState.Readonly mDeviceState;
public LooperStats(int samplingInterval, int entriesSizeCap) {
this.mSamplingInterval = samplingInterval;
this.mEntriesSizeCap = entriesSizeCap;
}
+ public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
+ mDeviceState = deviceState;
+ }
+
@Override
public Object messageDispatchStarting() {
- if (shouldCollectDetailedData()) {
+ if (deviceStateAllowsCollection() && shouldCollectDetailedData()) {
DispatchSession session = mSessionPool.poll();
session = session == null ? new DispatchSession() : session;
session.startTimeMicro = getElapsedRealtimeMicro();
@@ -74,6 +73,10 @@
@Override
public void messageDispatched(Object token, Message msg) {
+ if (!deviceStateAllowsCollection()) {
+ return;
+ }
+
DispatchSession session = (DispatchSession) token;
Entry entry = getOrCreateEntry(msg);
synchronized (entry) {
@@ -94,6 +97,10 @@
@Override
public void dispatchingThrewException(Object token, Message msg, Exception exception) {
+ if (!deviceStateAllowsCollection()) {
+ return;
+ }
+
DispatchSession session = (DispatchSession) token;
Entry entry = getOrCreateEntry(msg);
synchronized (entry) {
@@ -102,6 +109,11 @@
recycleSession(session);
}
+ private boolean deviceStateAllowsCollection() {
+ // Do not collect data if on charger or the state is not set.
+ return mDeviceState != null && !mDeviceState.isCharging();
+ }
+
/** Returns an array of {@link ExportedEntry entries} with the aggregated statistics. */
public List<ExportedEntry> getEntries() {
final ArrayList<ExportedEntry> entries;
@@ -142,9 +154,14 @@
}
}
+ public void setSamplingInterval(int samplingInterval) {
+ mSamplingInterval = samplingInterval;
+ }
+
@NonNull
private Entry getOrCreateEntry(Message msg) {
- final int id = Entry.idFor(msg);
+ final boolean isInteractive = mDeviceState.isScreenInteractive();
+ final int id = Entry.idFor(msg, isInteractive);
Entry entry;
synchronized (mLock) {
entry = mEntries.get(id);
@@ -153,14 +170,14 @@
// If over the size cap, track totals under a single entry.
return mOverflowEntry;
}
- entry = new Entry(msg);
+ entry = new Entry(msg, isInteractive);
mEntries.put(id, entry);
}
}
if (entry.handler.getClass() != msg.getTarget().getClass()
- || entry.handler.getLooper().getThread()
- != msg.getTarget().getLooper().getThread()) {
+ || entry.handler.getLooper().getThread() != msg.getTarget().getLooper().getThread()
+ || entry.isInteractive != isInteractive) {
// If a hash collision happened, track totals under a single entry.
return mHashCollisionEntry;
}
@@ -194,6 +211,7 @@
private static class Entry {
public final Handler handler;
public final String messageName;
+ public final boolean isInteractive;
public long messageCount;
public long recordedMessageCount;
public long exceptionCount;
@@ -202,14 +220,16 @@
public long cpuUsageMicro;
public long maxCpuUsageMicro;
- Entry(Message msg) {
- handler = msg.getTarget();
- messageName = handler.getMessageName(msg);
+ Entry(Message msg, boolean isInteractive) {
+ this.handler = msg.getTarget();
+ this.messageName = handler.getMessageName(msg);
+ this.isInteractive = isInteractive;
}
Entry(String specialEntryName) {
- handler = null;
- messageName = specialEntryName;
+ this.messageName = specialEntryName;
+ this.handler = null;
+ this.isInteractive = false;
}
void reset() {
@@ -222,10 +242,11 @@
maxCpuUsageMicro = 0;
}
- static int idFor(Message msg) {
+ static int idFor(Message msg, boolean isInteractive) {
int result = 7;
result = 31 * result + msg.getTarget().getLooper().getThread().hashCode();
result = 31 * result + msg.getTarget().getClass().hashCode();
+ result = 31 * result + (isInteractive ? 1231 : 1237);
if (msg.getCallback() != null) {
return 31 * result + msg.getCallback().getClass().hashCode();
} else {
@@ -239,6 +260,7 @@
public final String handlerClassName;
public final String threadName;
public final String messageName;
+ public final boolean isInteractive;
public final long messageCount;
public final long recordedMessageCount;
public final long exceptionCount;
@@ -256,6 +278,7 @@
this.handlerClassName = "";
this.threadName = "";
}
+ this.isInteractive = entry.isInteractive;
this.messageName = entry.messageName;
this.messageCount = entry.messageCount;
this.recordedMessageCount = entry.recordedMessageCount;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 189c8d5..d4c4ab3 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -16,9 +16,6 @@
package com.android.internal.view;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.SomeArgs;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
@@ -37,6 +34,9 @@
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
import android.view.inputmethod.InputContentInfo;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
public abstract class IInputConnectionWrapper extends IInputContext.Stub {
private static final String TAG = "IInputConnectionWrapper";
private static final boolean DEBUG = false;
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 5b29f4c..b6a654a 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -22,6 +22,7 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.IInputSessionCallback;
@@ -32,7 +33,7 @@
* {@hide}
*/
oneway interface IInputMethod {
- void attachToken(IBinder token);
+ void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps);
void bindInput(in InputBinding binding);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 4b004e2..c08c871 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -16,13 +16,12 @@
package com.android.internal.view;
-import android.net.Uri;
import android.os.ResultReceiver;
import android.text.style.SuggestionSpan;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.EditorInfo;
-import com.android.internal.inputmethod.IInputContentUriToken;
+
import com.android.internal.view.InputBindResult;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -69,8 +68,6 @@
void hideMySoftInput(in IBinder token, int flags);
void showMySoftInput(in IBinder token, int flags);
void updateStatusIcon(in IBinder token, String packageName, int iconId);
- void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
- void reportStartInput(in IBinder token, in IBinder startInputToken);
void registerSuggestionSpansForNotification(in SuggestionSpan[] spans);
boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
InputMethodSubtype getCurrentInputMethodSubtype();
@@ -79,13 +76,9 @@
boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme);
boolean shouldOfferSwitchingToNextInputMethod(in IBinder token);
void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
+ // This is kept due to @UnsupportedAppUsage.
+ // TODO(Bug 113914148): Consider removing this.
int getInputMethodWindowVisibleHeight();
- void clearLastInputMethodWindowForTransition(in IBinder token);
-
- IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri,
- in String packageName);
-
- void reportFullscreenMode(in IBinder token, boolean fullscreen);
oneway void notifyUserAction(int sequenceNumber);
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index f1bd63b..1257336 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -271,7 +271,7 @@
optional .android.graphics.RectProto containing_frame = 8 [deprecated=true];
optional .android.graphics.RectProto parent_frame = 9 [deprecated=true];
optional .android.graphics.RectProto content_frame = 10 [deprecated=true];
- optional .android.graphics.RectProto content_insets = 11;
+ optional .android.graphics.RectProto content_insets = 11 [deprecated=true];
optional .android.graphics.RectProto surface_insets = 12;
optional WindowStateAnimatorProto animator = 13;
optional bool animating_exit = 14;
@@ -288,10 +288,10 @@
optional .android.graphics.RectProto visible_frame = 26 [deprecated=true];
optional .android.graphics.RectProto decor_frame = 27 [deprecated=true];
optional .android.graphics.RectProto outset_frame = 28 [deprecated=true];
- optional .android.graphics.RectProto overscan_insets = 29;
- optional .android.graphics.RectProto visible_insets = 30;
- optional .android.graphics.RectProto stable_insets = 31;
- optional .android.graphics.RectProto outsets = 32;
+ optional .android.graphics.RectProto overscan_insets = 29 [deprecated=true];
+ optional .android.graphics.RectProto visible_insets = 30 [deprecated=true];
+ optional .android.graphics.RectProto stable_insets = 31 [deprecated=true];
+ optional .android.graphics.RectProto outsets = 32 [deprecated=true];
optional .android.view.DisplayCutoutProto cutout = 33 [deprecated=true];
optional bool remove_on_exit = 34;
optional bool destroying = 35;
@@ -380,4 +380,9 @@
optional .android.graphics.RectProto parent_frame = 8;
optional .android.graphics.RectProto visible_frame = 9;
optional .android.view.DisplayCutoutProto cutout = 10;
+ optional .android.graphics.RectProto content_insets = 11;
+ optional .android.graphics.RectProto overscan_insets = 12;
+ optional .android.graphics.RectProto visible_insets = 13;
+ optional .android.graphics.RectProto stable_insets = 14;
+ optional .android.graphics.RectProto outsets = 15;
}
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 3308128..13f6bce 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -40,7 +40,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=3</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index bb0d4d5..d45b91a 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -38,7 +38,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=3</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 1241a9d..b520d5d 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -41,7 +41,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 232f149..650aa62 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -28,7 +28,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 1d2e625..4bb68dc 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -24,7 +24,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index ef1ecd2..11bfa05 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -43,7 +43,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=2</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cf1320c..235f85b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2116,6 +2116,9 @@
<!-- Type of the reach sensor. Empty if reach is not supported. -->
<string name="config_dozeReachSensorType" translatable="false"></string>
+ <!-- Type of the wake up sensor. Empty if not supported. -->
+ <string name="config_dozeWakeScreenSensorType" translatable="false"></string>
+
<!-- Control whether the always on display mode is available. This should only be enabled on
devices where the display has been tuned to be power efficient in DOZE and/or DOZE_SUSPEND
states. -->
@@ -2793,7 +2796,7 @@
<item>SUPL_PORT=7275</item>
<item>SUPL_VER=0x20000</item>
<item>SUPL_MODE=1</item>
- <item>SUPL_ES=0</item>
+ <item>SUPL_ES=1</item>
<item>LPP_PROFILE=0</item>
<item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
<item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 48c263e..92cca72 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3462,4 +3462,5 @@
<java-symbol type="integer" name="db_wal_truncate_size" />
<java-symbol type="integer" name="config_wakeUpDelayDoze" />
+ <java-symbol type="string" name="config_dozeWakeScreenSensorType" />
</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 517cf4d..e84aed1 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -282,6 +282,7 @@
Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
Settings.Global.LOCK_SOUND,
+ Settings.Global.LOOPER_STATS,
Settings.Global.LOW_BATTERY_SOUND,
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
Settings.Global.LOW_POWER_MODE,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
index 3c04895..3e03414 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
@@ -40,7 +40,7 @@
// and assertAccessibilityEventCleared
/** The number of properties of the {@link AccessibilityEvent} class. */
- private static final int A11Y_EVENT_NON_STATIC_FIELD_COUNT = 32;
+ private static final int A11Y_EVENT_NON_STATIC_FIELD_COUNT = 33;
// The number of fields tested in the corresponding CTS AccessibilityRecordTest:
// assertAccessibilityRecordCleared, fullyPopulateAccessibilityRecord,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 7fa6ce4..922b79a 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -57,7 +57,7 @@
// The number of flags held in boolean properties. Their values should also be double-checked
// in the methods above.
- private static final int NUM_BOOLEAN_PROPERTIES = 22;
+ private static final int NUM_BOOLEAN_PROPERTIES = 17;
@Test
public void testStandardActions_serializationFlagIsValid() {
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index ace6b2d..364dcfd 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -18,10 +18,7 @@
import static org.junit.Assert.assertEquals;
-import android.content.Intent;
-import android.os.BatteryManager;
import android.os.Binder;
-import android.os.OsProtoEnums;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -34,7 +31,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -50,6 +46,7 @@
private static final int TEST_UID = 1;
private static final int REQUEST_SIZE = 2;
private static final int REPLY_SIZE = 3;
+ private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true);
@Test
public void testDetailedOff() {
@@ -388,43 +385,27 @@
}
@Test
- public void testDataResetWhenInitialStateSet() {
+ public void testNoDataCollectedBeforeInitialDeviceStateSet() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDeviceState(null);
bcs.setDetailedTracking(true);
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
bcs.time += 10;
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
- bcs.setInitialState(true, true);
+ bcs.setDeviceState(mDeviceState.getReadonlyClient());
SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
assertEquals(0, uidEntries.size());
}
@Test
- public void testScreenAndChargerInitialStates() {
- TestBinderCallsStats bcs = new TestBinderCallsStats();
- bcs.setDetailedTracking(true);
- Binder binder = new Binder();
- bcs.setInitialState(true /** screen iteractive */, false);
-
- CallSession callSession = bcs.callStarted(binder, 1);
- bcs.time += 10;
- bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
-
- List<BinderCallsStats.CallStat> callStatsList =
- new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
- assertEquals(true, callStatsList.get(0).screenInteractive);
- }
-
- @Test
public void testNoDataCollectedOnCharger() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setDetailedTracking(true);
- Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
- .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
- bcs.getBroadcastReceiver().onReceive(null, intent);
+ mDeviceState.setCharging(true);
+
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -436,7 +417,7 @@
public void testScreenOff() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setDetailedTracking(true);
- bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_OFF));
+ mDeviceState.setScreenInteractive(false);
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -453,7 +434,7 @@
public void testScreenOn() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setDetailedTracking(true);
- bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+ mDeviceState.setScreenInteractive(true);
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -470,9 +451,8 @@
public void testOnCharger() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setDetailedTracking(true);
- Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
- .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
- bcs.getBroadcastReceiver().onReceive(null, intent);
+ mDeviceState.setCharging(true);
+
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -484,9 +464,8 @@
public void testOnBattery() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setDetailedTracking(true);
- Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
- .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
- bcs.getBroadcastReceiver().onReceive(null, intent);
+ mDeviceState.setCharging(false);
+
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -522,7 +501,6 @@
public void testGetExportedStatsWhenDetailedTrackingEnabled() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setDetailedTracking(true);
- bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
Binder binder = new Binder();
CallSession callSession = bcs.callStarted(binder, 1);
@@ -561,7 +539,7 @@
assertEquals(0, bcs.getExceptionCounts().size());
}
- static class TestBinderCallsStats extends BinderCallsStats {
+ class TestBinderCallsStats extends BinderCallsStats {
int callingUid = TEST_UID;
long time = 1234;
long elapsedTime = 0;
@@ -580,6 +558,7 @@
}
});
setSamplingInterval(1);
+ setDeviceState(mDeviceState.getReadonlyClient());
}
@Override
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 297202b..0eb3d06 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -43,6 +43,7 @@
private Handler mHandlerFirst;
private Handler mHandlerSecond;
private Handler mHandlerAnonymous;
+ private CachedDeviceState mDeviceState;
@Before
public void setUp() {
@@ -58,6 +59,9 @@
mHandlerAnonymous = new Handler(mThreadFirst.getLooper()) {
/* To create an anonymous subclass. */
};
+ mDeviceState = new CachedDeviceState();
+ mDeviceState.setCharging(false);
+ mDeviceState.setScreenInteractive(true);
}
@After
@@ -82,6 +86,7 @@
assertThat(entry.handlerClassName).isEqualTo(
"com.android.internal.os.LooperStatsTest$TestHandlerFirst");
assertThat(entry.messageName).isEqualTo("0x3e8" /* 1000 in hex */);
+ assertThat(entry.isInteractive).isEqualTo(true);
assertThat(entry.messageCount).isEqualTo(1);
assertThat(entry.recordedMessageCount).isEqualTo(1);
assertThat(entry.exceptionCount).isEqualTo(0);
@@ -108,6 +113,7 @@
assertThat(entry.handlerClassName).isEqualTo(
"com.android.internal.os.LooperStatsTest$TestHandlerFirst");
assertThat(entry.messageName).isEqualTo("0x7" /* 7 in hex */);
+ assertThat(entry.isInteractive).isEqualTo(true);
assertThat(entry.messageCount).isEqualTo(0);
assertThat(entry.recordedMessageCount).isEqualTo(0);
assertThat(entry.exceptionCount).isEqualTo(1);
@@ -194,6 +200,70 @@
}
@Test
+ public void testDataNotCollectedBeforeDeviceStateSet() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+ looperStats.setDeviceState(null);
+
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+ new IllegalArgumentException());
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(0);
+ }
+
+ @Test
+ public void testDataNotCollectedOnCharger() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+ mDeviceState.setCharging(true);
+
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+ new IllegalArgumentException());
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(0);
+ }
+
+ @Test
+ public void testScreenStateCollected() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+ mDeviceState.setScreenInteractive(true);
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+ new IllegalArgumentException());
+
+ Object token3 = looperStats.messageDispatchStarting();
+ // If screen state changed during the call, we take the final state into account.
+ mDeviceState.setScreenInteractive(false);
+ looperStats.messageDispatched(token3, mHandlerFirst.obtainMessage(1000));
+ Object token4 = looperStats.messageDispatchStarting();
+ looperStats.dispatchingThrewException(token4, mHandlerFirst.obtainMessage(1000),
+ new IllegalArgumentException());
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(2);
+ entries.sort(Comparator.comparing(e -> e.isInteractive));
+
+ LooperStats.ExportedEntry entry1 = entries.get(0);
+ assertThat(entry1.isInteractive).isEqualTo(false);
+ assertThat(entry1.messageCount).isEqualTo(1);
+ assertThat(entry1.exceptionCount).isEqualTo(1);
+
+ LooperStats.ExportedEntry entry2 = entries.get(1);
+ assertThat(entry2.isInteractive).isEqualTo(true);
+ assertThat(entry2.messageCount).isEqualTo(1);
+ assertThat(entry2.exceptionCount).isEqualTo(1);
+ }
+
+ @Test
public void testMessagesOverSizeCap() {
TestableLooperStats looperStats = new TestableLooperStats(2, 1 /* sizeCap */);
@@ -281,7 +351,7 @@
}
}
- private static final class TestableLooperStats extends LooperStats {
+ private final class TestableLooperStats extends LooperStats {
private static final long INITIAL_MICROS = 10001000123L;
private int mCount;
private long mRealtimeMicros;
@@ -291,6 +361,7 @@
TestableLooperStats(int samplingInterval, int sizeCap) {
super(samplingInterval, sizeCap);
this.mSamplingInterval = samplingInterval;
+ this.setDeviceState(mDeviceState.getReadonlyClient());
}
void tickRealtime(long micros) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 9dab536..7fc1787 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -18,6 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
+import android.annotation.Px;
import android.annotation.Size;
import android.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontVariationAxis;
@@ -805,25 +806,39 @@
* Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
*
* @return true if the underlineText bit is set in the paint's flags.
+ * @see #getUnderlinePosition()
+ * @see #getUnderlineThickness()
+ * @see #setUnderlineText(boolean)
*/
public final boolean isUnderlineText() {
return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
}
/**
- * Distance from top of the underline to the baseline. Positive values mean below the baseline.
- * This method returns where the underline should be drawn independent of if the underlineText
- * bit is set at the moment.
- * @hide
+ * Returns the distance from top of the underline to the baseline in pixels.
+ *
+ * The result is positive for positions that are below the baseline.
+ * This method returns where the underline should be drawn independent of if the {@link
+ * #UNDERLINE_TEXT_FLAG} bit is set.
+ *
+ * @return the position of the underline in pixels
+ * @see #isUnderlineText()
+ * @see #getUnderlineThickness()
+ * @see #setUnderlineText(boolean)
*/
- public float getUnderlinePosition() {
+ public @Px float getUnderlinePosition() {
return nGetUnderlinePosition(mNativePaint);
}
/**
- * @hide
+ * Returns the thickness of the underline in pixels.
+ *
+ * @return the thickness of the underline in pixels
+ * @see #isUnderlineText()
+ * @see #getUnderlinePosition()
+ * @see #setUnderlineText(boolean)
*/
- public float getUnderlineThickness() {
+ public @Px float getUnderlineThickness() {
return nGetUnderlineThickness(mNativePaint);
}
@@ -832,6 +847,9 @@
*
* @param underlineText true to set the underlineText bit in the paint's
* flags, false to clear it.
+ * @see #isUnderlineText()
+ * @see #getUnderlinePosition()
+ * @see #getUnderlineThickness()
*/
public void setUnderlineText(boolean underlineText) {
nSetUnderlineText(mNativePaint, underlineText);
@@ -840,26 +858,40 @@
/**
* Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
*
- * @return true if the strikeThruText bit is set in the paint's flags.
+ * @return true if the {@link #STRIKE_THRU_TEXT_FLAG} bit is set in the paint's flags.
+ * @see #getStrikeThruPosition()
+ * @see #getStrikeThruThickness()
+ * @see #setStrikeThruText(boolean)
*/
public final boolean isStrikeThruText() {
return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
}
/**
- * Distance from top of the strike-through line to the baseline. Negative values mean above the
- * baseline. This method returns where the strike-through line should be drawn independent of if
- * the strikeThruText bit is set at the moment.
- * @hide
+ * Distance from top of the strike-through line to the baseline in pixels.
+ *
+ * The result is negative for positions that are above the baseline.
+ * This method returns where the strike-through line should be drawn independent of if the
+ * {@link #STRIKE_THRU_TEXT_FLAG} bit is set.
+ *
+ * @return the position of the strike-through line in pixels
+ * @see #getStrikeThruThickness()
+ * @see #setStrikeThruText(boolean)
+ * @see #isStrikeThruText()
*/
- public float getStrikeThruPosition() {
+ public @Px float getStrikeThruPosition() {
return nGetStrikeThruPosition(mNativePaint);
}
/**
- * @hide
+ * Returns the thickness of the strike-through line in pixels.
+ *
+ * @return the position of the strike-through line in pixels
+ * @see #getStrikeThruPosition()
+ * @see #setStrikeThruText(boolean)
+ * @see #isStrikeThruText()
*/
- public float getStrikeThruThickness() {
+ public @Px float getStrikeThruThickness() {
return nGetStrikeThruThickness(mNativePaint);
}
@@ -868,6 +900,9 @@
*
* @param strikeThruText true to set the strikeThruText bit in the paint's
* flags, false to clear it.
+ * @see #getStrikeThruPosition()
+ * @see #getStrikeThruThickness()
+ * @see #isStrikeThruText()
*/
public void setStrikeThruText(boolean strikeThruText) {
nSetStrikeThruText(mNativePaint, strikeThruText);
@@ -1560,22 +1595,25 @@
}
/**
- * Return the paint's word-spacing for text. The default value is 0.
+ * Return the paint's extra word-spacing for text.
*
- * @return the paint's word-spacing for drawing text.
- * @hide
+ * The default value is 0.
+ *
+ * @return the paint's extra word-spacing for drawing text in pixels.
+ * @see #setWordSpacing(float)
*/
public float getWordSpacing() {
return nGetWordSpacing(mNativePaint);
}
/**
- * Set the paint's word-spacing for text. The default value is 0.
- * The value is in pixels (note the units are not the same as for
- * letter-spacing).
+ * Set the paint's extra word-spacing for text.
*
- * @param wordSpacing set the paint's word-spacing for drawing text.
- * @hide
+ * Increases the white space width between words with the given amount of pixels.
+ * The default value is 0.
+ *
+ * @param wordSpacing set the paint's extra word-spacing for drawing text in pixels.
+ * @see #getWordSpacing()
*/
public void setWordSpacing(float wordSpacing) {
nSetWordSpacing(mNativePaint, wordSpacing);
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e8bc622..0476222 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1035,7 +1035,7 @@
return fromGetVolumeControlStream ?
AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
}
- if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
+ if ((aa.getAllFlags() & FLAG_SCO) == FLAG_SCO) {
return fromGetVolumeControlStream ?
AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
}
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 0892f73..967e13f 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -38,7 +38,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_vertical"
- android:visibility="invisible">
+ android:alpha="0">
<ImageView
android:id="@+id/next_alarm_icon"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
index 0d25c91..0cde9da 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.system;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
@@ -146,8 +147,9 @@
if (mInputEventReceiver == null) {
final InputChannel inputChannel = new InputChannel();
try {
- mWindowManager.destroyInputConsumer(mName);
- mWindowManager.createInputConsumer(mToken, mName, inputChannel);
+ // TODO(b/113087003): Support Picture-in-picture in multi-display.
+ mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
+ mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel);
} catch (RemoteException e) {
Log.e(TAG, "Failed to create input consumer", e);
}
@@ -164,7 +166,8 @@
public void unregisterInputConsumer() {
if (mInputEventReceiver != null) {
try {
- mWindowManager.destroyInputConsumer(mName);
+ // TODO(b/113087003): Support Picture-in-picture in multi-display.
+ mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
} catch (RemoteException e) {
Log.e(TAG, "Failed to destroy input consumer", e);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index 5605b7a..ac8f024 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -39,6 +39,7 @@
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.systemui.util.EmergencyDialerConstants;
/**
* This class implements a smart emergency button that updates itself based
@@ -48,11 +49,13 @@
*/
public class EmergencyButton extends Button {
private static final Intent INTENT_EMERGENCY_DIAL = new Intent()
- .setAction("com.android.phone.EmergencyDialer.DIAL")
+ .setAction(EmergencyDialerConstants.ACTION_DIAL)
.setPackage("com.android.phone")
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+ EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
private static final String LOG_TAG = "EmergencyButton";
private final EmergencyAffordanceManager mEmergencyAffordanceManager;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 51cc4a1..e6026c1 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -35,7 +35,7 @@
private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
- private static final int PULSE_REASONS = 7;
+ private static final int REASONS = 8;
public static final int PULSE_REASON_NONE = -1;
public static final int PULSE_REASON_INTENT = 0;
@@ -45,6 +45,7 @@
public static final int PULSE_REASON_SENSOR_DOUBLE_TAP = 4;
public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
public static final int PULSE_REASON_SENSOR_REACH = 6;
+ public static final int REASON_SENSOR_WAKE_UP = 7;
private static boolean sRegisterKeyguardCallback = true;
@@ -74,7 +75,7 @@
public static void tracePulseStart(int reason) {
if (!ENABLED) return;
sPulsing = true;
- log("pulseStart reason=" + pulseReasonToString(reason));
+ log("pulseStart reason=" + reasonToString(reason));
}
public static void tracePulseFinish() {
@@ -102,8 +103,8 @@
sScreenOnPulsingStats = new SummaryStats();
sScreenOnNotPulsingStats = new SummaryStats();
sEmergencyCallStats = new SummaryStats();
- sProxStats = new SummaryStats[PULSE_REASONS][2];
- for (int i = 0; i < PULSE_REASONS; i++) {
+ sProxStats = new SummaryStats[REASONS][2];
+ for (int i = 0; i < REASONS; i++) {
sProxStats[i][0] = new SummaryStats();
sProxStats[i][1] = new SummaryStats();
}
@@ -157,6 +158,12 @@
log("missedTick by=" + delay);
}
+ public static void traceTimeTickScheduled(long when, long triggerAt) {
+ if (!ENABLED) return;
+ log("timeTickScheduled at=" + FORMAT.format(new Date(when)) + " triggerAt="
+ + FORMAT.format(new Date(triggerAt)));
+ }
+
public static void traceKeyguard(boolean showing) {
if (!ENABLED) return;
log("keyguard " + showing);
@@ -176,15 +183,15 @@
}
public static void traceProximityResult(Context context, boolean near, long millis,
- int pulseReason) {
+ int reason) {
if (!ENABLED) return;
init(context);
- log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
+ log("proximityResult reason=" + reasonToString(reason) + " near=" + near
+ " millis=" + millis);
- sProxStats[pulseReason][near ? 0 : 1].append();
+ sProxStats[reason][near ? 0 : 1].append();
}
- public static String pulseReasonToString(int pulseReason) {
+ public static String reasonToString(int pulseReason) {
switch (pulseReason) {
case PULSE_REASON_INTENT: return "intent";
case PULSE_REASON_NOTIFICATION: return "notification";
@@ -193,6 +200,7 @@
case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
case PULSE_REASON_SENSOR_REACH: return "reach";
+ case REASON_SENSOR_WAKE_UP: return "wakeup";
default: throw new IllegalArgumentException("bad reason: " + pulseReason);
}
}
@@ -218,8 +226,8 @@
sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
sEmergencyCallStats.dump(pw, "Emergency call");
- for (int i = 0; i < PULSE_REASONS; i++) {
- final String reason = pulseReasonToString(i);
+ for (int i = 0; i < REASONS; i++) {
+ final String reason = reasonToString(i);
sProxStats[i][0].dump(pw, "Proximity near (" + reason + ")");
sProxStats[i][1].dump(pw, "Proximity far (" + reason + ")");
}
@@ -262,10 +270,10 @@
}
}
- public static void traceSensor(Context context, int pulseReason) {
+ public static void traceSensor(Context context, int reason) {
if (!ENABLED) return;
init(context);
- log("sensor type=" + pulseReasonToString(pulseReason));
+ log("sensor type=" + reasonToString(reason));
}
private static class SummaryStats {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 045a98c..f9dfb5d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -63,6 +63,7 @@
private final AmbientDisplayConfiguration mConfig;
private final WakeLock mWakeLock;
private final Consumer<Boolean> mProxCallback;
+ private final Consumer<Boolean> mWakeScreenCallback;
private final Callback mCallback;
private final Handler mHandler = new Handler();
@@ -70,9 +71,9 @@
public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
- DozeParameters dozeParameters,
- AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
- Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
+ DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
+ Callback callback, Consumer<Boolean> proxCallback,
+ Consumer<Boolean> wakeScreenCallback, AlwaysOnDisplayPolicy policy) {
mContext = context;
mAlarmManager = alarmManager;
mSensorManager = sensorManager;
@@ -80,6 +81,7 @@
mConfig = config;
mWakeLock = wakeLock;
mProxCallback = proxCallback;
+ mWakeScreenCallback = wakeScreenCallback;
mResolver = mContext.getContentResolver();
mSensors = new TriggerSensor[] {
@@ -117,6 +119,7 @@
DozeLog.PULSE_REASON_SENSOR_REACH,
false /* reports touch coordinates */,
false /* touchscreen */),
+ new WakeScreenSensor(),
};
mProxSensor = new ProxSensor(policy);
@@ -302,9 +305,9 @@
final boolean mSettingDefault;
final boolean mRequiresTouchscreen;
- private boolean mRequested;
- private boolean mRegistered;
- private boolean mDisabled;
+ protected boolean mRequested;
+ protected boolean mRegistered;
+ protected boolean mDisabled;
public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
@@ -348,7 +351,7 @@
}
}
- private boolean enabledBySetting() {
+ protected boolean enabledBySetting() {
if (TextUtils.isEmpty(mSetting)) {
return true;
}
@@ -401,7 +404,7 @@
}
}
- private String triggerEventToString(TriggerEvent event) {
+ protected String triggerEventToString(TriggerEvent event) {
if (event == null) return null;
final StringBuilder sb = new StringBuilder("TriggerEvent[")
.append(event.timestamp).append(',')
@@ -415,6 +418,28 @@
}
}
+ private class WakeScreenSensor extends TriggerSensor {
+
+ WakeScreenSensor() {
+ super(findSensorWithType(mConfig.wakeScreenSensorType()),
+ Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, true /* configured */,
+ DozeLog.REASON_SENSOR_WAKE_UP, false /* reportsTouchCoordinates */,
+ false /* requiresTouchscreen */);
+ }
+
+ @Override
+ @AnyThread
+ public void onTrigger(TriggerEvent event) {
+ DozeLog.traceSensor(mContext, mPulseReason);
+ mHandler.post(mWakeLock.wrap(() -> {
+ if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
+ mRegistered = false;
+ mWakeScreenCallback.accept(event.values[0] > 0);
+ updateListener(); // reregister, this sensor only fires once
+ }));
+ }
+ }
+
public interface Callback {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 73cbd7d..1589969 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -84,7 +84,7 @@
mWakeLock = wakeLock;
mAllowPulseTriggers = allowPulseTriggers;
mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
- config, wakeLock, this::onSensor, this::onProximityFar,
+ config, wakeLock, this::onSensor, this::onProximityFar, this::onWakeScreen,
dozeParameters.getPolicy());
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
@@ -103,7 +103,7 @@
private void proximityCheckThenCall(IntConsumer callback,
boolean alreadyPerformedProxCheck,
- int pulseReason) {
+ int reason) {
Boolean cachedProxFar = mDozeSensors.isProximityCurrentlyFar();
if (alreadyPerformedProxCheck) {
callback.accept(ProximityCheck.RESULT_NOT_CHECKED);
@@ -116,7 +116,7 @@
public void onProximityResult(int result) {
final long end = SystemClock.uptimeMillis();
DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
- end - start, pulseReason);
+ end - start, reason);
callback.accept(result);
}
}.check();
@@ -182,6 +182,28 @@
}
}
+ private void onWakeScreen(boolean wake) {
+ DozeMachine.State state = mMachine.getState();
+ boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
+ boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
+
+ if (wake) {
+ proximityCheckThenCall((result) -> {
+ if (result == ProximityCheck.RESULT_NEAR) {
+ // In pocket, drop event.
+ return;
+ }
+ if (pausing || paused) {
+ mMachine.requestState(DozeMachine.State.DOZE_AOD);
+ }
+ }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
+ } else {
+ if (!pausing && !paused) {
+ mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
+ }
+ }
+ }
+
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 7863245..67aa82d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -158,8 +158,12 @@
return;
}
- long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
- mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ long time = System.currentTimeMillis();
+ long delta = roundToNextMinute(time) - System.currentTimeMillis();
+ boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ if (scheduled) {
+ DozeLog.traceTimeTickScheduled(time, time + delta);
+ }
mLastTimeTickElapsed = SystemClock.elapsedRealtime();
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 06d4434..cc1b9e8 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -89,6 +89,7 @@
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
import java.util.ArrayList;
@@ -449,9 +450,6 @@
}
private class EmergencyDialerAction extends SinglePressAction {
- private static final String ACTION_EMERGENCY_DIALER_DIAL =
- "com.android.phone.EmergencyDialer.DIAL";
-
private EmergencyDialerAction() {
super(R.drawable.ic_faster_emergency,
R.string.global_action_emergency);
@@ -460,8 +458,10 @@
@Override
public void onPress() {
MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU);
- Intent intent = new Intent(ACTION_EMERGENCY_DIALER_DIAL);
+ Intent intent = new Intent(EmergencyDialerConstants.ACTION_DIAL);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+ EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4977ff7..1655c01 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -503,9 +503,6 @@
case READY:
synchronized (KeyguardViewMediator.this) {
if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing);
- if (mShowing) {
- resetStateLocked();
- }
mLockWhenSimRemoved = true;
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index ff5ac76..b988c55 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -547,38 +547,23 @@
/**
* Fades in the updated status text. Note that if there's already a status showing, this will
- * immediately hide it and fade in the updated status.
+ * immediately fade it out and fade in the updated status.
*/
private void showStatus() {
mStatusContainer.setAlpha(0f);
- mStatusContainer.setVisibility(View.VISIBLE);
- // Animate the alarm back in. Make sure to clear the animator listener for the animation!
mStatusContainer.animate()
.alpha(1f)
.setDuration(FADE_ANIMATION_DURATION_MS)
- .setListener(null)
.start();
}
- /** Fades out and hides the status text. */
+ /** Fades out the status text. */
private void hideStatusText() {
- if (mStatusContainer.getVisibility() == View.VISIBLE) {
- mStatusContainer.animate()
- .alpha(0f)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (DEBUG) Log.d(TAG, "hideAlarmText: Hid alarm text");
-
- // Reset the alpha regardless of how the animation ends for the next
- // time we show this view/want to animate it.
- mStatusContainer.setVisibility(View.INVISIBLE);
- mStatusContainer.setAlpha(1f);
- }
- })
- .start();
- }
+ mStatusContainer.animate()
+ .alpha(0f)
+ .setDuration(FADE_ANIMATION_DURATION_MS)
+ .start();
}
public void updateEverything() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index afd64f3..0d3ba77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -45,7 +45,7 @@
public void onDisplayBlanked() {
if (DEBUG) {
Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason="
- + DozeLog.pulseReasonToString(mPulseReason));
+ + DozeLog.reasonToString(mPulseReason));
}
if (!mDozing) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
index f7f61af..a791376 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
@@ -44,7 +44,15 @@
mHandler = handler;
}
- public void schedule(long timeout, int mode) {
+ /**
+ * Schedules an alarm in {@code timeout} milliseconds in the future.
+ *
+ * @param timeout How long to wait from now.
+ * @param mode {@link #MODE_CRASH_IF_SCHEDULED}, {@link #MODE_IGNORE_IF_SCHEDULED} or
+ * {@link #MODE_RESCHEDULE_IF_SCHEDULED}.
+ * @return {@code true} when scheduled successfully, {@code false} otherwise.
+ */
+ public boolean schedule(long timeout, int mode) {
switch (mode) {
case MODE_CRASH_IF_SCHEDULED:
if (mScheduled) {
@@ -53,7 +61,7 @@
break;
case MODE_IGNORE_IF_SCHEDULED:
if (mScheduled) {
- return;
+ return false;
}
break;
case MODE_RESCHEDULE_IF_SCHEDULED:
@@ -68,6 +76,7 @@
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + timeout, mTag, this, mHandler);
mScheduled = true;
+ return true;
}
public boolean isScheduled() {
diff --git a/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
new file mode 100644
index 0000000..d101ccb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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 com.android.systemui.util;
+
+/**
+ * Constants defined and used in emergency dialer.
+ * Please keep these constants being consistent with those in com.android.phone.EmergencyDialer.
+ */
+public class EmergencyDialerConstants {
+ // Intent action for emergency dialer activity.
+ public static final String ACTION_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
+ /**
+ * Extra included in {@link #ACTION_DIAL} to indicate the entry type that user starts
+ * the emergency dialer.
+ */
+ public static final String EXTRA_ENTRY_TYPE =
+ "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE";
+
+ // Indicating the entrance to emergency dialer
+ public static final int ENTRY_TYPE_UNKNOWN = 0;
+ public static final int ENTRY_TYPE_LOCKSCREEN_BUTTON = 1;
+ public static final int ENTRY_TYPE_POWER_MENU = 2;
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index b668623..7edcdcb 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -6508,6 +6508,10 @@
// OS: Q
ACTION_EMERGENCY_DIALER_FROM_POWER_MENU = 1569;
+ // OPEN: Settings > System > Input & Gesture > Wake screen
+ // OS: Q
+ SETTINGS_GESTURE_WAKE_SCREEN = 1570;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/accessibility/TEST_MAPPING b/services/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..320924c
--- /dev/null
+++ b/services/accessibility/TEST_MAPPING
@@ -0,0 +1,105 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsAccessibilityTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsUiAutomationTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.accessibility"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "com.android.internal.accessibility"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.accessibility"
+ },
+ {
+ "exclude-annotation": "android.support.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases"
+ },
+ {
+ "name": "CtsAccessibilityTestCases"
+ },
+ {
+ "name": "CtsUiAutomationTestCases"
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.accessibility"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "com.android.internal.accessibility"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.accessibility"
+ }
+ ]
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 50f15ca0..a85b69b 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -399,6 +399,12 @@
private void update(android.hardware.health.V2_0.HealthInfo info) {
traceBegin("HealthInfoUpdate");
+
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryChargeCounter",
+ info.legacy.batteryChargeCounter);
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent",
+ info.legacy.batteryCurrent);
+
synchronized (mLock) {
if (!mUpdatesStopped) {
mHealthInfo = info.legacy;
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 9a7c345..15673a7 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -33,7 +33,7 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats;
-import com.android.internal.os.BinderInternal;
+import com.android.internal.os.CachedDeviceState;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -41,7 +41,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Random;
public class BinderCallsStatsService extends Binder {
@@ -156,8 +155,10 @@
@Override
public void onBootPhase(int phase) {
if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+ CachedDeviceState.Readonly deviceState = getLocalService(
+ CachedDeviceState.Readonly.class);
mService.systemReady(getContext());
- mBinderCallsStats.systemReady(getContext());
+ mBinderCallsStats.setDeviceState(deviceState);
}
}
}
diff --git a/services/core/java/com/android/server/CachedDeviceStateService.java b/services/core/java/com/android/server/CachedDeviceStateService.java
new file mode 100644
index 0000000..38269d3
--- /dev/null
+++ b/services/core/java/com/android/server/CachedDeviceStateService.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 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 com.android.server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
+import android.util.Slog;
+
+import com.android.internal.os.CachedDeviceState;
+
+/**
+ * Tracks changes to the device state (e.g. charging/on battery, screen on/off) to share it with
+ * the System Server telemetry services.
+ *
+ * @hide Only for use within the system server.
+ */
+public class CachedDeviceStateService extends SystemService {
+ private static final String TAG = "CachedDeviceStateService";
+ private final CachedDeviceState mDeviceState = new CachedDeviceState();
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ switch (intent.getAction()) {
+ case Intent.ACTION_BATTERY_CHANGED:
+ mDeviceState.setCharging(
+ intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,
+ OsProtoEnums.BATTERY_PLUGGED_NONE)
+ != OsProtoEnums.BATTERY_PLUGGED_NONE);
+ break;
+ case Intent.ACTION_SCREEN_ON:
+ mDeviceState.setScreenInteractive(true);
+ break;
+ case Intent.ACTION_SCREEN_OFF:
+ mDeviceState.setScreenInteractive(false);
+ break;
+ }
+ }
+ };
+
+ public CachedDeviceStateService(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishLocalService(CachedDeviceState.Readonly.class, mDeviceState.getReadonlyClient());
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ getContext().registerReceiver(mBroadcastReceiver, filter);
+ mDeviceState.setCharging(queryIsCharging());
+ mDeviceState.setScreenInteractive(queryScreenInteractive(getContext()));
+ }
+ }
+
+ private boolean queryIsCharging() {
+ final BatteryManagerInternal batteryManager =
+ LocalServices.getService(BatteryManagerInternal.class);
+ if (batteryManager == null) {
+ Slog.wtf(TAG, "BatteryManager null while starting CachedDeviceStateService");
+ // Default to true to not collect any data.
+ return true;
+ } else {
+ return batteryManager.getPlugType() != OsProtoEnums.BATTERY_PLUGGED_NONE;
+ }
+ }
+
+ private boolean queryScreenInteractive(Context context) {
+ final PowerManager powerManager = context.getSystemService(PowerManager.class);
+ if (powerManager == null) {
+ Slog.wtf(TAG, "PowerManager null while starting CachedDeviceStateService");
+ return false;
+ } else {
+ return powerManager.isInteractive();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 44dddd1..f981b26 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -127,6 +127,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
import com.android.internal.inputmethod.InputMethodUtils;
@@ -198,7 +199,7 @@
static final int MSG_SHOW_SOFT_INPUT = 1020;
static final int MSG_HIDE_SOFT_INPUT = 1030;
static final int MSG_HIDE_CURRENT_INPUT_METHOD = 1035;
- static final int MSG_ATTACH_TOKEN = 1040;
+ static final int MSG_INITIALIZE_IME = 1040;
static final int MSG_CREATE_SESSION = 1050;
static final int MSG_START_INPUT = 2000;
@@ -1968,7 +1969,7 @@
}
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
- MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
+ MSG_INITIALIZE_IME, mCurMethod, mCurToken));
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
requestClientSessionLocked(mCurClient);
@@ -2217,8 +2218,7 @@
@BinderThread
@SuppressWarnings("deprecation")
- @Override
- public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
+ private void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
if (!calledWithValidToken(token)) {
return;
}
@@ -2253,8 +2253,7 @@
}
@BinderThread
- @Override
- public void reportStartInput(IBinder token, IBinder startInputToken) {
+ private void reportStartInput(IBinder token, IBinder startInputToken) {
if (!calledWithValidToken(token)) {
return;
}
@@ -3145,13 +3144,21 @@
return;
}
+ /**
+ * This is kept due to {@link android.annotation.UnsupportedAppUsage} in
+ * {@link InputMethodManager#getInputMethodWindowVisibleHeight()} and a dependency in
+ * {@link InputMethodService#onCreate()}.
+ *
+ * <p>TODO(Bug 113914148): Check if we can remove this.</p>
+ * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()}
+ */
@Override
public int getInputMethodWindowVisibleHeight() {
return mWindowManagerInternal.getInputMethodWindowVisibleHeight();
}
- @Override
- public void clearLastInputMethodWindowForTransition(IBinder token) {
+ @BinderThread
+ private void clearLastInputMethodWindowForTransition(IBinder token) {
if (!calledFromValidUser()) {
return;
}
@@ -3346,11 +3353,13 @@
hideCurrentInputLocked(0, null);
}
return true;
- case MSG_ATTACH_TOKEN:
+ case MSG_INITIALIZE_IME:
args = (SomeArgs)msg.obj;
try {
if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
- ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
+ final IBinder token = (IBinder) args.arg2;
+ ((IInputMethod) args.arg1).initializeInternal(token,
+ new InputMethodPrivilegedOperationsImpl(this, token));
} catch (RemoteException e) {
}
args.recycle();
@@ -4424,8 +4433,8 @@
}
}
- @Override
- public IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
+ @BinderThread
+ private IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
@Nullable Uri contentUri, @Nullable String packageName) {
if (!calledFromValidUser()) {
return null;
@@ -4482,8 +4491,8 @@
}
}
- @Override
- public void reportFullscreenMode(IBinder token, boolean fullscreen) {
+ @BinderThread
+ private void reportFullscreenMode(IBinder token, boolean fullscreen) {
if (!calledFromValidUser()) {
return;
}
@@ -4958,4 +4967,45 @@
return ShellCommandResult.SUCCESS;
}
}
+
+ private static final class InputMethodPrivilegedOperationsImpl
+ extends IInputMethodPrivilegedOperations.Stub {
+ private final InputMethodManagerService mImms;
+ private final IBinder mToken;
+ InputMethodPrivilegedOperationsImpl(InputMethodManagerService imms, IBinder token) {
+ mImms = imms;
+ mToken = token;
+ }
+
+ @BinderThread
+ @Override
+ public void setImeWindowStatus(int vis, int backDisposition) {
+ mImms.setImeWindowStatus(mToken, vis, backDisposition);
+ }
+
+ @BinderThread
+ @Override
+ public void reportStartInput(IBinder startInputToken) {
+ mImms.reportStartInput(mToken, startInputToken);
+ }
+
+ @BinderThread
+ @Override
+ public void clearLastInputMethodWindowForTransition() {
+ mImms.clearLastInputMethodWindowForTransition(mToken);
+ }
+
+ @BinderThread
+ @Override
+ public IInputContentUriToken createInputContentUriToken(Uri contentUri,
+ String packageName) {
+ return mImms.createInputContentUriToken(mToken, contentUri, packageName);
+ }
+
+ @BinderThread
+ @Override
+ public void reportFullscreenMode(boolean fullscreen) {
+ mImms.reportFullscreenMode(mToken, fullscreen);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index 237e169..23b30cc 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -17,12 +17,21 @@
package com.android.server;
import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
import android.os.Binder;
import android.os.Looper;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.CachedDeviceState;
import com.android.internal.os.LooperStats;
import com.android.internal.util.DumpUtils;
@@ -38,6 +47,13 @@
public class LooperStatsService extends Binder {
private static final String TAG = "LooperStatsService";
private static final String LOOPER_STATS_SERVICE_NAME = "looper_stats";
+ private static final String SETTINGS_ENABLED_KEY = "enabled";
+ private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
+ private static final String DEBUG_SYS_LOOPER_STATS_ENABLED =
+ "debug.sys.looper_stats_enabled";
+ private static final int DEFAULT_SAMPLING_INTERVAL = 100;
+ private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
+ private static final boolean DEFAULT_ENABLED = false;
private final Context mContext;
private final LooperStats mStats;
@@ -48,6 +64,24 @@
this.mStats = stats;
}
+ private void initFromSettings() {
+ final KeyValueListParser parser = new KeyValueListParser(',');
+
+ try {
+ parser.setString(Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.LOOPER_STATS));
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Bad looper_stats settings", e);
+ }
+
+ setSamplingInterval(
+ parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL));
+ // Manually specified value takes precedence over Settings.
+ setEnabled(SystemProperties.getBoolean(
+ DEBUG_SYS_LOOPER_STATS_ENABLED,
+ parser.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED)));
+ }
+
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
@@ -66,6 +100,7 @@
"thread_name",
"handler_class",
"message_name",
+ "is_interactive",
"message_count",
"recorded_message_count",
"total_latency_micros",
@@ -75,10 +110,11 @@
"exception_count"));
pw.println(header);
for (LooperStats.ExportedEntry entry : entries) {
- pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.threadName, entry.handlerClassName,
- entry.messageName, entry.messageCount, entry.recordedMessageCount,
- entry.totalLatencyMicros, entry.maxLatencyMicros, entry.cpuUsageMicros,
- entry.maxCpuUsageMicros, entry.exceptionCount);
+ pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.threadName,
+ entry.handlerClassName, entry.messageName, entry.isInteractive,
+ entry.messageCount, entry.recordedMessageCount, entry.totalLatencyMicros,
+ entry.maxLatencyMicros, entry.cpuUsageMicros, entry.maxCpuUsageMicros,
+ entry.exceptionCount);
}
}
@@ -90,20 +126,55 @@
}
}
+ private void setSamplingInterval(int samplingInterval) {
+ mStats.setSamplingInterval(samplingInterval);
+ }
+
/**
* Manages the lifecycle of LooperStatsService within System Server.
*/
public static class Lifecycle extends SystemService {
+ private final SettingsObserver mSettingsObserver;
+ private final LooperStatsService mService;
+ private final LooperStats mStats;
+
public Lifecycle(Context context) {
super(context);
+ mStats = new LooperStats(DEFAULT_SAMPLING_INTERVAL, DEFAULT_ENTRIES_SIZE_CAP);
+ mService = new LooperStatsService(getContext(), mStats);
+ mSettingsObserver = new SettingsObserver(mService);
}
@Override
public void onStart() {
- LooperStats stats = new LooperStats();
- publishLocalService(LooperStats.class, stats);
+ publishLocalService(LooperStats.class, mStats);
// TODO: publish LooperStatsService as a binder service when the SE Policy is changed.
}
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+ mService.initFromSettings();
+ Uri settingsUri = Settings.Global.getUriFor(Settings.Global.LOOPER_STATS);
+ getContext().getContentResolver().registerContentObserver(
+ settingsUri, false, mSettingsObserver, UserHandle.USER_SYSTEM);
+ mStats.setDeviceState(getLocalService(CachedDeviceState.Readonly.class));
+ }
+ }
+ }
+
+ private static class SettingsObserver extends ContentObserver {
+ private final LooperStatsService mService;
+
+ SettingsObserver(LooperStatsService service) {
+ super(BackgroundThread.getHandler());
+ mService = service;
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ mService.initFromSettings();
+ }
}
private class LooperShellCommand extends ShellCommand {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b91a449..e6ff0d8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17061,7 +17061,7 @@
activeInstr.mUiAutomationConnection = uiAutomationConnection;
activeInstr.mResultClass = className;
- boolean disableHiddenApiChecks = ai.usesNonSdkApi
+ boolean disableHiddenApiChecks = ai.usesNonSdkApi()
|| (flags & INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
if (disableHiddenApiChecks) {
enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 9de6875..b24c36a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -302,7 +303,9 @@
mSamplingInterval = 0;
mAutoStop = false;
mStreaming = false;
- mUserId = defUser;
+ mUserId = mInternal.mUserController.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), defUser, false, ALLOW_FULL_ONLY,
+ "ActivityManagerShellCommand", null);
mDisplayId = INVALID_DISPLAY;
mWindowingMode = WINDOWING_MODE_UNDEFINED;
mActivityType = ACTIVITY_TYPE_UNDEFINED;
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 11f8bb1..7eadcb3 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -27,17 +27,7 @@
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.content.pm.PackageManager.FEATURE_PC;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
-import static android.provider.Settings.System.FONT_SCALE;
-import static com.android.server.am.ActivityManagerService.dumpStackTraces;
-import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
-import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_NONE;
@@ -51,15 +41,19 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.content.pm.PackageManager.FEATURE_PC;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
import static android.os.Build.VERSION_CODES.N;
import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
+import static android.provider.Settings.System.FONT_SCALE;
import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -68,6 +62,7 @@
import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -86,13 +81,13 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static com.android.server.am.ActivityManagerService.ANIMATE;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ActivityManagerService.SEND_LOCALE_TO_MOUNT_DAEMON_MSG;
import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
import static com.android.server.am.ActivityManagerService.UPDATE_CONFIGURATION_MSG;
import static com.android.server.am.ActivityManagerService.checkComponentPermission;
+import static com.android.server.am.ActivityManagerService.dumpStackTraces;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
@@ -100,10 +95,16 @@
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
+import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
@@ -118,26 +119,8 @@
import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.database.ContentObserver;
-import android.os.IUserManager;
-import android.os.PowerManager;
-import android.os.ServiceManager;
-import android.os.Trace;
-import android.os.UserManager;
-import android.os.WorkSource;
-import android.view.WindowManager;
-import com.android.internal.R;
-import com.android.internal.app.IAppOpsService;
-import com.android.server.AppOpsService;
-import com.android.server.SystemServiceManager;
-import com.android.server.pm.UserManagerService;
-import com.android.server.uri.UriGrantsManagerInternal;
-import com.android.server.wm.ActivityTaskManagerInternal;
import android.app.AppGlobals;
+import android.app.Dialog;
import android.app.IActivityController;
import android.app.IActivityTaskManager;
import android.app.IApplicationThread;
@@ -157,15 +140,19 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
@@ -177,16 +164,22 @@
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IUserManager;
import android.os.LocaleList;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
+import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UpdateLock;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.WorkSource;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
@@ -197,7 +190,6 @@
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
-
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.StatsLog;
@@ -206,22 +198,30 @@
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
+import android.view.WindowManager;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
+import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.KeyguardDismissCallback;
import com.android.internal.util.Preconditions;
+import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
import com.android.server.Watchdog;
+import com.android.server.pm.UserManagerService;
+import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index bc23316..0a7e127 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -414,7 +414,11 @@
if (state == BroadcastRecord.IDLE) {
Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
}
- r.duration[r.nextReceiver - 1] = finishTime - r.receiverTime;
+ // If we're abandoning this broadcast before any receivers were actually spun up,
+ // nextReceiver is zero; in which case time-to-process bookkeeping doesn't apply.
+ if (r.nextReceiver > 0) {
+ r.duration[r.nextReceiver - 1] = finishTime - r.receiverTime;
+ }
r.receiver = null;
r.intent.setComponent(null);
if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 2750dc1..a050aa9 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -20,25 +20,6 @@
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import android.annotation.NonNull;
-import android.os.LocaleList;
-import android.os.ShellCallback;
-import android.util.Log;
-import android.view.Display;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.R;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
-import com.android.server.DisplayThread;
-import com.android.server.LocalServices;
-import com.android.server.Watchdog;
-import com.android.server.policy.WindowManagerPolicy;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.Manifest;
import android.app.IInputForwarder;
import android.app.Notification;
import android.app.NotificationManager;
@@ -53,8 +34,8 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
@@ -64,10 +45,10 @@
import android.hardware.display.DisplayViewport;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
+import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
-import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.TouchCalibration;
import android.os.Binder;
@@ -75,6 +56,7 @@
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
@@ -84,6 +66,7 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
@@ -100,6 +83,23 @@
import android.view.ViewConfiguration;
import android.widget.Toast;
+import com.android.internal.R;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+import com.android.server.DisplayThread;
+import com.android.server.LocalServices;
+import com.android.server.Watchdog;
+import com.android.server.policy.WindowManagerPolicy;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import org.xmlpull.v1.XmlPullParser;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
@@ -116,9 +116,6 @@
import java.util.Locale;
import java.util.Objects;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
/*
* Wraps the C++ InputManager and provides its callbacks.
*/
@@ -215,7 +212,8 @@
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
int policyFlags);
private static native void nativeToggleCapsLock(long ptr, int deviceId);
- private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
+ private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles,
+ int displayId);
private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
private static native void nativeSetFocusedApplication(long ptr,
@@ -1465,7 +1463,7 @@
}
public void setInputWindows(InputWindowHandle[] windowHandles,
- InputWindowHandle focusedWindowHandle) {
+ InputWindowHandle focusedWindowHandle, int displayId) {
final IWindow newFocusedWindow =
focusedWindowHandle != null ? focusedWindowHandle.clientWindow : null;
if (mFocusedWindow != newFocusedWindow) {
@@ -1474,7 +1472,7 @@
setPointerCapture(false);
}
}
- nativeSetInputWindows(mPtr, windowHandles);
+ nativeSetInputWindows(mPtr, windowHandles, displayId);
}
public void setFocusedApplication(InputApplicationHandle application) {
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java
index 720eaaa5..bb29bf8 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/services/core/java/com/android/server/input/InputWindowHandle.java
@@ -17,8 +17,8 @@
package com.android.server.input;
import android.graphics.Region;
-import android.view.InputChannel;
import android.view.IWindow;
+import android.view.InputChannel;
/**
* Functions as a handle for a window that can receive input.
@@ -106,7 +106,7 @@
@Override
public String toString() {
- return new StringBuilder(name)
+ return new StringBuilder(name != null ? name : "")
.append(", layer=").append(layer)
.append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
.append(frameRight).append(",").append(frameBottom).append("]")
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b775918..6da9f10 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -32,29 +32,11 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-
+import static android.view.WindowManager.TRANSIT_UNSET;
import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_UNSET;
-
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
@@ -78,6 +60,23 @@
import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import android.annotation.CallSuper;
@@ -1845,8 +1844,8 @@
surfaceInsets = win.getAttrs().surfaceInsets;
// XXX(b/72757033): These are insets relative to the window frame, but we're really
// interested in the insets relative to the frame we chose in the if-blocks above.
- insets.set(win.mContentInsets);
- stableInsets.set(win.mStableInsets);
+ win.getContentInsets(insets);
+ win.getStableInsets(stableInsets);
}
if (mLaunchTaskBehind) {
@@ -2099,7 +2098,7 @@
WindowState win = findMainWindow();
Rect appRect = win != null ? win.getContentFrameLw() :
new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
- Rect insets = win != null ? win.mContentInsets : null;
+ final Rect insets = win != null ? win.getContentInsets() : null;
final Configuration displayConfig = mDisplayContent.getConfiguration();
return mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(
appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9490ae2..d3e534c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -814,9 +814,7 @@
// {@link DisplayContent} ready for use.
mDisplayReady = true;
- // TODO(b/112081256): Use independent InputMonitor.
- mInputMonitor = isDefaultDisplay ? new InputMonitor(service, mDisplayId)
- : mService.getDefaultDisplayContentLocked().mInputMonitor;
+ mInputMonitor = new InputMonitor(service, mDisplayId);
}
boolean isReady() {
@@ -2185,6 +2183,7 @@
mRemovingDisplay = false;
}
+ mInputMonitor.onRemoved();
mService.onDisplayRemoved(mDisplayId);
}
@@ -3009,7 +3008,7 @@
if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
w.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
- w.mLastContentInsets.set(-1, -1, -1, -1);
+ w.resetLastContentInsets();
mService.mWaitingForDrawn.add(w);
}
}, true /* traverseTopToBottom */);
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 6a08f4d..585a4f5 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -20,9 +20,9 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.view.Display;
import android.view.InputChannel;
import android.view.WindowManager;
+
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index c4beb55..3309798 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -367,6 +367,13 @@
}
}
+ void onRemoved() {
+ // If DisplayContent removed, we need find a way to remove window handles of this display
+ // from InputDispatcher, so pass an empty InputWindowHandles to remove them.
+ mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+ mDisplayId);
+ }
+
private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
InputConsumerImpl navInputConsumer;
InputConsumerImpl pipInputConsumer;
@@ -399,8 +406,7 @@
this.inDrag = inDrag;
wallpaperController = mService.mRoot.mWallpaperController;
- // TODO(b/112081256): Use independent InputMonitor for each display.
- mService.mRoot/*.getDisplayContent(mDisplayId)*/.forAllWindows(this,
+ mService.mRoot.getDisplayContent(mDisplayId).forAllWindows(this,
true /* traverseTopToBottom */);
if (mAddWallpaperInputConsumerHandle) {
// No visible wallpaper found, add the wallpaper input consumer at the end.
@@ -408,8 +414,8 @@
}
// Send windows to native code.
- // TODO: Update Input windows and focus by display?
- mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
+ mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+ mDisplayId);
clearInputWindowHandlesLw();
@@ -429,7 +435,8 @@
final int flags = w.mAttrs.flags;
final int privateFlags = w.mAttrs.privateFlags;
final int type = w.mAttrs.type;
- final boolean hasFocus = w == mInputFocus;
+ // TODO(b/111361570): multi-display focus, one focus window per display.
+ final boolean hasFocus = w.isFocused();
final boolean isVisible = w.isVisibleLw();
if (mAddRecentsAnimationInputConsumerHandle) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 4dbd858..1eae567 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -373,7 +373,7 @@
: null;
final Rect contentInsets;
if (mTargetAppToken != null && mTargetAppToken.findMainWindow() != null) {
- contentInsets = mTargetAppToken.findMainWindow().mContentInsets;
+ contentInsets = mTargetAppToken.findMainWindow().getContentInsets();
} else {
// If the window for the activity had not yet been created, use the display insets.
mService.getStableInsets(mDisplayId, mTmpRect);
@@ -583,7 +583,8 @@
if (mainWindow == null) {
return null;
}
- final Rect insets = new Rect(mainWindow.mContentInsets);
+ final Rect insets = new Rect();
+ mainWindow.getContentInsets(insets);
InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
!topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 67ef471..00422e3 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -305,7 +305,8 @@
|| mCapturedLeash == null) {
return null;
}
- final Rect insets = new Rect(mainWindow.mContentInsets);
+ final Rect insets = new Rect();
+ mainWindow.getContentInsets(insets);
InsetUtils.addInsets(insets, mAppWindowToken.getLetterboxInsets());
mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
mCapturedLeash, !mAppWindowToken.fillsParent(),
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 6c8572a..b7507a4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -303,7 +303,7 @@
private Rect getInsets(WindowState state) {
// XXX(b/72757033): These are insets relative to the window frame, but we're really
// interested in the insets relative to the task bounds.
- final Rect insets = minRect(state.mContentInsets, state.mStableInsets);
+ final Rect insets = minRect(state.getContentInsets(), state.getStableInsets());
InsetUtils.addInsets(insets, state.mAppToken.getLetterboxInsets());
return insets;
}
@@ -373,7 +373,7 @@
node.setClipToBounds(false);
final DisplayListCanvas c = node.start(width, height);
c.drawColor(color);
- decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
+ decorPainter.setInsets(mainWindow.getContentInsets(), mainWindow.getStableInsets());
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
node.end(c);
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
@@ -383,7 +383,7 @@
// Note, the app theme snapshot is never translucent because we enforce a non-translucent
// color above
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
- topChild.getConfiguration().orientation, mainWindow.mStableInsets,
+ topChild.getConfiguration().orientation, mainWindow.getStableInsets(),
ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
false /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
false);
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 228bfad..9381fc6 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -18,20 +18,27 @@
import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME;
import static com.android.server.wm.WindowFramesProto.CONTENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.CONTENT_INSETS;
import static com.android.server.wm.WindowFramesProto.CUTOUT;
import static com.android.server.wm.WindowFramesProto.DECOR_FRAME;
import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME;
import static com.android.server.wm.WindowFramesProto.FRAME;
+import static com.android.server.wm.WindowFramesProto.OUTSETS;
import static com.android.server.wm.WindowFramesProto.OUTSET_FRAME;
import static com.android.server.wm.WindowFramesProto.OVERSCAN_FRAME;
+import static com.android.server.wm.WindowFramesProto.OVERSCAN_INSETS;
import static com.android.server.wm.WindowFramesProto.PARENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.STABLE_INSETS;
import static com.android.server.wm.WindowFramesProto.VISIBLE_FRAME;
+import static com.android.server.wm.WindowFramesProto.VISIBLE_INSETS;
import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayCutout;
+import android.view.WindowManager;
+import com.android.server.wm.utils.InsetUtils;
import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
@@ -60,7 +67,7 @@
*
* TODO(b/111611553): The name is unclear and most likely should be swapped with
* {@link #mParentFrame}
- */
+ */
public final Rect mDisplayFrame = new Rect();
/**
@@ -118,6 +125,12 @@
*/
final Rect mLastFrame = new Rect();
+ private boolean mFrameSizeChanged = false;
+
+ // Frame that is scaled to the application's coordinate space when in
+ // screen size compatibility mode.
+ final Rect mCompatFrame = new Rect();
+
/**
* Whether the parent frame would have been different if there was no display cutout.
*/
@@ -131,7 +144,52 @@
/**
* The last cutout that has been reported to the client.
*/
- WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+ private WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+
+ private boolean mDisplayCutoutChanged;
+
+ /**
+ * Insets that determine the area covered by the display overscan region. These are in the
+ * application's coordinate space (without compatibility scale applied).
+ */
+ final Rect mOverscanInsets = new Rect();
+ final Rect mLastOverscanInsets = new Rect();
+ private boolean mOverscanInsetsChanged;
+
+ /**
+ * Insets that determine the area covered by the stable system windows. These are in the
+ * application's coordinate space (without compatibility scale applied).
+ */
+ final Rect mStableInsets = new Rect();
+ final Rect mLastStableInsets = new Rect();
+ private boolean mStableInsetsChanged;
+
+ /**
+ * Outsets determine the area outside of the surface where we want to pretend that it's possible
+ * to draw anyway.
+ */
+ final Rect mOutsets = new Rect();
+ final Rect mLastOutsets = new Rect();
+ private boolean mOutsetsChanged = false;
+
+ /**
+ * Insets that determine the actually visible area. These are in the application's
+ * coordinate space (without compatibility scale applied).
+ */
+ final Rect mVisibleInsets = new Rect();
+ final Rect mLastVisibleInsets = new Rect();
+ private boolean mVisibleInsetsChanged;
+
+ /**
+ * Insets that are covered by system windows (such as the status bar) and
+ * transient docking windows (such as the IME). These are in the application's
+ * coordinate space (without compatibility scale applied).
+ */
+ final Rect mContentInsets = new Rect();
+ final Rect mLastContentInsets = new Rect();
+ private boolean mContentInsetsChanged;
+
+ private final Rect mTmpRect = new Rect();
public WindowFrames() {
}
@@ -171,15 +229,141 @@
/**
* @return true if the width or height has changed since last reported to the client.
*/
- boolean didFrameSizeChange() {
+ private boolean didFrameSizeChange() {
return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
}
/**
- * @return true if the display cutout has changed since last reported to the client.
+ * Calculates the outsets for this windowFrame. The outsets are calculated by the area between
+ * the {@link #mOutsetFrame} and the {@link #mContentFrame}. If there are no outsets, then
+ * {@link #mOutsets} is set to empty.
+ *
+ * @param hasOutsets Whether this frame has outsets.
*/
- boolean didDisplayCutoutChange() {
- return !mLastDisplayCutout.equals(mDisplayCutout);
+ void calculateOutsets(boolean hasOutsets) {
+ if (hasOutsets) {
+ InsetUtils.insetsBetweenFrames(mOutsetFrame, mContentFrame, mOutsets);
+ } else {
+ mOutsets.setEmpty();
+ }
+ }
+
+ /**
+ * Calculate the insets for the type {@link WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
+ *
+ * @param cutoutInsets The insets for the cutout.
+ */
+ void calculateDockedDividerInsets(Rect cutoutInsets) {
+ // For the docked divider, we calculate the stable insets like a full-screen window
+ // so it can use it to calculate the snap positions.
+ mTmpRect.set(mDisplayFrame);
+ mTmpRect.inset(cutoutInsets);
+ mTmpRect.intersectUnchecked(mStableFrame);
+ InsetUtils.insetsBetweenFrames(mDisplayFrame, mTmpRect, mStableInsets);
+
+ // The divider doesn't care about insets in any case, so set it to empty so we don't
+ // trigger a relayout when moving it.
+ mContentInsets.setEmpty();
+ mVisibleInsets.setEmpty();
+ mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+ }
+
+ /**
+ * Calculate the insets for a window.
+ *
+ * @param windowsAreFloating Whether the window is in a floating task such as pinned or
+ * freeform
+ * @param inFullscreenContainer Whether the window is in a container that takes up the screen's
+ * entire space
+ * @param windowBounds The bounds for the window
+ */
+ void calculateInsets(boolean windowsAreFloating, boolean inFullscreenContainer,
+ Rect windowBounds) {
+ // Override right and/or bottom insets in case if the frame doesn't fit the screen in
+ // non-fullscreen mode.
+ boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
+ && mFrame.right > windowBounds.right;
+ boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
+ && mFrame.bottom > windowBounds.bottom;
+
+ mTmpRect.set(mFrame.left, mFrame.top, overrideRightInset ? mTmpRect.right : mFrame.right,
+ overrideBottomInset ? mTmpRect.bottom : mFrame.bottom);
+
+ InsetUtils.insetsBetweenFrames(mTmpRect, mContentFrame, mContentInsets);
+ InsetUtils.insetsBetweenFrames(mTmpRect, mVisibleFrame, mVisibleInsets);
+ InsetUtils.insetsBetweenFrames(mTmpRect, mStableFrame, mStableInsets);
+ }
+
+ /**
+ * Scales all the insets by a specific amount.
+ *
+ * @param scale The amount to scale the insets by.
+ */
+ void scaleInsets(float scale) {
+ mOverscanInsets.scale(scale);
+ mContentInsets.scale(scale);
+ mVisibleInsets.scale(scale);
+ mStableInsets.scale(scale);
+ mOutsets.scale(scale);
+ }
+
+ void offsetFrames(int layoutXDiff, int layoutYDiff) {
+ mFrame.offset(layoutXDiff, layoutYDiff);
+ mContentFrame.offset(layoutXDiff, layoutYDiff);
+ mVisibleFrame.offset(layoutXDiff, layoutYDiff);
+ mStableFrame.offset(layoutXDiff, layoutYDiff);
+ }
+
+ /**
+ * Updates info about whether the size of the window has changed since last reported.
+ *
+ * @return true if info about size has changed since last reported.
+ */
+ boolean setReportResizeHints() {
+ mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
+ mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
+ mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
+ mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
+ mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
+ mFrameSizeChanged |= didFrameSizeChange();
+ mDisplayCutoutChanged |= !mLastDisplayCutout.equals(mDisplayCutout);
+ return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
+ || mStableInsetsChanged || mOutsetsChanged || mFrameSizeChanged
+ || mDisplayCutoutChanged;
+ }
+
+ /**
+ * Resets the insets changed flags so they're all set to false again. This should be called
+ * after the insets are reported to client.
+ */
+ void resetInsetsChanged() {
+ mOverscanInsetsChanged = false;
+ mContentInsetsChanged = false;
+ mVisibleInsetsChanged = false;
+ mStableInsetsChanged = false;
+ mOutsetsChanged = false;
+ mFrameSizeChanged = false;
+ mDisplayCutoutChanged = false;
+ }
+
+ /**
+ * Copy over inset values as the last insets that were sent to the client.
+ */
+ void updateLastInsetValues() {
+ mLastOverscanInsets.set(mOverscanInsets);
+ mLastContentInsets.set(mContentInsets);
+ mLastVisibleInsets.set(mVisibleInsets);
+ mLastStableInsets.set(mStableInsets);
+ mLastOutsets.set(mOutsets);
+ mLastDisplayCutout = mDisplayCutout;
+ }
+
+ /**
+ * Sets the last content insets as (-1, -1, -1, -1) to force the next layout pass to update
+ * the client.
+ */
+ void resetLastContentInsets() {
+ mLastContentInsets.set(-1, -1, -1, -1);
}
public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) {
@@ -194,6 +378,12 @@
mContainingFrame.writeToProto(proto, CONTAINING_FRAME);
mFrame.writeToProto(proto, FRAME);
mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
+ mContentInsets.writeToProto(proto, CONTENT_INSETS);
+ mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
+ mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
+ mStableInsets.writeToProto(proto, STABLE_INSETS);
+ mOutsets.writeToProto(proto, OUTSETS);
+
proto.end(token);
}
@@ -211,5 +401,34 @@
+ " last=" + mLastFrame.toShortString(sTmpSB));
pw.println(prefix + " cutout=" + mDisplayCutout.getDisplayCutout()
+ " last=" + mLastDisplayCutout.getDisplayCutout());
+ pw.print(prefix + "Cur insets: overscan=" + mOverscanInsets.toShortString(sTmpSB)
+ + " content=" + mContentInsets.toShortString(sTmpSB)
+ + " visible=" + mVisibleInsets.toShortString(sTmpSB)
+ + " stable=" + mStableInsets.toShortString(sTmpSB)
+ + " outsets=" + mOutsets.toShortString(sTmpSB));
+ pw.println(prefix + "Lst insets: overscan=" + mLastOverscanInsets.toShortString(sTmpSB)
+ + " content=" + mLastContentInsets.toShortString(sTmpSB)
+ + " visible=" + mLastVisibleInsets.toShortString(sTmpSB)
+ + " stable=" + mLastStableInsets.toShortString(sTmpSB)
+ + " outset=" + mLastOutsets.toShortString(sTmpSB));
+ }
+
+ String getInsetsInfo() {
+ return "ci=" + mContentInsets.toShortString()
+ + " vi=" + mVisibleInsets.toShortString()
+ + " si=" + mStableInsets.toShortString()
+ + " of=" + mOutsets.toShortString();
+ }
+
+ String getInsetsChangedInfo() {
+ return "contentInsetsChanged=" + mContentInsetsChanged
+ + " " + mContentInsets.toShortString()
+ + " visibleInsetsChanged=" + mVisibleInsetsChanged
+ + " " + mVisibleInsets.toShortString()
+ + " stableInsetsChanged=" + mStableInsetsChanged
+ + " " + mStableInsets.toShortString()
+ + " outsetsChanged=" + mOutsetsChanged
+ + " " + mOutsets.toShortString()
+ + " displayCutoutChanged=" + mDisplayCutoutChanged;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2a381ac..679e0d8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2168,14 +2168,10 @@
// The last inset values represent the last client state.
win.updateLastInsetValues();
- outFrame.set(win.mCompatFrame);
- outOverscanInsets.set(win.mOverscanInsets);
- outContentInsets.set(win.mContentInsets);
- win.mLastRelayoutContentInsets.set(win.mContentInsets);
- outVisibleInsets.set(win.mVisibleInsets);
- outStableInsets.set(win.mStableInsets);
+ win.getCompatFrame(outFrame);
+ win.getInsetsForRelayout(outOverscanInsets, outContentInsets, outVisibleInsets,
+ outStableInsets, outOutsets);
outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
- outOutsets.set(win.mOutsets);
outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
if (localLOGV) Slog.v(
TAG_WM, "Relayout given client " + client.asBinder()
@@ -6008,11 +6004,10 @@
}
@Override
- public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
+ public void createInputConsumer(IBinder token, String name, int displayId,
+ InputChannel inputChannel) {
synchronized (mWindowMap) {
- // TODO(b/112049699): Fix this for multiple displays. There is only one inputChannel
- // here to accept the return value.
- DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+ DisplayContent display = mRoot.getDisplayContent(displayId);
if (display != null) {
display.getInputMonitor().createInputConsumer(token, name, inputChannel,
Binder.getCallingPid(), Binder.getCallingUserHandle());
@@ -6021,11 +6016,9 @@
}
@Override
- public boolean destroyInputConsumer(String name) {
+ public boolean destroyInputConsumer(String name, int displayId) {
synchronized (mWindowMap) {
- // TODO(b/112049699): Fix this for multiple displays. For consistency with
- // createInputConsumer above.
- DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+ DisplayContent display = mRoot.getDisplayContent(displayId);
if (display != null) {
return display.getInputMonitor().destroyInputConsumer(name);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 466e298..637c0ea 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -120,7 +120,6 @@
import static com.android.server.wm.WindowStateProto.ANIMATOR;
import static com.android.server.wm.WindowStateProto.ATTRIBUTES;
import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS;
-import static com.android.server.wm.WindowStateProto.CONTENT_INSETS;
import static com.android.server.wm.WindowStateProto.DESTROYING;
import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
import static com.android.server.wm.WindowStateProto.FINISHED_SEAMLESS_ROTATION_FRAME;
@@ -131,20 +130,16 @@
import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
-import static com.android.server.wm.WindowStateProto.OUTSETS;
-import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION;
import static com.android.server.wm.WindowStateProto.REMOVED;
import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH;
-import static com.android.server.wm.WindowStateProto.STABLE_INSETS;
import static com.android.server.wm.WindowStateProto.STACK_ID;
import static com.android.server.wm.WindowStateProto.SURFACE_INSETS;
import static com.android.server.wm.WindowStateProto.SURFACE_POSITION;
import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY;
import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
-import static com.android.server.wm.WindowStateProto.VISIBLE_INSETS;
import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
@@ -200,6 +195,7 @@
import com.android.server.input.InputWindowHandle;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import com.android.server.wm.utils.InsetUtils;
import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
@@ -309,22 +305,6 @@
private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration();
/**
- * Insets that determine the actually visible area. These are in the application's
- * coordinate space (without compatibility scale applied).
- */
- final Rect mVisibleInsets = new Rect();
- private final Rect mLastVisibleInsets = new Rect();
- private boolean mVisibleInsetsChanged;
-
- /**
- * Insets that are covered by system windows (such as the status bar) and
- * transient docking windows (such as the IME). These are in the application's
- * coordinate space (without compatibility scale applied).
- */
- final Rect mContentInsets = new Rect();
- final Rect mLastContentInsets = new Rect();
-
- /**
* The last content insets returned to the client in relayout. We use
* these in the bounds animation to ensure we only observe inset changes
* at the same time that a client resizes it's surface so that we may use
@@ -333,34 +313,6 @@
*/
final Rect mLastRelayoutContentInsets = new Rect();
- private boolean mContentInsetsChanged;
-
- /**
- * Insets that determine the area covered by the display overscan region. These are in the
- * application's coordinate space (without compatibility scale applied).
- */
- final Rect mOverscanInsets = new Rect();
- private final Rect mLastOverscanInsets = new Rect();
- private boolean mOverscanInsetsChanged;
-
- /**
- * Insets that determine the area covered by the stable system windows. These are in the
- * application's coordinate space (without compatibility scale applied).
- */
- final Rect mStableInsets = new Rect();
- private final Rect mLastStableInsets = new Rect();
- private boolean mStableInsetsChanged;
-
- /**
- * Outsets determine the area outside of the surface where we want to pretend that it's possible
- * to draw anyway.
- */
- final Rect mOutsets = new Rect();
- private final Rect mLastOutsets = new Rect();
- private boolean mOutsetsChanged = false;
-
- private boolean mDisplayCutoutChanged;
-
/**
* Set to true if we are waiting for this window to receive its
* given internal insets before laying out other windows based on it.
@@ -399,11 +351,6 @@
float mLastHScale=1, mLastVScale=1;
final Matrix mTmpMatrix = new Matrix();
- private boolean mFrameSizeChanged = false;
- // Frame that is scaled to the application's coordinate space when in
- // screen size compatibility mode.
- final Rect mCompatFrame = new Rect();
-
private final WindowFrames mWindowFrames = new WindowFrames();
/**
@@ -988,17 +935,7 @@
applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
// Calculate the outsets before the content frame gets shrinked to the window frame.
- if (hasOutsets) {
- mOutsets.set(
- Math.max(mWindowFrames.mContentFrame.left - mWindowFrames.mOutsetFrame.left, 0),
- Math.max(mWindowFrames.mContentFrame.top - mWindowFrames.mOutsetFrame.top, 0),
- Math.max(mWindowFrames.mOutsetFrame.right - mWindowFrames.mContentFrame.right,
- 0),
- Math.max(mWindowFrames.mOutsetFrame.bottom - mWindowFrames.mContentFrame.bottom,
- 0));
- } else {
- mOutsets.set(0, 0, 0, 0);
- }
+ mWindowFrames.calculateOutsets(hasOutsets);
// Make sure the content and visible frames are inside of the
// final window frame.
@@ -1055,90 +992,35 @@
if (inFullscreenContainer && !windowsAreFloating) {
// Windows that are not fullscreen can be positioned outside of the display frame,
// but that is not a reason to provide them with overscan insets.
- mOverscanInsets.set(
- Math.max(mWindowFrames.mOverscanFrame.left - layoutContainingFrame.left, 0),
- Math.max(mWindowFrames.mOverscanFrame.top - layoutContainingFrame.top, 0),
- Math.max(layoutContainingFrame.right - mWindowFrames.mOverscanFrame.right, 0),
- Math.max(layoutContainingFrame.bottom - mWindowFrames.mOverscanFrame.bottom,
- 0));
+ InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame,
+ mWindowFrames.mOverscanInsets);
}
if (mAttrs.type == TYPE_DOCK_DIVIDER) {
- // For the docked divider, we calculate the stable insets like a full-screen window
- // so it can use it to calculate the snap positions.
final WmDisplayCutout c = windowFrames.mDisplayCutout.calculateRelativeTo(
mWindowFrames.mDisplayFrame);
- mTmpRect.set(mWindowFrames.mDisplayFrame);
- mTmpRect.inset(c.getDisplayCutout().getSafeInsets());
- mTmpRect.intersectUnchecked(mWindowFrames.mStableFrame);
-
- mStableInsets.set(Math.max(mTmpRect.left - mWindowFrames.mDisplayFrame.left, 0),
- Math.max(mTmpRect.top - mWindowFrames.mDisplayFrame.top, 0),
- Math.max(mWindowFrames.mDisplayFrame.right - mTmpRect.right, 0),
- Math.max(mWindowFrames.mDisplayFrame.bottom - mTmpRect.bottom, 0));
-
- // The divider doesn't care about insets in any case, so set it to empty so we don't
- // trigger a relayout when moving it.
- mContentInsets.setEmpty();
- mVisibleInsets.setEmpty();
- windowFrames.setDisplayCutout(WmDisplayCutout.NO_CUTOUT);
+ mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
} else {
getDisplayContent().getBounds(mTmpRect);
- // Override right and/or bottom insets in case if the frame doesn't fit the screen in
- // non-fullscreen mode.
- boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
- && mWindowFrames.mFrame.right > mTmpRect.right;
- boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
- && mWindowFrames.mFrame.bottom > mTmpRect.bottom;
- mContentInsets.set(mWindowFrames.mContentFrame.left - mWindowFrames.mFrame.left,
- mWindowFrames.mContentFrame.top - mWindowFrames.mFrame.top,
- overrideRightInset ? mTmpRect.right - mWindowFrames.mContentFrame.right
- : mWindowFrames.mFrame.right - mWindowFrames.mContentFrame.right,
- overrideBottomInset ? mTmpRect.bottom - mWindowFrames.mContentFrame.bottom
- : mWindowFrames.mFrame.bottom - mWindowFrames.mContentFrame.bottom);
-
- mVisibleInsets.set(mWindowFrames.mVisibleFrame.left - mWindowFrames.mFrame.left,
- mWindowFrames.mVisibleFrame.top - mWindowFrames.mFrame.top,
- overrideRightInset ? mTmpRect.right - mWindowFrames.mVisibleFrame.right
- : mWindowFrames.mFrame.right - mWindowFrames.mVisibleFrame.right,
- overrideBottomInset ? mTmpRect.bottom - mWindowFrames.mVisibleFrame.bottom
- : mWindowFrames.mFrame.bottom - mWindowFrames.mVisibleFrame.bottom);
-
- mStableInsets.set(
- Math.max(mWindowFrames.mStableFrame.left - mWindowFrames.mFrame.left, 0),
- Math.max(mWindowFrames.mStableFrame.top - mWindowFrames.mFrame.top, 0),
- overrideRightInset ? Math.max(mTmpRect.right - mWindowFrames.mStableFrame.right,
- 0) : Math.max(
- mWindowFrames.mFrame.right - mWindowFrames.mStableFrame.right, 0),
- overrideBottomInset ? Math.max(
- mTmpRect.bottom - mWindowFrames.mStableFrame.bottom, 0) : Math.max(
- mWindowFrames.mFrame.bottom - mWindowFrames.mStableFrame.bottom, 0));
+ mWindowFrames.calculateInsets(windowsAreFloating, inFullscreenContainer, mTmpRect);
}
mWindowFrames.setDisplayCutout(
windowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame));
// Offset the actual frame by the amount layout frame is off.
- mWindowFrames.mFrame.offset(-layoutXDiff, -layoutYDiff);
- mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
- mWindowFrames.mContentFrame.offset(-layoutXDiff, -layoutYDiff);
- mWindowFrames.mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
- mWindowFrames.mStableFrame.offset(-layoutXDiff, -layoutYDiff);
+ mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
- mCompatFrame.set(mWindowFrames.mFrame);
+ mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
if (mEnforceSizeCompat) {
// If there is a size compatibility scale being applied to the
// window, we need to apply this to its insets so that they are
// reported to the app in its coordinate space.
- mOverscanInsets.scale(mInvGlobalScale);
- mContentInsets.scale(mInvGlobalScale);
- mVisibleInsets.scale(mInvGlobalScale);
- mStableInsets.scale(mInvGlobalScale);
- mOutsets.scale(mInvGlobalScale);
+ mWindowFrames.scaleInsets(mInvGlobalScale);
// Also the scaled frame that we report to the app needs to be
// adjusted to be in its coordinate space.
- mCompatFrame.scale(mInvGlobalScale);
+ mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
}
if (mIsWallpaper && (fw != mWindowFrames.mFrame.width()
@@ -1156,10 +1038,7 @@
+ mRequestedWidth + ", mRequestedheight="
+ mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ "): frame=" + mWindowFrames.mFrame.toShortString()
- + " ci=" + mContentInsets.toShortString()
- + " vi=" + mVisibleInsets.toShortString()
- + " si=" + mStableInsets.toShortString()
- + " of=" + mOutsets.toShortString());
+ + " " + mWindowFrames.getInsetsInfo());
}
// TODO: Look into whether this override is still necessary.
@@ -1219,6 +1098,14 @@
return mWindowFrames.mDisplayCutout;
}
+ void getCompatFrame(Rect outFrame) {
+ outFrame.set(mWindowFrames.mCompatFrame);
+ }
+
+ void getCompatFrameSize(Rect outFrame) {
+ outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height());
+ }
+
@Override
public boolean getGivenInsetsPendingLw() {
return mGivenInsetsPending;
@@ -1270,15 +1157,7 @@
}
boolean setReportResizeHints() {
- mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
- mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
- mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
- mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
- mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
- mFrameSizeChanged |= mWindowFrames.didFrameSizeChange();
- mDisplayCutoutChanged |= mWindowFrames.didDisplayCutoutChange();
- return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
- || mOutsetsChanged || mFrameSizeChanged || mDisplayCutoutChanged;
+ return mWindowFrames.setReportResizeHints();
}
/**
@@ -1301,7 +1180,7 @@
return;
}
- setReportResizeHints();
+ boolean didFrameInsetsChange = setReportResizeHints();
boolean configChanged = isConfigChanged();
if (DEBUG_CONFIGURATION && configChanged) {
Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
@@ -1318,31 +1197,18 @@
// variables, because mFrameSizeChanged only tracks the width and height changing.
mWindowFrames.mLastFrame.set(mWindowFrames.mFrame);
- if (mContentInsetsChanged
- || mVisibleInsetsChanged
- || mStableInsetsChanged
+ if (didFrameInsetsChange
|| winAnimator.mSurfaceResized
- || mOutsetsChanged
- || mFrameSizeChanged
- || mDisplayCutoutChanged
|| configChanged
|| dragResizingChanged
|| mReportOrientationChanged) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
Slog.v(TAG_WM, "Resize reasons for w=" + this + ": "
- + " contentInsetsChanged=" + mContentInsetsChanged
- + " " + mContentInsets.toShortString()
- + " visibleInsetsChanged=" + mVisibleInsetsChanged
- + " " + mVisibleInsets.toShortString()
- + " stableInsetsChanged=" + mStableInsetsChanged
- + " " + mStableInsets.toShortString()
- + " outsetsChanged=" + mOutsetsChanged
- + " " + mOutsets.toShortString()
+ + " " + mWindowFrames.getInsetsChangedInfo()
+ " surfaceResized=" + winAnimator.mSurfaceResized
+ " configChanged=" + configChanged
+ " dragResizingChanged=" + dragResizingChanged
- + " reportOrientationChanged=" + mReportOrientationChanged
- + " displayCutoutChanged=" + mDisplayCutoutChanged);
+ + " reportOrientationChanged=" + mReportOrientationChanged);
}
// If it's a dead window left on screen, and the configuration changed, there is nothing
@@ -3015,7 +2881,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
- + ": " + mCompatFrame);
+ + ": " + mWindowFrames.mCompatFrame);
final MergedConfiguration mergedConfiguration =
new MergedConfiguration(mService.mRoot.getConfiguration(),
getMergedOverrideConfiguration());
@@ -3026,11 +2892,11 @@
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
final Rect frame = mWindowFrames.mFrame;
- final Rect overscanInsets = mLastOverscanInsets;
- final Rect contentInsets = mLastContentInsets;
- final Rect visibleInsets = mLastVisibleInsets;
- final Rect stableInsets = mLastStableInsets;
- final Rect outsets = mLastOutsets;
+ final Rect overscanInsets = mWindowFrames.mLastOverscanInsets;
+ final Rect contentInsets = mWindowFrames.mLastContentInsets;
+ final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
+ final Rect stableInsets = mWindowFrames.mLastStableInsets;
+ final Rect outsets = mWindowFrames.mLastOutsets;
final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
final boolean reportOrientation = mReportOrientationChanged;
final int displayId = getDisplayId();
@@ -3061,13 +2927,7 @@
mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
- mOverscanInsetsChanged = false;
- mContentInsetsChanged = false;
- mVisibleInsetsChanged = false;
- mStableInsetsChanged = false;
- mOutsetsChanged = false;
- mFrameSizeChanged = false;
- mDisplayCutoutChanged = false;
+ mWindowFrames.resetInsetsChanged();
mWinAnimator.mSurfaceResized = false;
mReportOrientationChanged = false;
} catch (RemoteException e) {
@@ -3293,7 +3153,6 @@
mAttrs.writeToProto(proto, ATTRIBUTES);
mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS);
mWindowFrames.writeToProto(proto, WINDOW_FRAMES);
- mContentInsets.writeToProto(proto, CONTENT_INSETS);
mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS);
mSurfacePosition.writeToProto(proto, SURFACE_POSITION);
mWinAnimator.writeToProto(proto, ANIMATOR);
@@ -3307,10 +3166,6 @@
proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
proto.write(HAS_SURFACE, mHasSurface);
proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay());
- mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
- mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
- mStableInsets.writeToProto(proto, STABLE_INSETS);
- mOutsets.writeToProto(proto, OUTSETS);
proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
proto.write(DESTROYING, mDestroying);
proto.write(REMOVED, mRemoved);
@@ -3417,21 +3272,11 @@
+ " isReadyForDisplay()=" + isReadyForDisplay()
+ " mWindowRemovalAllowed=" + mWindowRemovalAllowed);
if (mEnforceSizeCompat) {
- pw.println(prefix + "mCompatFrame=" + mCompatFrame.toShortString(sTmpSB));
+ pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB));
}
if (dumpAll) {
mWindowFrames.dump(pw, prefix);
- pw.print(prefix + "Cur insets: overscan=" + mOverscanInsets.toShortString(sTmpSB)
- + " content=" + mContentInsets.toShortString(sTmpSB)
- + " visible=" + mVisibleInsets.toShortString(sTmpSB)
- + " stable=" + mStableInsets.toShortString(sTmpSB)
- + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB)
- + " outsets=" + mOutsets.toShortString(sTmpSB));
- pw.println(prefix + "Lst insets: overscan=" + mLastOverscanInsets.toShortString(sTmpSB)
- + " content=" + mLastContentInsets.toShortString(sTmpSB)
- + " visible=" + mLastVisibleInsets.toShortString(sTmpSB)
- + " stable=" + mLastStableInsets.toShortString(sTmpSB)
- + " outset=" + mLastOutsets.toShortString(sTmpSB));
+ pw.println(prefix + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB));
}
super.dump(pw, prefix, dumpAll);
pw.println(prefix + mWinAnimator + ":");
@@ -3531,7 +3376,7 @@
}
}
- void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
+ private void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
final int pw = containingFrame.width();
final int ph = containingFrame.height();
final Task task = getTask();
@@ -3609,10 +3454,10 @@
// We need to make sure we update the CompatFrame as it is used for
// cropping decisions, etc, on systems where we lack a decor layer.
- mCompatFrame.set(mWindowFrames.mFrame);
+ mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
if (mEnforceSizeCompat) {
// See comparable block in computeFrameLw.
- mCompatFrame.scale(mInvGlobalScale);
+ mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
}
}
@@ -4322,13 +4167,15 @@
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
// TODO(multi-display)
- policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
- policyCrop.intersect(-mCompatFrame.left, -mCompatFrame.top,
- displayInfo.logicalWidth - mCompatFrame.left,
- displayInfo.logicalHeight - mCompatFrame.top);
+ policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
+ mWindowFrames.mCompatFrame.height());
+ policyCrop.intersect(-mWindowFrames.mCompatFrame.left, -mWindowFrames.mCompatFrame.top,
+ displayInfo.logicalWidth - mWindowFrames.mCompatFrame.left,
+ displayInfo.logicalHeight - mWindowFrames.mCompatFrame.top);
} else if (skipDecorCrop()) {
// Windows without policy decor aren't cropped.
- policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
+ policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
+ mWindowFrames.mCompatFrame.height());
} else {
// Crop to the system decor specified by policy.
calculateSystemDecorRect(policyCrop);
@@ -4486,12 +4333,7 @@
* Updates the last inset values to the current ones.
*/
void updateLastInsetValues() {
- mLastOverscanInsets.set(mOverscanInsets);
- mLastContentInsets.set(mContentInsets);
- mLastVisibleInsets.set(mVisibleInsets);
- mLastStableInsets.set(mStableInsets);
- mLastOutsets.set(mOutsets);
- mWindowFrames.mLastDisplayCutout = mWindowFrames.mDisplayCutout;
+ mWindowFrames.updateLastInsetValues();
}
void startAnimation(Animation anim) {
@@ -4880,6 +4722,44 @@
}
}
+ /**
+ * Copy the inset values over so they can be sent back to the client when a relayout occurs.
+ */
+ void getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
+ Rect outStableInsets, Rect outOutsets) {
+ outOverscanInsets.set(mWindowFrames.mOverscanInsets);
+ outContentInsets.set(mWindowFrames.mContentInsets);
+ outVisibleInsets.set(mWindowFrames.mVisibleInsets);
+ outStableInsets.set(mWindowFrames.mStableInsets);
+ outOutsets.set(mWindowFrames.mOutsets);
+
+ mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets);
+ }
+
+ void getContentInsets(Rect outContentInsets) {
+ outContentInsets.set(mWindowFrames.mContentInsets);
+ }
+
+ Rect getContentInsets() {
+ return mWindowFrames.mContentInsets;
+ }
+
+ void getStableInsets(Rect outStableInsets) {
+ outStableInsets.set(mWindowFrames.mStableInsets);
+ }
+
+ Rect getStableInsets() {
+ return mWindowFrames.mStableInsets;
+ }
+
+ void resetLastContentInsets() {
+ mWindowFrames.resetLastContentInsets();
+ }
+
+ Rect getVisibleInsets() {
+ return mWindowFrames.mVisibleInsets;
+ }
+
private final class MoveAnimationSpec implements AnimationSpec {
private final long mDuration;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b158ae2..c80eb86 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -24,6 +24,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_NONE;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
@@ -46,7 +47,6 @@
import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
import android.content.Context;
import android.graphics.Matrix;
@@ -476,8 +476,7 @@
flags |= SurfaceControl.SECURE;
}
- mTmpSize.set(0, 0, 0, 0);
- calculateSurfaceBounds(w, attrs);
+ calculateSurfaceBounds(w, attrs, mTmpSize);
final int width = mTmpSize.width();
final int height = mTmpSize.height();
@@ -556,44 +555,38 @@
return mSurfaceController;
}
- private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) {
+ private void calculateSurfaceBounds(WindowState w, LayoutParams attrs, Rect outSize) {
+ outSize.setEmpty();
if ((attrs.flags & FLAG_SCALED) != 0) {
// For a scaled surface, we always want the requested size.
- mTmpSize.right = mTmpSize.left + w.mRequestedWidth;
- mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight;
+ outSize.right = w.mRequestedWidth;
+ outSize.bottom = w.mRequestedHeight;
} else {
// When we're doing a drag-resizing, request a surface that's fullscreen size,
// so that we don't need to reallocate during the process. This also prevents
// buffer drops due to size mismatch.
if (w.isDragResizing()) {
- if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) {
- mTmpSize.left = 0;
- mTmpSize.top = 0;
- }
final DisplayInfo displayInfo = w.getDisplayInfo();
- mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth;
- mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight;
+ outSize.right = displayInfo.logicalWidth;
+ outSize.bottom = displayInfo.logicalHeight;
} else {
- mTmpSize.right = mTmpSize.left + w.mCompatFrame.width();
- mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height();
+ w.getCompatFrameSize(outSize);
}
}
// Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
// This doesn't necessarily mean that there is an error in the system. The sizes might be
// incorrect, because it is before the first layout or draw.
- if (mTmpSize.width() < 1) {
- mTmpSize.right = mTmpSize.left + 1;
+ if (outSize.width() < 1) {
+ outSize.right = 1;
}
- if (mTmpSize.height() < 1) {
- mTmpSize.bottom = mTmpSize.top + 1;
+ if (outSize.height() < 1) {
+ outSize.bottom = 1;
}
// Adjust for surface insets.
- mTmpSize.left -= attrs.surfaceInsets.left;
- mTmpSize.top -= attrs.surfaceInsets.top;
- mTmpSize.right += attrs.surfaceInsets.right;
- mTmpSize.bottom += attrs.surfaceInsets.bottom;
+ outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top,
+ -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom);
}
boolean hasSurface() {
@@ -870,8 +863,7 @@
final LayoutParams attrs = mWin.getAttrs();
final Task task = w.getTask();
- mTmpSize.set(0, 0, 0, 0);
- calculateSurfaceBounds(w, attrs);
+ calculateSurfaceBounds(w, attrs, mTmpSize);
mExtraHScale = (float) 1.0;
mExtraVScale = (float) 1.0;
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index b467d61..42ade38 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -210,7 +210,7 @@
const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
- void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
+ void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
void setInputDispatchMode(bool enabled, bool frozen);
void setSystemUiVisibility(int32_t visibility);
@@ -736,7 +736,8 @@
}
}
-void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray,
+ int32_t displayId) {
Vector<sp<InputWindowHandle> > windowHandles;
if (windowHandleObjArray) {
@@ -756,7 +757,7 @@
}
}
- mInputManager->getDispatcher()->setInputWindows(windowHandles);
+ mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId);
// Do this after the dispatcher has updated the window handle state.
bool newPointerGesturesEnabled = true;
@@ -1446,10 +1447,10 @@
}
static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
- jlong ptr, jobjectArray windowHandleObjArray) {
+ jlong ptr, jobjectArray windowHandleObjArray, jint displayId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- im->setInputWindows(env, windowHandleObjArray);
+ im->setInputWindows(env, windowHandleObjArray, displayId);
}
static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
@@ -1678,7 +1679,7 @@
(void*) nativeInjectInputEvent },
{ "nativeToggleCapsLock", "(JI)V",
(void*) nativeToggleCapsLock },
- { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
+ { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;I)V",
(void*) nativeSetInputWindows },
{ "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
(void*) nativeSetFocusedApplication },
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4664601..0b6a33f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -743,6 +743,11 @@
traceEnd();
}
+ // Tracks and caches the device state.
+ traceBeginAndSlog("StartCachedDeviceStateService");
+ mSystemServiceManager.startService(CachedDeviceStateService.class);
+ traceEnd();
+
// Tracks cpu time spent in binder calls
traceBeginAndSlog("StartBinderCallsStatsService");
mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 3cdef1e..ccc092d 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -1385,6 +1385,20 @@
private boolean startIpReachabilityMonitor() {
try {
+ // TODO: Fetch these parameters from settings, and install a
+ // settings observer to watch for update and re-program these
+ // parameters (Q: is this level of dynamic updatability really
+ // necessary or does reading from settings at startup suffice?).
+ final int NUM_SOLICITS = 5;
+ final int INTER_SOLICIT_INTERVAL_MS = 750;
+ setNeighborParameters(mDependencies.getNetd(), mInterfaceName,
+ NUM_SOLICITS, INTER_SOLICIT_INTERVAL_MS);
+ } catch (Exception e) {
+ mLog.e("Failed to adjust neighbor parameters", e);
+ // Carry on using the system defaults (currently: 3, 1000);
+ }
+
+ try {
mIpReachabilityMonitor = new IpReachabilityMonitor(
mContext,
mInterfaceParams,
@@ -1863,6 +1877,20 @@
}
}
+ private static void setNeighborParameters(
+ INetd netd, String ifName, int num_solicits, int inter_solicit_interval_ms)
+ throws RemoteException, IllegalArgumentException {
+ Preconditions.checkNotNull(netd);
+ Preconditions.checkArgument(!TextUtils.isEmpty(ifName));
+ Preconditions.checkArgument(num_solicits > 0);
+ Preconditions.checkArgument(inter_solicit_interval_ms > 0);
+
+ for (int family : new Integer[]{INetd.IPV4, INetd.IPV6}) {
+ netd.setProcSysNet(family, INetd.NEIGH, ifName, "retrans_time_ms", Integer.toString(inter_solicit_interval_ms));
+ netd.setProcSysNet(family, INetd.NEIGH, ifName, "ucast_solicit", Integer.toString(num_solicits));
+ }
+ }
+
// TODO: extract out into CollectionUtils.
static <T> boolean any(Iterable<T> coll, Predicate<T> fn) {
for (T t : coll) {
diff --git a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
new file mode 100644
index 0000000..81107cf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 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 com.android.server;
+
+
+import static org.mockito.Mockito.when;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.IPowerManager;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
+import android.os.RemoteException;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link CachedDeviceStateService}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class CachedDeviceStateServiceTest {
+ @Mock private BatteryManagerInternal mBatteryManager;
+ @Mock private IPowerManager mPowerManager;
+ private BroadcastInterceptingContext mContext;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ Context context = InstrumentationRegistry.getContext();
+ PowerManager powerManager = new PowerManager(context, mPowerManager, null);
+ mContext = new BroadcastInterceptingContext(context) {
+ @Override
+ public Object getSystemService(String name) {
+ switch (name) {
+ case Context.POWER_SERVICE:
+ return powerManager;
+ default:
+ return super.getSystemService(name);
+ }
+ }
+ };
+
+ LocalServices.addService(BatteryManagerInternal.class, mBatteryManager);
+
+ when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ }
+
+ @After
+ public void tearDown() {
+ // Added by the CachedDeviceStateService.onStart().
+ LocalServices.removeServiceForTest(CachedDeviceState.Readonly.class);
+
+ // Added in @Before.
+ LocalServices.removeServiceForTest(BatteryManagerInternal.class);
+ }
+
+ @Test
+ public void correctlyReportsScreenInteractive() throws RemoteException {
+ CachedDeviceStateService service = new CachedDeviceStateService(mContext);
+ when(mPowerManager.isInteractive()).thenReturn(true); // Screen on.
+
+ service.onStart();
+ CachedDeviceState.Readonly deviceState =
+ LocalServices.getService(CachedDeviceState.Readonly.class);
+
+ // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY.
+ assertThat(deviceState.isScreenInteractive()).isFalse();
+
+ service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+ assertThat(deviceState.isScreenInteractive()).isTrue();
+
+ mContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+ assertThat(deviceState.isScreenInteractive()).isFalse();
+
+ mContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+ assertThat(deviceState.isScreenInteractive()).isTrue();
+ }
+
+ @Test
+ public void correctlyReportsCharging() {
+ CachedDeviceStateService service = new CachedDeviceStateService(mContext);
+ when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE);
+
+ service.onStart();
+ CachedDeviceState.Readonly deviceState =
+ LocalServices.getService(CachedDeviceState.Readonly.class);
+
+ // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY.
+ assertThat(deviceState.isCharging()).isTrue();
+
+ service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+ assertThat(deviceState.isCharging()).isFalse();
+
+ Intent intentPluggedIn = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ intentPluggedIn.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+ mContext.sendBroadcast(intentPluggedIn);
+ assertThat(deviceState.isCharging()).isTrue();
+
+ Intent intentUnplugged = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ intentUnplugged.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
+ mContext.sendBroadcast(intentUnplugged);
+ assertThat(deviceState.isCharging()).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
index 360ccbf..a3decb9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
@@ -20,6 +20,8 @@
import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Looper;
+import android.support.test.filters.FlakyTest;
+
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -95,6 +97,7 @@
}
@Test
+ @FlakyTest
public void testDetectionActiveCallback_withHandler_shouldPostRunnableToHandler() {
MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
message.getCallback().run();
@@ -142,6 +145,7 @@
}
@Test
+ @FlakyTest
public void testGestureCallback_withHandler_shouldPostRunnableToHandler() {
MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
message.getCallback().run();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
index f9d264b..d6d21c6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -43,6 +43,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.support.test.filters.FlakyTest;
import android.view.MagnificationSpec;
import androidx.test.runner.AndroidJUnit4;
@@ -66,6 +67,7 @@
import java.util.Locale;
@RunWith(AndroidJUnit4.class)
+@FlakyTest
public class MagnificationControllerTest {
static final Rect INITIAL_MAGNIFICATION_BOUNDS = new Rect(0, 0, 100, 200);
static final PointF INITIAL_MAGNIFICATION_BOUNDS_CENTER = new PointF(
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index ea3a3d0..e648230 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -133,15 +133,15 @@
}
private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
- assertRect(w.mContentInsets, left, top, right, bottom);
+ assertRect(w.getContentInsets(), left, top, right, bottom);
}
private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
- assertRect(w.mVisibleInsets, left, top, right, bottom);
+ assertRect(w.getVisibleInsets(), left, top, right, bottom);
}
private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
- assertRect(w.mStableInsets, left, top, right, bottom);
+ assertRect(w.getStableInsets(), left, top, right, bottom);
}
private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 119733e..5e3bac5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2007,20 +2007,21 @@
}
/**
- * Get User downloaded Profiles.
+ * Get opportunistic data Profiles.
*
- * Provide all available user downloaded profile on the phone.
- * @param slotId on which phone the switch will operate on
+ * Provide all available user downloaded profiles on phone which are used only for
+ * opportunistic data.
+ * @param slotIndex slot on which the profiles are queried from.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId) {
+ public List<SubscriptionInfo> getOpportunisticSubscriptions(int slotIndex) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
List<SubscriptionInfo> subInfoList = null;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfoList = iSub.getOpportunisticSubscriptions(slotId, pkgForDebug);
+ subInfoList = iSub.getOpportunisticSubscriptions(slotIndex, pkgForDebug);
}
} catch (RemoteException ex) {
// ignore it
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index abcdeed..b8e4c0e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -64,6 +64,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telecom.ITelecomService;
import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.internal.telephony.IAnas;
import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
@@ -4327,6 +4328,10 @@
return ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));
}
+ private IAnas getIAnas() {
+ return IAnas.Stub.asInterface(ServiceManager.getService("ianas"));
+ }
+
//
//
// PhoneStateListener
@@ -8193,7 +8198,6 @@
return UNKNOWN_CARRIER_ID_LIST_VERSION;
}
-
/**
* How many modems can have simultaneous data connections.
* @hide
@@ -8211,4 +8215,62 @@
}
return 0;
}
+
+ /**
+ * Enable or disable AlternativeNetworkAccessService.
+ *
+ * This method should be called to enable or disable
+ * AlternativeNetworkAccess service on the device.
+ *
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ *
+ * @param enable enable(True) or disable(False)
+ * @return returns true if successfully set.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setAlternativeNetworkAccessState(boolean enable) {
+ String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ boolean ret = false;
+ try {
+ IAnas iAlternativeAccessService = getIAnas();
+ if (iAlternativeAccessService != null) {
+ ret = iAlternativeAccessService.setEnable(enable, pkgForDebug);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "enableAlternativeNetworkAccess RemoteException", ex);
+ }
+
+ return ret;
+ }
+
+ /**
+ * is AlternativeNetworkAccessService enabled
+ *
+ * This method should be called to determine if the AlternativeNetworkAccessService is
+ * enabled
+ *
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public boolean isAlternativeNetworkAccessEnabled() {
+ String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ boolean isEnabled = false;
+
+ try {
+ IAnas iAlternativeAccessService = getIAnas();
+ if (iAlternativeAccessService != null) {
+ isEnabled = iAlternativeAccessService.isEnabled(pkgForDebug);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "enableAlternativeNetworkAccess RemoteException", ex);
+ }
+
+ return isEnabled;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/IAnas.aidl b/telephony/java/com/android/internal/telephony/IAnas.aidl
new file mode 100755
index 0000000..88d681a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IAnas.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.telephony;
+
+
+interface IAnas {
+
+ /**
+ * Enable or disable Alternative Network Access service.
+ *
+ * This method should be called to enable or disable
+ * AlternativeNetworkAccess service on the device.
+ *
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param enable enable(True) or disable(False)
+ * @param callingPackage caller's package name
+ * @return returns true if successfully set.
+ */
+ boolean setEnable(boolean enable, String callingPackage);
+
+ /**
+ * is Alternative Network Access service enabled
+ *
+ * This method should be called to determine if the Alternative Network Access service is enabled
+ *
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param callingPackage caller's package name
+ */
+ boolean isEnabled(String callingPackage);
+}
diff --git a/tools/processors/unsupportedappusage/Android.bp b/tools/processors/unsupportedappusage/Android.bp
index 98f3c95..1aca3ed 100644
--- a/tools/processors/unsupportedappusage/Android.bp
+++ b/tools/processors/unsupportedappusage/Android.bp
@@ -11,5 +11,15 @@
"guava",
"unsupportedappusage-annotation"
],
+ openjdk9: {
+ javacflags: [
+ "--add-modules=jdk.compiler",
+ "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+ "--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+ "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+ "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+ ],
+ },
+
use_tools_jar: true,
}