Merge "Fix a race condition in SeekBarVolumizer." into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 672eb4d9..015c035 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19262,7 +19262,6 @@
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
method public boolean hasSnrInDb();
- method public boolean isPseudorangeRateCorrected();
method public void writeToParcel(android.os.Parcel, int);
field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
field public static final int ADR_STATE_RESET = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index 91d6292..7412908 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -20433,7 +20433,6 @@
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
method public boolean hasSnrInDb();
- method public boolean isPseudorangeRateCorrected();
method public void writeToParcel(android.os.Parcel, int);
field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -25721,9 +25720,11 @@
public class ScoredNetwork implements android.os.Parcelable {
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
+ ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+ field public final boolean meteredHint;
field public final android.net.NetworkKey networkKey;
field public final android.net.RssiCurve rssiCurve;
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 55d6ecd..34c14d4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19292,7 +19292,6 @@
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
method public boolean hasSnrInDb();
- method public boolean isPseudorangeRateCorrected();
method public void reset();
method public void resetCarrierCycles();
method public void resetCarrierFrequencyHz();
@@ -19310,7 +19309,6 @@
method public void setCn0DbHz(double);
method public void setConstellationType(int);
method public void setMultipathIndicator(int);
- method public void setPseudorangeRateCorrected(boolean);
method public void setPseudorangeRateMetersPerSecond(double);
method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
method public void setReceivedSvTimeNanos(long);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a0a599e..cc1d68e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -744,7 +744,7 @@
Activity mParent;
boolean mCalled;
/*package*/ boolean mResumed;
- private boolean mStopped;
+ /*package*/ boolean mStopped;
boolean mFinished;
boolean mStartedActivity;
private boolean mDestroyed;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 060ac5e..93c668d1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -379,6 +379,33 @@
? "no component name" : componentName.toShortString())
+ "}";
}
+
+ public String getStateString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("ActivityClientRecord{");
+ sb.append("paused=").append(paused);
+ sb.append(", stopped=").append(stopped);
+ sb.append(", hideForNow=").append(hideForNow);
+ sb.append(", startsNotResumed=").append(startsNotResumed);
+ sb.append(", isForward=").append(isForward);
+ sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
+ sb.append(", onlyLocalRequest=").append(onlyLocalRequest);
+ sb.append(", preserveWindow=").append(mPreserveWindow);
+ if (activity != null) {
+ sb.append(", Activity{");
+ sb.append("resumed=").append(activity.mResumed);
+ sb.append(", stopped=").append(activity.mStopped);
+ sb.append(", finished=").append(activity.isFinishing());
+ sb.append(", destroyed=").append(activity.isDestroyed());
+ sb.append(", startedActivity=").append(activity.mStartedActivity);
+ sb.append(", temporaryPause=").append(activity.mTemporaryPause);
+ sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
+ sb.append(", visibleBehind=").append(activity.mVisibleBehind);
+ sb.append("}");
+ }
+ sb.append("}");
+ return sb.toString();
+ }
}
final class ProviderClientRecord {
@@ -3752,9 +3779,10 @@
return;
}
RuntimeException e = new RuntimeException(
- "Performing stop of activity that is not resumed: "
+ "Performing stop of activity that is already stopped: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
+ Slog.e(TAG, r.getStateString());
}
if (info != null) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1e288de..e9d0846 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3197,6 +3197,7 @@
}
private void resetStandardTemplateWithActions(RemoteViews big) {
+ big.setViewVisibility(R.id.actions_container, View.GONE);
big.setViewVisibility(R.id.actions, View.GONE);
big.removeAllViews(R.id.actions);
@@ -3218,6 +3219,7 @@
int N = mActions.size();
if (N > 0) {
+ big.setViewVisibility(R.id.actions_container, View.VISIBLE);
big.setViewVisibility(R.id.actions, View.VISIBLE);
if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
for (int i=0; i<N; i++) {
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 2dfb061..8582150 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -43,6 +43,16 @@
public final RssiCurve rssiCurve;
/**
+ * A boolean value that indicates whether or not the network is believed to be metered.
+ *
+ * <p>A network can be classified as metered if the user would be
+ * sensitive to heavy data usage on that connection due to monetary costs,
+ * data limitations or battery/performance issues. A typical example would
+ * be a wifi connection where the user would be charged for usage.
+ */
+ public final boolean meteredHint;
+
+ /**
* Construct a new {@link ScoredNetwork}.
*
* @param networkKey the {@link NetworkKey} uniquely identifying this network.
@@ -54,8 +64,26 @@
* the scorer may choose to issue an out-of-band update at any time.
*/
public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
+ this(networkKey, rssiCurve, false /* meteredHint */);
+ }
+
+ /**
+ * Construct a new {@link ScoredNetwork}.
+ *
+ * @param networkKey the {@link NetworkKey} uniquely identifying this network.
+ * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+ * RSSI. This field is optional, and may be skipped to represent a network which the scorer
+ * has opted not to score at this time. Passing a null value here is strongly preferred to
+ * not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+ * indicates to the system not to request scores for this network in the future, although
+ * the scorer may choose to issue an out-of-band update at any time.
+ * @param meteredHint A boolean value indicating whether or not the network is believed to be
+ * metered.
+ */
+ public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) {
this.networkKey = networkKey;
this.rssiCurve = rssiCurve;
+ this.meteredHint = meteredHint;
}
private ScoredNetwork(Parcel in) {
@@ -65,6 +93,7 @@
} else {
rssiCurve = null;
}
+ meteredHint = in.readByte() != 0;
}
@Override
@@ -81,6 +110,7 @@
} else {
out.writeByte((byte) 0);
}
+ out.writeByte((byte) (meteredHint ? 1 : 0));
}
@Override
@@ -90,18 +120,20 @@
ScoredNetwork that = (ScoredNetwork) o;
- return Objects.equals(networkKey, that.networkKey) &&
- Objects.equals(rssiCurve, that.rssiCurve);
+ return Objects.equals(networkKey, that.networkKey)
+ && Objects.equals(rssiCurve, that.rssiCurve)
+ && Objects.equals(meteredHint, that.meteredHint);
}
@Override
public int hashCode() {
- return Objects.hash(networkKey, rssiCurve);
+ return Objects.hash(networkKey, rssiCurve, meteredHint);
}
@Override
public String toString() {
- return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
+ return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve
+ + ",meteredHint=" + meteredHint + "]";
}
public static final Parcelable.Creator<ScoredNetwork> CREATOR =
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 8a1a8c5..5060350 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9646,7 +9646,10 @@
}
boolean canShare() {
- return canCopy() && isDeviceProvisioned();
+ if (!getContext().canStartActivityForResult() || !isDeviceProvisioned()) {
+ return false;
+ }
+ return canCopy();
}
boolean isDeviceProvisioned() {
@@ -9669,16 +9672,10 @@
}
boolean canProcessText() {
- if (!getContext().canStartActivityForResult() || getId() == View.NO_ID
- || hasPasswordTransformationMethod()) {
+ if (getId() == View.NO_ID) {
return false;
}
-
- if (mText.length() > 0 && hasSelection() && mEditor != null) {
- return true;
- }
-
- return false;
+ return canShare();
}
boolean canSelectAllText() {
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index cbf17a4..ec8cd71 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -37,6 +37,8 @@
import android.print.mockservice.PrinterDiscoverySessionCallbacks;
import android.print.mockservice.StubbablePrinterDiscoverySession;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -253,6 +255,7 @@
/**
* test IPrintManager.getPrintJobInfo
*/
+ @LargeTest
public void testGetPrintJobInfo() throws Exception {
startPrinting();
@@ -274,6 +277,7 @@
/**
* test IPrintManager.getPrintJobInfos
*/
+ @LargeTest
public void testGetPrintJobInfos() throws Exception {
startPrinting();
@@ -301,6 +305,7 @@
/**
* test IPrintManager.print
*/
+ @LargeTest
public void testPrint() throws Exception {
final String name = "dummy print job";
@@ -354,6 +359,7 @@
/**
* test IPrintManager.cancelPrintJob
*/
+ @LargeTest
public void testCancelPrintJob() throws Exception {
startPrinting();
@@ -377,6 +383,7 @@
/**
* test IPrintManager.restartPrintJob
*/
+ @LargeTest
public void testRestartPrintJob() throws Exception {
startPrinting();
@@ -399,6 +406,7 @@
/**
* test IPrintManager.addPrintJobStateChangeListener
*/
+ @MediumTest
public void testAddPrintJobStateChangeListener() throws Exception {
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
@@ -424,6 +432,7 @@
/**
* test IPrintManager.removePrintJobStateChangeListener
*/
+ @MediumTest
public void testRemovePrintJobStateChangeListener() throws Exception {
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
@@ -447,6 +456,7 @@
/**
* test IPrintManager.addPrintServicesChangeListener
*/
+ @MediumTest
public void testAddPrintServicesChangeListener() throws Exception {
final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
@@ -465,6 +475,7 @@
/**
* test IPrintManager.removePrintServicesChangeListener
*/
+ @MediumTest
public void testRemovePrintServicesChangeListener() throws Exception {
final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
@@ -488,6 +499,7 @@
/**
* test IPrintManager.getPrintServices
*/
+ @MediumTest
public void testGetPrintServices() throws Exception {
List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId);
@@ -509,6 +521,7 @@
/**
* test IPrintManager.setPrintServiceEnabled
*/
+ @MediumTest
public void testSetPrintServiceEnabled() throws Exception {
final ComponentName printService = mIPrintManager.getPrintServices(
PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
@@ -548,6 +561,7 @@
/**
* test IPrintManager.createPrinterDiscoverySession
*/
+ @MediumTest
public void testCreatePrinterDiscoverySession() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
@@ -573,6 +587,7 @@
/**
* test IPrintManager.startPrinterDiscovery
*/
+ @LargeTest
public void testStartPrinterDiscovery() throws Exception {
startPrinting();
@@ -615,6 +630,7 @@
/**
* test IPrintManager.stopPrinterDiscovery
*/
+ @MediumTest
public void testStopPrinterDiscovery() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
@@ -638,6 +654,7 @@
/**
* test IPrintManager.validatePrinters
*/
+ @LargeTest
public void testValidatePrinters() throws Exception {
startPrinting();
@@ -678,6 +695,7 @@
/**
* test IPrintManager.startPrinterStateTracking
*/
+ @LargeTest
public void testStartPrinterStateTracking() throws Exception {
startPrinting();
@@ -699,6 +717,7 @@
/**
* test IPrintManager.getCustomPrinterIcon
*/
+ @LargeTest
public void testGetCustomPrinterIcon() throws Exception {
startPrinting();
@@ -720,6 +739,7 @@
/**
* test IPrintManager.stopPrinterStateTracking
*/
+ @LargeTest
public void testStopPrinterStateTracking() throws Exception {
startPrinting();
@@ -746,6 +766,7 @@
/**
* test IPrintManager.destroyPrinterDiscoverySession
*/
+ @MediumTest
public void testDestroyPrinterDiscoverySession() throws Exception {
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 11fecfb..a7eb73f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -47,7 +47,6 @@
private double mCarrierPhaseUncertainty;
private int mMultipathIndicator;
private double mSnrInDb;
- private boolean mPseudorangeRateCorrected;
// The following enumerations must be in sync with the values declared in gps.h
@@ -440,25 +439,6 @@
}
/**
- * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
- *
- * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
- * value, {@code false} if it contains an uncorrected value.
- */
- public boolean isPseudorangeRateCorrected() {
- return mPseudorangeRateCorrected;
- }
-
- /**
- * Sets whether the pseudorange corrected.
- * @hide
- */
- @TestApi
- public void setPseudorangeRateCorrected(boolean value) {
- mPseudorangeRateCorrected = value;
- }
-
- /**
* Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
* The uncertainty is represented as an absolute (single sided) value.
*/
@@ -813,7 +793,6 @@
gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
gnssMeasurement.mMultipathIndicator = parcel.readInt();
gnssMeasurement.mSnrInDb = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
return gnssMeasurement;
}
@@ -845,7 +824,6 @@
parcel.writeDouble(mCarrierPhaseUncertainty);
parcel.writeInt(mMultipathIndicator);
parcel.writeDouble(mSnrInDb);
- parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
}
@Override
@@ -880,10 +858,6 @@
mPseudorangeRateMetersPerSecond,
"PseudorangeRateUncertaintyMetersPerSecond",
mPseudorangeRateUncertaintyMetersPerSecond));
- builder.append(String.format(
- format,
- "PseudorangeRateIsCorrected",
- isPseudorangeRateCorrected()));
builder.append(String.format(
format,
@@ -943,7 +917,6 @@
resetCarrierPhaseUncertainty();
setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
resetSnrInDb();
- setPseudorangeRateCorrected(false);
}
private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index ac255c8..e5c0f27 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -286,18 +286,11 @@
navigationMessage.setSvid(parcel.readInt());
navigationMessage.setMessageId(parcel.readInt());
navigationMessage.setSubmessageId(parcel.readInt());
-
int dataLength = parcel.readInt();
byte[] data = new byte[dataLength];
parcel.readByteArray(data);
navigationMessage.setData(data);
-
- if (parcel.dataAvail() >= Integer.SIZE) {
- int status = parcel.readInt();
- navigationMessage.setStatus(status);
- } else {
- navigationMessage.setStatus(STATUS_UNKNOWN);
- }
+ navigationMessage.setStatus(parcel.readInt());
return navigationMessage;
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d179171..3c42161 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1076,9 +1076,6 @@
* <p>
* This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
- * <p>From N onward, stream mute changes that would toggle Do Not Disturb are not allowed unless
- * the app has been granted Do Not Disturb Access.
- * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* <p>
* This method was deprecated in API level 22. Prior to API level 22 this
* method had significantly different behavior and should be used carefully.
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 75195c4..7460201 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -43,6 +43,7 @@
android:singleLine="true"
android:ellipsize="start"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+ android:textIsSelectable="true"
android:imeOptions="actionSend|flagNoExtractUi" />
<FrameLayout
@@ -62,6 +63,7 @@
android:paddingBottom="12dp"
android:id="@+id/remote_input_send"
android:src="@drawable/ic_send"
+ android:contentDescription="@*android:string/ime_action_send"
android:tint="@color/remote_input_send"
android:tintMode="src_in"
android:background="@drawable/ripple_drawable" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 8f1517d..bb4a771 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1107,6 +1107,7 @@
});
a.start();
guts.setExposed(true);
+ row.closeRemoteInput();
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
mNotificationGutsExposed = guts;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 246f15e..22bb8eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -579,6 +579,11 @@
}
}
+ public void closeRemoteInput() {
+ mPrivateLayout.closeRemoteInput();
+ mPublicLayout.closeRemoteInput();
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 3b87577..c2df292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -69,6 +69,9 @@
private View mHeadsUpChild;
private HybridNotificationView mSingleLineView;
+ private RemoteInputView mExpandedRemoteInput;
+ private RemoteInputView mHeadsUpRemoteInput;
+
private NotificationViewWrapper mContractedWrapper;
private NotificationViewWrapper mExpandedWrapper;
private NotificationViewWrapper mHeadsUpWrapper;
@@ -743,15 +746,19 @@
View bigContentView = mExpandedChild;
if (bigContentView != null) {
- applyRemoteInput(bigContentView, entry, hasRemoteInput);
+ mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput);
+ } else {
+ mExpandedRemoteInput = null;
}
View headsUpContentView = mHeadsUpChild;
if (headsUpContentView != null) {
- applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
+ mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
+ } else {
+ mHeadsUpRemoteInput = null;
}
}
- private void applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
+ private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
View actionContainerCandidate = view.findViewById(
com.android.internal.R.id.actions_container);
if (actionContainerCandidate instanceof FrameLayout) {
@@ -777,7 +784,20 @@
color = mContext.getColor(R.color.default_remote_input_background);
}
riv.setBackgroundColor(color);
+
+ return riv;
}
+ return existing;
+ }
+ return null;
+ }
+
+ public void closeRemoteInput() {
+ if (mHeadsUpRemoteInput != null) {
+ mHeadsUpRemoteInput.close();
+ }
+ if (mExpandedRemoteInput != null) {
+ mExpandedRemoteInput.close();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index eb5b57e..95f26d4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -16,24 +16,42 @@
package com.android.systemui.statusbar.phone;
+import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
import android.app.StatusBarManager;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.media.session.MediaSessionLegacyHelper;
+import android.net.Uri;
+import android.os.Bundle;
import android.os.IBinder;
import android.util.AttributeSet;
+import android.view.ActionMode;
+import android.view.InputQueue;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.MotionEvent;
+import android.view.SurfaceHolder;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
+import com.android.internal.view.FloatingActionMode;
+import com.android.internal.widget.FloatingToolbar;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -57,6 +75,13 @@
private final Paint mTransparentSrcPaint = new Paint();
private FalsingManager mFalsingManager;
+ // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
+ // DecorView, but since this is a special window we have to roll our own.
+ private View mFloatingActionModeOriginatingView;
+ private ActionMode mFloatingActionMode;
+ private FloatingToolbar mFloatingToolbar;
+ private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
+
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
@@ -301,5 +326,341 @@
a.recycle();
}
}
+
+ @Override
+ public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
+ int type) {
+ if (type == ActionMode.TYPE_FLOATING) {
+ return startActionMode(originalView, callback, type);
+ }
+ return super.startActionModeForChild(originalView, callback, type);
+ }
+
+ private ActionMode createFloatingActionMode(
+ View originatingView, ActionMode.Callback2 callback) {
+ if (mFloatingActionMode != null) {
+ mFloatingActionMode.finish();
+ }
+ cleanupFloatingActionModeViews();
+ final FloatingActionMode mode =
+ new FloatingActionMode(mContext, callback, originatingView);
+ mFloatingActionModeOriginatingView = originatingView;
+ mFloatingToolbarPreDrawListener =
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mode.updateViewLocationInWindow();
+ return true;
+ }
+ };
+ return mode;
+ }
+
+ private void setHandledFloatingActionMode(ActionMode mode) {
+ mFloatingActionMode = mode;
+ mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow);
+ ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
+ mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
+ mFloatingActionModeOriginatingView.getViewTreeObserver()
+ .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
+ }
+
+ private void cleanupFloatingActionModeViews() {
+ if (mFloatingToolbar != null) {
+ mFloatingToolbar.dismiss();
+ mFloatingToolbar = null;
+ }
+ if (mFloatingActionModeOriginatingView != null) {
+ if (mFloatingToolbarPreDrawListener != null) {
+ mFloatingActionModeOriginatingView.getViewTreeObserver()
+ .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
+ mFloatingToolbarPreDrawListener = null;
+ }
+ mFloatingActionModeOriginatingView = null;
+ }
+ }
+
+ private ActionMode startActionMode(
+ View originatingView, ActionMode.Callback callback, int type) {
+ ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
+ ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback);
+ if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
+ setHandledFloatingActionMode(mode);
+ } else {
+ mode = null;
+ }
+ return mode;
+ }
+
+ private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
+ private final ActionMode.Callback mWrapped;
+
+ public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
+ mWrapped = wrapped;
+ }
+
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return mWrapped.onCreateActionMode(mode, menu);
+ }
+
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ requestFitSystemWindows();
+ return mWrapped.onPrepareActionMode(mode, menu);
+ }
+
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return mWrapped.onActionItemClicked(mode, item);
+ }
+
+ public void onDestroyActionMode(ActionMode mode) {
+ mWrapped.onDestroyActionMode(mode);
+ if (mode == mFloatingActionMode) {
+ cleanupFloatingActionModeViews();
+ mFloatingActionMode = null;
+ }
+ requestFitSystemWindows();
+ }
+
+ @Override
+ public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+ if (mWrapped instanceof ActionMode.Callback2) {
+ ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
+ } else {
+ super.onGetContentRect(mode, view, outRect);
+ }
+ }
+ }
+
+ /**
+ * Minimal window to satisfy FloatingToolbar.
+ */
+ private Window mFakeWindow = new Window(mContext) {
+ @Override
+ public void takeSurface(SurfaceHolder.Callback2 callback) {
+ }
+
+ @Override
+ public void takeInputQueue(InputQueue.Callback callback) {
+ }
+
+ @Override
+ public boolean isFloating() {
+ return false;
+ }
+
+ @Override
+ public void alwaysReadCloseOnTouchAttr() {
+ }
+
+ @Override
+ public void setContentView(@LayoutRes int layoutResID) {
+ }
+
+ @Override
+ public void setContentView(View view) {
+ }
+
+ @Override
+ public void setContentView(View view, ViewGroup.LayoutParams params) {
+ }
+
+ @Override
+ public void addContentView(View view, ViewGroup.LayoutParams params) {
+ }
+
+ @Override
+ public void clearContentView() {
+ }
+
+ @Override
+ public View getCurrentFocus() {
+ return null;
+ }
+
+ @Override
+ public LayoutInflater getLayoutInflater() {
+ return null;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ }
+
+ @Override
+ public void setTitleColor(@ColorInt int textColor) {
+ }
+
+ @Override
+ public void openPanel(int featureId, KeyEvent event) {
+ }
+
+ @Override
+ public void closePanel(int featureId) {
+ }
+
+ @Override
+ public void togglePanel(int featureId, KeyEvent event) {
+ }
+
+ @Override
+ public void invalidatePanelMenu(int featureId) {
+ }
+
+ @Override
+ public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
+ return false;
+ }
+
+ @Override
+ public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
+ return false;
+ }
+
+ @Override
+ public void closeAllPanels() {
+ }
+
+ @Override
+ public boolean performContextMenuIdentifierAction(int id, int flags) {
+ return false;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ }
+
+ @Override
+ public void setBackgroundDrawable(Drawable drawable) {
+ }
+
+ @Override
+ public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
+ }
+
+ @Override
+ public void setFeatureDrawableUri(int featureId, Uri uri) {
+ }
+
+ @Override
+ public void setFeatureDrawable(int featureId, Drawable drawable) {
+ }
+
+ @Override
+ public void setFeatureDrawableAlpha(int featureId, int alpha) {
+ }
+
+ @Override
+ public void setFeatureInt(int featureId, int value) {
+ }
+
+ @Override
+ public void takeKeyEvents(boolean get) {
+ }
+
+ @Override
+ public boolean superDispatchKeyEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchTouchEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchTrackballEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean superDispatchGenericMotionEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public View getDecorView() {
+ return StatusBarWindowView.this;
+ }
+
+ @Override
+ public View peekDecorView() {
+ return null;
+ }
+
+ @Override
+ public Bundle saveHierarchyState() {
+ return null;
+ }
+
+ @Override
+ public void restoreHierarchyState(Bundle savedInstanceState) {
+ }
+
+ @Override
+ protected void onActive() {
+ }
+
+ @Override
+ public void setChildDrawable(int featureId, Drawable drawable) {
+ }
+
+ @Override
+ public void setChildInt(int featureId, int value) {
+ }
+
+ @Override
+ public boolean isShortcutKey(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public void setVolumeControlStream(int streamType) {
+ }
+
+ @Override
+ public int getVolumeControlStream() {
+ return 0;
+ }
+
+ @Override
+ public int getStatusBarColor() {
+ return 0;
+ }
+
+ @Override
+ public void setStatusBarColor(@ColorInt int color) {
+ }
+
+ @Override
+ public int getNavigationBarColor() {
+ return 0;
+ }
+
+ @Override
+ public void setNavigationBarColor(@ColorInt int color) {
+ }
+
+ @Override
+ public void setDecorCaptionShade(int decorCaptionShade) {
+ }
+
+ @Override
+ public void setResizingCaptionDrawable(Drawable drawable) {
+ }
+
+ @Override
+ public void onMultiWindowChanged() {
+ }
+
+ @Override
+ public void reportActivityRelaunched() {
+ }
+ };
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 29b0f4b..3a0336b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -29,8 +29,10 @@
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@@ -44,6 +46,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.stack.LongPressCancelable;
/**
* Host for the remote input.
@@ -64,6 +67,7 @@
private RemoteInputController mController;
private NotificationData.Entry mEntry;
+ private LongPressCancelable mLongPressCancelable;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -226,6 +230,30 @@
updateSendButton();
}
+ public void close() {
+ mEditText.defocusIfNeeded();
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (mLongPressCancelable == null) {
+ ViewParent p = getParent();
+ while (p != null) {
+ if (p instanceof LongPressCancelable) {
+ mLongPressCancelable = (LongPressCancelable) p;
+ break;
+ }
+ p = p.getParent();
+ }
+ }
+ if (mLongPressCancelable != null) {
+ mLongPressCancelable.requestDisallowLongPress();
+ }
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+
/**
* An EditText that changes appearance based on whether it's focusable and becomes
* un-focusable whenever the user navigates away from it or it becomes invisible.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
new file mode 100644
index 0000000..05f0c07
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.statusbar.stack;
+
+/**
+ * Interface for container layouts that listen for long presses. A child that
+ * wants to handle long press can use this to cancel the parents long press logic.
+ */
+public interface LongPressCancelable {
+ /**
+ * Request that the view does not perform long press for the current touch.
+ */
+ void requestDisallowLongPress();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 59ec6112..686a712 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -83,7 +83,7 @@
public class NotificationStackScrollLayout extends ViewGroup
implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
- SettingsIconRowListener {
+ SettingsIconRowListener, LongPressCancelable {
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
@@ -2627,6 +2627,11 @@
}
}
+ @Override
+ public void requestDisallowLongPress() {
+ removeLongPressCallback();
+ }
+
public void removeLongPressCallback() {
mSwipeHelper.removeLongPressCallback();
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d4dd505..8310c97 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -597,7 +597,7 @@
if (sharedAccounts == null || sharedAccounts.length == 0) return;
Account[] accounts = getAccountsAsUser(null, userId, mContext.getOpPackageName());
int parentUserId = UserManager.isSplitSystemUser()
- ? mUserManager.getUserInfo(userId).restrictedProfileParentId
+ ? getUserManager().getUserInfo(userId).restrictedProfileParentId
: UserHandle.USER_SYSTEM;
if (parentUserId < 0) {
Log.w(TAG, "User " + userId + " has shared accounts, but no parent user");
@@ -1061,7 +1061,7 @@
for (UserInfo user : users) {
if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) {
addSharedAccountAsUser(account, user.id);
- if (mUserManager.isUserUnlocked(user.id)) {
+ if (getUserManager().isUserUnlocked(user.id)) {
mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
}
@@ -1270,7 +1270,7 @@
* Owner or system user account was renamed, rename the account for
* those users with which the account was shared.
*/
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = getUserManager().getUsers(true);
for (UserInfo user : users) {
if (user.isRestricted()
&& (user.restrictedProfileParentId == parentUserId)) {
@@ -1286,7 +1286,7 @@
}
private boolean canHaveProfile(final int parentUserId) {
- final UserInfo userInfo = mUserManager.getUserInfo(parentUserId);
+ final UserInfo userInfo = getUserManager().getUserInfo(parentUserId);
return userInfo != null && userInfo.canHaveProfile();
}
@@ -1477,7 +1477,7 @@
int parentUserId = accounts.userId;
if (canHaveProfile(parentUserId)) {
// Remove from any restricted profiles that are sharing this account.
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = getUserManager().getUsers(true);
for (UserInfo user : users) {
if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) {
removeSharedAccountAsUser(account, user.id, callingUid);
@@ -4730,7 +4730,7 @@
|| callingUid == Process.myUid()) {
return unfiltered;
}
- UserInfo user = mUserManager.getUserInfo(userAccounts.userId);
+ UserInfo user = getUserManager().getUserInfo(userAccounts.userId);
if (user != null && user.isRestricted()) {
String[] packages = mPackageManager.getPackagesForUid(callingUid);
// If any of the packages is a white listed package, return the full set,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5320221..b4df689 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1290,7 +1290,7 @@
// Check if the ringer mode handles this adjustment. If it does we don't
// need to adjust the volume further.
final int result = checkForRingerModeChange(aliasIndex, direction, step,
- streamState.mIsMuted, caller);
+ streamState.mIsMuted);
adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
// If suppressing a volume adjustment in silent mode, display the UI hint
if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -3361,8 +3361,7 @@
* adjusting volume. If so, this will set the proper ringer mode and volume
* indices on the stream states.
*/
- private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
- String caller) {
+ private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
int result = FLAG_ADJUST_VOLUME;
int ringerMode = getRingerModeInternal();
@@ -3451,11 +3450,6 @@
break;
}
- if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
- && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
- throw new SecurityException("Not allowed to change Do Not Disturb state");
- }
-
setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
mPrevVolDirection = direction;