Merge "Allow Activity/Service to get media keys across the boot"
diff --git a/api/current.txt b/api/current.txt
index cd33830..4657394 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -41939,13 +41939,13 @@
method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.system.Int64Ref, long) throws android.system.ErrnoException;
method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
- method public static void setegid(int) throws android.system.ErrnoException;
+ method public static deprecated void setegid(int) throws android.system.ErrnoException;
method public static void setenv(java.lang.String, java.lang.String, boolean) throws android.system.ErrnoException;
- method public static void seteuid(int) throws android.system.ErrnoException;
- method public static void setgid(int) throws android.system.ErrnoException;
+ method public static deprecated void seteuid(int) throws android.system.ErrnoException;
+ method public static deprecated void setgid(int) throws android.system.ErrnoException;
method public static int setsid() throws android.system.ErrnoException;
method public static void setsockoptInt(java.io.FileDescriptor, int, int, int) throws android.system.ErrnoException;
- method public static void setuid(int) throws android.system.ErrnoException;
+ method public static deprecated void setuid(int) throws android.system.ErrnoException;
method public static void setxattr(java.lang.String, java.lang.String, byte[], int) throws android.system.ErrnoException;
method public static void shutdown(java.io.FileDescriptor, int) throws android.system.ErrnoException;
method public static java.io.FileDescriptor socket(int, int, int) throws android.system.ErrnoException;
@@ -51901,6 +51901,7 @@
public abstract class Animation implements java.lang.Cloneable {
ctor public Animation();
ctor public Animation(android.content.Context, android.util.AttributeSet);
+ method public void addAnimationListener(android.view.animation.Animation.AnimationListener);
method protected void applyTransformation(float, android.view.animation.Transformation);
method public void cancel();
method protected android.view.animation.Animation clone() throws java.lang.CloneNotSupportedException;
@@ -51925,6 +51926,7 @@
method public void initialize(int, int, int, int);
method public boolean isFillEnabled();
method public boolean isInitialized();
+ method public void removeAnimationListener(android.view.animation.Animation.AnimationListener);
method public void reset();
method protected float resolveSize(int, float, int, int);
method public void restrictDuration(long);
diff --git a/api/system-current.txt b/api/system-current.txt
index 734ac82..f7ea8be 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6269,6 +6269,7 @@
method public int getSimCardState();
method public int getSupportedRadioAccessFamily();
method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
+ method public android.telephony.UiccCardInfo[] getUiccCardsInfo();
method public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
method public android.os.Bundle getVisualVoicemailSettings();
method public int getVoiceActivationState();
@@ -6365,6 +6366,18 @@
field public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR;
}
+ public class UiccCardInfo implements android.os.Parcelable {
+ ctor public UiccCardInfo(boolean, int, java.lang.String, java.lang.String, int);
+ method public int describeContents();
+ method public int getCardId();
+ method public java.lang.String getEid();
+ method public java.lang.String getIccId();
+ method public int getSlotIndex();
+ method public boolean isEuicc();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR;
+ }
+
public class UiccSlotInfo implements android.os.Parcelable {
ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int, boolean);
method public int describeContents();
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 7bbeb16..8f28ae1 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2869,7 +2869,6 @@
Lcom/android/internal/telephony/dataconnection/DataConnection;->mPhone:Lcom/android/internal/telephony/Phone;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mRilRat:I
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfConnected(Ljava/lang/String;)V
-Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfDisconnectDcRetrying(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;Z)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->onConnect(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->tearDownData(Ljava/lang/Object;)V
@@ -2937,7 +2936,6 @@
Lcom/android/internal/telephony/DctConstants$State;->FAILED:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DctConstants$State;->IDLE:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DctConstants$State;->RETRYING:Lcom/android/internal/telephony/DctConstants$State;
-Lcom/android/internal/telephony/DctConstants$State;->SCANNING:Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DctConstants$State;->values()[Lcom/android/internal/telephony/DctConstants$State;
Lcom/android/internal/telephony/DefaultPhoneNotifier;->mRegistry:Lcom/android/internal/telephony/ITelephonyRegistry;
Lcom/android/internal/telephony/DriverCall$State;->ACTIVE:Lcom/android/internal/telephony/DriverCall$State;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 48a767b..3561f71 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -924,6 +924,9 @@
private AutofillPopupWindow mAutofillPopupWindow;
+ /** @hide */
+ boolean mEnterAnimationComplete;
+
private static native String getDlWarning();
/** Return the intent that started this activity. */
@@ -2328,6 +2331,7 @@
}
notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_STOP);
}
+ mEnterAnimationComplete = false;
}
/**
@@ -7085,6 +7089,8 @@
* @hide
*/
public void dispatchEnterAnimationComplete() {
+ mEnterAnimationComplete = true;
+ mInstrumentation.onEnterAnimationComplete();
onEnterAnimationComplete();
if (getWindow() != null && getWindow().getDecorView() != null) {
getWindow().getDecorView().getViewTreeObserver().dispatchOnEnterAnimationComplete();
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 015bc6c..d7c7f3c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -110,6 +110,7 @@
private PerformanceCollector mPerformanceCollector;
private Bundle mPerfMetrics = new Bundle();
private UiAutomation mUiAutomation;
+ private final Object mAnimationCompleteLock = new Object();
public Instrumentation() {
}
@@ -397,6 +398,31 @@
idler.waitForIdle();
}
+ private void waitForEnterAnimationComplete(Activity activity) {
+ synchronized (mAnimationCompleteLock) {
+ long timeout = 5000;
+ try {
+ // We need to check that this specified Activity completed the animation, not just
+ // any Activity. If it was another Activity, then decrease the timeout by how long
+ // it's already waited and wait for the thread to wakeup again.
+ while (timeout > 0 && !activity.mEnterAnimationComplete) {
+ long startTime = System.currentTimeMillis();
+ mAnimationCompleteLock.wait(timeout);
+ long totalTime = System.currentTimeMillis() - startTime;
+ timeout -= totalTime;
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /** @hide */
+ public void onEnterAnimationComplete() {
+ synchronized (mAnimationCompleteLock) {
+ mAnimationCompleteLock.notifyAll();
+ }
+ }
+
/**
* Execute a call on the application's main thread, blocking until it is
* complete. Useful for doing things that are not thread-safe, such as
@@ -499,6 +525,7 @@
}
} while (mWaitingActivities.contains(aw));
+ waitForEnterAnimationComplete(aw.activity);
return aw.activity;
}
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 60eeeea..f8d5014 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -195,12 +195,10 @@
}
int childHeight = child.getMeasuredHeight();
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
- left += params.getMarginStart();
- int right = left + child.getMeasuredWidth();
+ int layoutLeft;
+ int layoutRight;
int top = (int) (getPaddingTop() + (ownHeight - childHeight) / 2.0f);
int bottom = top + childHeight;
- int layoutLeft = left;
- int layoutRight = right;
if ((child == mExpandButton && mShowExpandButtonAtEnd)
|| child == mProfileBadge
|| child == mAppOps) {
@@ -211,6 +209,12 @@
}
layoutLeft = layoutRight - child.getMeasuredWidth();
end = layoutLeft - params.getMarginStart();
+ } else {
+ left += params.getMarginStart();
+ int right = left + child.getMeasuredWidth();
+ layoutLeft = left;
+ layoutRight = right;
+ left = right + params.getMarginEnd();
}
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
int ltrLeft = layoutLeft;
@@ -218,7 +222,6 @@
layoutRight = getWidth() - ltrLeft;
}
child.layout(layoutLeft, top, layoutRight, bottom);
- left = right + params.getMarginEnd();
}
updateTouchListener();
}
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 0e1f767..95a346f 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -30,6 +30,9 @@
import dalvik.system.CloseGuard;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Abstraction for an Animation that can be applied to Views, Surfaces, or
* other objects. See the {@link android.view.animation animation package
@@ -182,10 +185,14 @@
Interpolator mInterpolator;
/**
- * The animation listener to be notified when the animation starts, ends or repeats.
+ * An animation listener to be notified when the animation starts, ends or repeats.
*/
- @UnsupportedAppUsage
- AnimationListener mListener;
+ private AnimationListener mListener;
+
+ /**
+ * A list of animation listeners to be notified when the animation starts, ends or repeats.
+ */
+ private List<AnimationListener> mListeners;
/**
* Desired Z order mode during animation.
@@ -371,23 +378,17 @@
if (mListenerHandler == null) {
mOnStart = new Runnable() {
public void run() {
- if (mListener != null) {
- mListener.onAnimationStart(Animation.this);
- }
+ dispatchAnimationStart();
}
};
mOnRepeat = new Runnable() {
public void run() {
- if (mListener != null) {
- mListener.onAnimationRepeat(Animation.this);
- }
+ dispatchAnimationRepeat();
}
};
mOnEnd = new Runnable() {
public void run() {
- if (mListener != null) {
- mListener.onAnimationEnd(Animation.this);
- }
+ dispatchAnimationEnd();
}
};
}
@@ -830,6 +831,10 @@
return true;
}
+ private boolean hasAnimationListener() {
+ return mListener != null || (mListeners != null && !mListeners.isEmpty());
+ }
+
/**
* <p>Binds an animation listener to this animation. The animation listener
* is notified of animation events such as the end of the animation or the
@@ -842,6 +847,32 @@
}
/**
+ * <p>Adds an animation listener to this animation. The animation listener
+ * is notified of animation events such as the end of the animation or the
+ * repetition of the animation.</p>
+ *
+ * @param listener the animation listener to be notified
+ */
+ public void addAnimationListener(AnimationListener listener) {
+ if (mListeners == null) {
+ mListeners = new ArrayList<>(1);
+ }
+ mListeners.add(listener);
+ }
+
+ /**
+ * <p>Removes an animation listener that has been added with
+ * {@link #addAnimationListener(AnimationListener)}.</p>
+ *
+ * @param listener the animation listener to be removed
+ */
+ public void removeAnimationListener(AnimationListener listener) {
+ if (mListeners != null) {
+ mListeners.remove(listener);
+ }
+ }
+
+ /**
* Gurantees that this animation has an interpolator. Will use
* a AccelerateDecelerateInterpolator is nothing else was specified.
*/
@@ -947,26 +978,59 @@
}
private void fireAnimationStart() {
- if (mListener != null) {
- if (mListenerHandler == null) mListener.onAnimationStart(this);
+ if (hasAnimationListener()) {
+ if (mListenerHandler == null) dispatchAnimationStart();
else mListenerHandler.postAtFrontOfQueue(mOnStart);
}
}
private void fireAnimationRepeat() {
- if (mListener != null) {
- if (mListenerHandler == null) mListener.onAnimationRepeat(this);
+ if (hasAnimationListener()) {
+ if (mListenerHandler == null) dispatchAnimationRepeat();
else mListenerHandler.postAtFrontOfQueue(mOnRepeat);
}
}
private void fireAnimationEnd() {
- if (mListener != null) {
- if (mListenerHandler == null) mListener.onAnimationEnd(this);
+ if (hasAnimationListener()) {
+ if (mListenerHandler == null) dispatchAnimationEnd();
else mListenerHandler.postAtFrontOfQueue(mOnEnd);
}
}
+ void dispatchAnimationStart() {
+ if (mListener != null) {
+ mListener.onAnimationStart(this);
+ }
+ if (mListeners != null && !mListeners.isEmpty()) {
+ for (AnimationListener listener : mListeners) {
+ listener.onAnimationStart(this);
+ }
+ }
+ }
+
+ void dispatchAnimationRepeat() {
+ if (mListener != null) {
+ mListener.onAnimationRepeat(this);
+ }
+ if (mListeners != null && !mListeners.isEmpty()) {
+ for (AnimationListener listener : mListeners) {
+ listener.onAnimationRepeat(this);
+ }
+ }
+ }
+
+ void dispatchAnimationEnd() {
+ if (mListener != null) {
+ mListener.onAnimationEnd(this);
+ }
+ if (mListeners != null && !mListeners.isEmpty()) {
+ for (AnimationListener listener : mListeners) {
+ listener.onAnimationEnd(this);
+ }
+ }
+ }
+
/**
* Gets the transformation to apply at a specified point in time. Implementations of this
* method should always replace the specified Transformation or document they are doing
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index 767024e..03c6ca6 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -389,16 +389,12 @@
}
if (started && !mStarted) {
- if (mListener != null) {
- mListener.onAnimationStart(this);
- }
+ dispatchAnimationStart();
mStarted = true;
}
if (ended != mEnded) {
- if (mListener != null) {
- mListener.onAnimationEnd(this);
- }
+ dispatchAnimationEnd();
mEnded = ended;
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 36e81e6..1ba7d8e 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,6 +26,8 @@
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.app.ActivityThread;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Rect;
@@ -37,11 +39,13 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.Trace;
+import android.provider.Settings;
import android.text.style.SuggestionSpan;
import android.util.Log;
import android.util.Pools.Pool;
@@ -232,6 +236,8 @@
static final String PENDING_EVENT_COUNTER = "aq:imm";
+ private static final int NOT_A_SUBTYPE_ID = -1;
+
/**
* A constant that represents Voice IME.
*
@@ -2071,6 +2077,13 @@
/**
* Force switch to a new input method component. This can only be called
* from an application or a service which has a token of the currently active input method.
+ *
+ * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, the undocumented behavior that
+ * token can be {@code null} when the caller has
+ * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} is deprecated. Instead, update
+ * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
+ * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</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.
@@ -2082,14 +2095,50 @@
@Deprecated
public void setInputMethod(IBinder token, String id) {
if (token == null) {
- // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
- // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately.
- // TODO(Bug 114488811): Consider deprecating null token rule.
- try {
- mService.setInputMethod(token, id);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ // There are still some system components that rely on this undocumented behavior
+ // regarding null IME token with WRITE_SECURE_SETTINGS. Provide a fallback logic as a
+ // temporary remedy.
+ if (id == null) {
+ return;
}
+ if (Process.myUid() == Process.SYSTEM_UID) {
+ Log.w(TAG, "System process should not be calling setInputMethod() because almost "
+ + "always it is a bug under multi-user / multi-profile environment. "
+ + "Consider interacting with InputMethodManagerService directly via "
+ + "LocalServices.");
+ return;
+ }
+ final Context fallbackContext = ActivityThread.currentApplication();
+ if (fallbackContext == null) {
+ return;
+ }
+ if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ final List<InputMethodInfo> imis = getEnabledInputMethodList();
+ final int numImis = imis.size();
+ boolean found = false;
+ for (int i = 0; i < numImis; ++i) {
+ final InputMethodInfo imi = imis.get(i);
+ if (id.equals(imi.getId())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Log.e(TAG, "Ignoring setInputMethod(null, " + id + ") because the specified "
+ + "id not found in enabled IMEs.");
+ return;
+ }
+ Log.w(TAG, "The undocumented behavior that setInputMethod() accepts null token "
+ + "when the caller has WRITE_SECURE_SETTINGS is deprecated. This behavior may "
+ + "be completely removed in a future version. Update secure settings directly "
+ + "instead.");
+ final ContentResolver resolver = fallbackContext.getContentResolver();
+ Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+ NOT_A_SUBTYPE_ID);
+ Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, id);
return;
}
InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id);
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index d4c451e..78d366c 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -68,10 +68,10 @@
public boolean wakeLockScreenGestureEnabled(int user) {
return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
- && wakeLockScreenGestureAvailable();
+ && wakeScreenGestureAvailable();
}
- public boolean wakeLockScreenGestureAvailable() {
+ public boolean wakeScreenGestureAvailable() {
return mContext.getResources()
.getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable);
}
@@ -81,10 +81,6 @@
&& wakeScreenGestureAvailable();
}
- public boolean wakeScreenGestureAvailable() {
- return !TextUtils.isEmpty(wakeScreenSensorType());
- }
-
public String doubleTapSensorType() {
return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
}
@@ -93,10 +89,6 @@
return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
}
- 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/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 3873d24..70f4ed2 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -65,8 +65,6 @@
int displayId);
void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
boolean isInputMethodPickerShownForTest();
- // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
- void setInputMethod(in IBinder token, String id);
void registerSuggestionSpansForNotification(in SuggestionSpan[] spans);
boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
InputMethodSubtype getCurrentInputMethodSubtype();
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9f5eab5..cb4f416 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2160,9 +2160,6 @@
<!-- If the sensor that wakes up the lock screen is available or not. -->
<bool name="config_dozeWakeLockScreenSensorAvailable">false</bool>
- <!-- 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. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e5ff1aa..a4a97d3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3499,7 +3499,6 @@
<java-symbol type="integer" name="db_wal_truncate_size" />
<java-symbol type="integer" name="config_wakeUpDelayDoze" />
- <java-symbol type="string" name="config_dozeWakeScreenSensorType" />
<!-- For Bluetooth AbsoluteVolume -->
<java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index1" />
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 953cef7d..aa29174 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -210,6 +210,10 @@
throw new InvalidAlgorithmParameterException(
"HMAC key size must be at least 64 bits.");
}
+ if (mKeySizeBits > 512 && spec.isStrongBoxBacked()) {
+ throw new InvalidAlgorithmParameterException(
+ "StrongBox HMAC key size must be smaller than 512 bits.");
+ }
// JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
// implies SHA-256 digest). Because keymaster HMAC key is authorized only for
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 5fc742a..d44c894 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -303,7 +303,7 @@
if (mKeySizeBits == -1) {
mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
}
- checkValidKeySize(keymasterAlgorithm, mKeySizeBits);
+ checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked());
if (spec.getKeystoreAlias() == null) {
throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
@@ -724,10 +724,18 @@
}
}
- private static void checkValidKeySize(int keymasterAlgorithm, int keySize)
+ private static void checkValidKeySize(
+ int keymasterAlgorithm,
+ int keySize,
+ boolean isStrongBoxBacked)
throws InvalidAlgorithmParameterException {
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
+ if (isStrongBoxBacked && keySize != 256) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported StrongBox EC key size: "
+ + keySize + " bits. Supported: 256");
+ }
if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
+ keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 1cdc291..125ab2e 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -479,7 +479,7 @@
public static final int HE_AAC = 4;
/** Enhanced Low Delay AAC (AAC-ELD) audio codec */
public static final int AAC_ELD = 5;
- /** Ogg Vorbis audio codec */
+ /** Ogg Vorbis audio codec (Support is optional) */
public static final int VORBIS = 6;
/** Opus audio codec */
public static final int OPUS = 7;
diff --git a/media/java/android/media/Session2Command.java b/media/java/android/media/Session2Command.java
new file mode 100644
index 0000000..a5e2ae4
--- /dev/null
+++ b/media/java/android/media/Session2Command.java
@@ -0,0 +1,596 @@
+/*
+ * Copyright 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.media;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
+ * <p>
+ * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
+ * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
+ * {@link #getCustomCommand()} shouldn't be {@code null}.
+ * <p>
+ * This API is not generally intended for third party application developers.
+ * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
+ * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a>
+ * for consistent behavior across all devices.
+ * </p>
+ * @hide
+ */
+public final class Session2Command implements Parcelable {
+ /**
+ * The first version of session commands. This version is for commands introduced in API 29.
+ * <p>
+ * This would be used to specify which commands should be added by
+ * {@link Session2CommandGroup.Builder#addAllPredefinedCommands(int)}
+ *
+ * @see Session2CommandGroup.Builder#addAllPredefinedCommands(int)
+ */
+ public static final int COMMAND_VERSION_1 = 1;
+
+ /**
+ * @hide
+ */
+ public static final int COMMAND_VERSION_CURRENT = COMMAND_VERSION_1;
+
+ /**
+ * @hide
+ */
+ @IntDef({COMMAND_VERSION_1})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CommandVersion {}
+
+ /**
+ * @hide
+ */
+ @IntDef({COMMAND_CODE_CUSTOM,
+ COMMAND_CODE_PLAYER_PLAY,
+ COMMAND_CODE_PLAYER_PAUSE,
+ COMMAND_CODE_PLAYER_PREPARE,
+ COMMAND_CODE_PLAYER_SEEK_TO,
+ COMMAND_CODE_PLAYER_SET_SPEED,
+ COMMAND_CODE_PLAYER_GET_PLAYLIST,
+ COMMAND_CODE_PLAYER_SET_PLAYLIST,
+ COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM,
+ COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM,
+ COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM,
+ COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE,
+ COMMAND_CODE_PLAYER_SET_REPEAT_MODE,
+ COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA,
+ COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM,
+ COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM,
+ COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM,
+ COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM,
+ COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA,
+ COMMAND_CODE_PLAYER_SET_MEDIA_ITEM,
+ COMMAND_CODE_VOLUME_SET_VOLUME,
+ COMMAND_CODE_VOLUME_ADJUST_VOLUME,
+ COMMAND_CODE_SESSION_FAST_FORWARD,
+ COMMAND_CODE_SESSION_REWIND,
+ COMMAND_CODE_SESSION_SKIP_FORWARD,
+ COMMAND_CODE_SESSION_SKIP_BACKWARD,
+ COMMAND_CODE_SESSION_SET_RATING,
+ COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT,
+ COMMAND_CODE_LIBRARY_SUBSCRIBE,
+ COMMAND_CODE_LIBRARY_UNSUBSCRIBE,
+ COMMAND_CODE_LIBRARY_GET_CHILDREN,
+ COMMAND_CODE_LIBRARY_GET_ITEM,
+ COMMAND_CODE_LIBRARY_SEARCH,
+ COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CommandCode {}
+
+ /**
+ * Command code for the custom command which can be defined by string action in the
+ * {@link Session2Command}.
+ */
+ public static final int COMMAND_CODE_CUSTOM = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Player commands (i.e. commands to {@link Session2Player})
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ static final ArrayMap<Integer, Range> VERSION_PLAYER_COMMANDS_MAP = new ArrayMap<>();
+ static final ArrayMap<Integer, Range> VERSION_PLAYER_PLAYLIST_COMMANDS_MAP = new ArrayMap<>();
+
+ // TODO: check the link tag, and reassign int values properly.
+ /**
+ * Command code for {@link MediaController2#play()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info,
+ * Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_PLAY = 10000;
+
+ /**
+ * Command code for {@link MediaController2#pause()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info,
+ * Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_PAUSE = 10001;
+
+ /**
+ * Command code for {@link MediaController2#prepare()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info,
+ * Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_PREPARE = 10002;
+
+ /**
+ * Command code for {@link MediaController2#seekTo(long)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info,
+ * Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003;
+
+ /**
+ * Command code for {@link MediaController2#setPlaybackSpeed(float)}}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session22Callback#onCommandRequest(MediaSession2, Controller2Info,
+ * Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004;
+
+ /**
+ * Command code for {@link MediaController2#getPlaylist()}. This will expose metadata
+ * information to the controller.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005;
+
+ /**
+ * Command code for {@link MediaController2#setPlaylist(List, MediaMetadata)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006;
+
+ /**
+ * Command code for {@link MediaController2#skipToPlaylistItem(int)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007;
+
+ /**
+ * Command code for {@link MediaController2#skipToPreviousPlaylistItem()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session2Callback#onCommandRequest(
+ * MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008;
+
+ /**
+ * Command code for {@link MediaController2#skipToNextPlaylistItem()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link Session2Callback#onCommandRequest(
+ * MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+
+ public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009;
+
+ /**
+ * Command code for {@link MediaController2#setShuffleMode(int)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010;
+
+ /**
+ * Command code for {@link MediaController2#setRepeatMode(int)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011;
+
+ /**
+ * Command code for {@link MediaController2#getPlaylistMetadata()}. This will expose metadata
+ * information to the controller.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012;
+
+ /**
+ * Command code for {@link MediaController2#addPlaylistItem(int, String)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013;
+
+ /**
+ * Command code for {@link MediaController2#removePlaylistItem(int, String)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014;
+
+ /**
+ * Command code for {@link MediaController2#replacePlaylistItem(int, String)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015;
+
+ /**
+ * Command code for {@link MediaController2#getCurrentMediaItem()}. This will expose metadata
+ * information to the controller.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016;
+
+ /**
+ * Command code for {@link MediaController2#updatePlaylistMetadata(MediaMetadata)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017;
+
+ /**
+ * Command code for {@link MediaController2#setMediaItem(String)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018;
+
+ static {
+ VERSION_PLAYER_COMMANDS_MAP.put(COMMAND_VERSION_1,
+ new Range(COMMAND_CODE_PLAYER_PLAY, COMMAND_CODE_PLAYER_SET_MEDIA_ITEM));
+ }
+
+ static {
+ VERSION_PLAYER_PLAYLIST_COMMANDS_MAP.put(COMMAND_VERSION_1,
+ new Range(COMMAND_CODE_PLAYER_GET_PLAYLIST,
+ COMMAND_CODE_PLAYER_SET_MEDIA_ITEM));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Volume commands (i.e. commands to {@link AudioManager} or {@link RouteMediaPlayer})
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ static final ArrayMap<Integer, Range> VERSION_VOLUME_COMMANDS_MAP = new ArrayMap<>();
+
+ /**
+ * Command code for {@link MediaController2#setVolumeTo(int, int)}.
+ * <p>
+ * <p>
+ * If the session doesn't reject the request through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)},
+ * command would adjust the device volume. It would send to the player directly only if it's
+ * remote player. See RouteMediaPlayer for a remote player.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000;
+
+ /**
+ * Command code for {@link MediaController2#adjustVolume(int, int)}.
+ * <p>
+ * If the session doesn't reject the request through the
+ * {@link Session2Callback#onCommandRequest(MediaSession2, Controller2Info, Session2Command)},
+ * command would adjust the device volume. It would send to the player directly only if it's
+ * remote player. See RouteMediaPlayer for a remote player.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001;
+
+ static {
+ VERSION_VOLUME_COMMANDS_MAP.put(COMMAND_VERSION_1,
+ new Range(COMMAND_CODE_VOLUME_SET_VOLUME,
+ COMMAND_CODE_VOLUME_ADJUST_VOLUME));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Session commands (i.e. commands to {@link MediaSession2#Session2Callback})
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ static final ArrayMap<Integer, Range> VERSION_SESSION_COMMANDS_MAP = new ArrayMap<>();
+
+ /**
+ * Command code for {@link MediaController2#fastForward()}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000;
+
+ /**
+ * Command code for {@link MediaController2#rewind()}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_SESSION_REWIND = 40001;
+
+ /**
+ * Command code for {@link MediaController2#skipForward()}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002;
+
+ /**
+ * Command code for {@link MediaController2#skipBackward()}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003;
+
+ /**
+ * Command code for {@link MediaController2#setRating(String, Rating)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_SESSION_SET_RATING = 40010;
+
+ public static final Parcelable.Creator<Session2Command> CREATOR =
+ new Parcelable.Creator<Session2Command>() {
+ @Override
+ public Session2Command createFromParcel(Parcel in) {
+ return new Session2Command(in);
+ }
+
+ @Override
+ public Session2Command[] newArray(int size) {
+ return new Session2Command[size];
+ }
+ };
+
+ static {
+ VERSION_SESSION_COMMANDS_MAP.put(COMMAND_VERSION_1,
+ new Range(COMMAND_CODE_SESSION_FAST_FORWARD, COMMAND_CODE_SESSION_SET_RATING));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Session commands (i.e. commands to {@link MediaLibrarySession#MediaLibrarySessionCallback})
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ static final ArrayMap<Integer, Range> VERSION_LIBRARY_COMMANDS_MAP = new ArrayMap<>();
+
+ /**
+ * Command code for {@link MediaBrowser2#getLibraryRoot(Library2Params)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000;
+
+ /**
+ * Command code for {@link MediaBrowser2#subscribe(String, Library2Params)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001;
+
+ /**
+ * Command code for {@link MediaBrowser2#unsubscribe(String)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002;
+
+ /**
+ * Command code for {@link MediaBrowser2#getChildren(String, int, int, Library2Params)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003;
+
+ /**
+ * Command code for {@link MediaBrowser2#getItem(String)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004;
+
+ /**
+ * Command code for {@link MediaBrowser2#search(String, LibraryParams)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005;
+
+ /**
+ * Command code for {@link MediaBrowser2#getSearchResult(String, int, int, Library2Params)}.
+ * <p>
+ * Code version is {@link #COMMAND_VERSION_1}.
+ */
+ public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006;
+
+ static {
+ VERSION_LIBRARY_COMMANDS_MAP.put(COMMAND_VERSION_1,
+ new Range(COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT,
+ COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT));
+ }
+
+ @CommandCode private final int mCommandCode;
+ // Nonnull if it's custom command
+ private final String mCustomCommand;
+ private final Bundle mExtras;
+
+ /**
+ * Constructor for creating a predefined command.
+ *
+ * @param commandCode A command code for predefined command.
+ */
+ public Session2Command(@CommandCode int commandCode) {
+ if (commandCode == COMMAND_CODE_CUSTOM) {
+ throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
+ }
+ mCommandCode = commandCode;
+ mCustomCommand = null;
+ mExtras = null;
+ }
+
+ /**
+ * Constructor for creating a custom command.
+ *
+ * @param action The action of this custom command.
+ * @param extras An extra bundle for this custom command.
+ */
+ public Session2Command(@NonNull String action, @Nullable Bundle extras) {
+ if (action == null) {
+ throw new IllegalArgumentException("action shouldn't be null");
+ }
+ mCommandCode = COMMAND_CODE_CUSTOM;
+ mCustomCommand = action;
+ mExtras = extras;
+ }
+
+ /**
+ * Used by parcelable creator.
+ */
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ Session2Command(Parcel in) {
+ mCommandCode = in.readInt();
+ mCustomCommand = in.readString();
+ mExtras = in.readBundle();
+ }
+
+ /**
+ * Gets the command code of a predefined command.
+ * This will return {@link #COMMAND_CODE_CUSTOM} for a custom command.
+ */
+ public @CommandCode int getCommandCode() {
+ return mCommandCode;
+ }
+
+ /**
+ * Gets the action of a custom command.
+ * This will return {@code null} for a predefined command.
+ */
+ public @Nullable String getCustomCommand() {
+ return mCustomCommand;
+ }
+
+ /**
+ * Gets the extra bundle of a custom command.
+ * This will return {@code null} for a predefined command.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mCommandCode);
+ dest.writeString(mCustomCommand);
+ dest.writeBundle(mExtras);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Session2Command)) {
+ return false;
+ }
+ Session2Command other = (Session2Command) obj;
+ return mCommandCode == other.mCommandCode
+ && TextUtils.equals(mCustomCommand, other.mCustomCommand);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCustomCommand, mCommandCode);
+ }
+
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ static final class Range {
+ public final int lower;
+ public final int upper;
+
+ Range(int lower, int upper) {
+ this.lower = lower;
+ this.upper = upper;
+ }
+ }
+}
+
diff --git a/media/java/android/media/Session2CommandGroup.java b/media/java/android/media/Session2CommandGroup.java
new file mode 100644
index 0000000..de34fe5
--- /dev/null
+++ b/media/java/android/media/Session2CommandGroup.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright 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.media;
+
+import static android.media.Session2Command.COMMAND_CODE_CUSTOM;
+import static android.media.Session2Command.COMMAND_VERSION_1;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.Session2Command.Range;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A set of {@link Session2Command} which represents a command group.
+ * <p>
+ * This API is not generally intended for third party application developers.
+ * Use the <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>
+ * {@link androidx.media2.SessionCommandGroup} for consistent behavior across all devices.
+ * </p>
+ * @hide
+ */
+public final class Session2CommandGroup implements Parcelable {
+ private static final String TAG = "Session2CommandGroup";
+
+ public static final Parcelable.Creator<Session2CommandGroup> CREATOR =
+ new Parcelable.Creator<Session2CommandGroup>() {
+ @Override
+ public Session2CommandGroup createFromParcel(Parcel in) {
+ return new Session2CommandGroup(in);
+ }
+
+ @Override
+ public Session2CommandGroup[] newArray(int size) {
+ return new Session2CommandGroup[size];
+ }
+ };
+
+ Set<Session2Command> mCommands = new HashSet<>();
+
+ /**
+ * Default Constructor.
+ */
+ public Session2CommandGroup() { }
+
+ /**
+ * Creates a new Session2CommandGroup with commands copied from another object.
+ *
+ * @param commands The collection of commands to copy.
+ */
+ public Session2CommandGroup(@Nullable Collection<Session2Command> commands) {
+ if (commands != null) {
+ mCommands.addAll(commands);
+ }
+ }
+
+ /**
+ * Used by parcelable creator.
+ */
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ Session2CommandGroup(Parcel in) {
+ Session2Command[] commands = in.readParcelableArray(
+ Session2Command.class.getClassLoader(), Session2Command.class);
+ if (commands != null) {
+ for (Session2Command command : commands) {
+ mCommands.add(command);
+ }
+ }
+ }
+
+ /**
+ * Adds a command to this command group.
+ *
+ * @param command A command to add. Shouldn't be {@code null}.
+ * @hide TODO remove this method
+ */
+ public void addCommand(@NonNull Session2Command command) {
+ if (command == null) {
+ throw new IllegalArgumentException("command shouldn't be null");
+ }
+ if (!hasCommand(command)) {
+ mCommands.add(command);
+ }
+ }
+
+ /**
+ * Adds a predefined command with given {@code commandCode} to this command group.
+ *
+ * @param commandCode A command code to add.
+ * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}.
+ * @hide TODO remove this method
+ */
+ public void addCommand(@Session2Command.CommandCode int commandCode) {
+ if (commandCode == COMMAND_CODE_CUSTOM) {
+ throw new IllegalArgumentException(
+ "Use addCommand(Session2Command) for COMMAND_CODE_CUSTOM.");
+ }
+ if (!hasCommand(commandCode)) {
+ mCommands.add(new Session2Command(commandCode));
+ }
+ }
+
+ /**
+ * Checks whether this command group has a command that matches given {@code command}.
+ *
+ * @param command A command to find. Shouldn't be {@code null}.
+ */
+ public boolean hasCommand(@NonNull Session2Command command) {
+ if (command == null) {
+ throw new IllegalArgumentException("command shouldn't be null");
+ }
+ return mCommands.contains(command);
+ }
+
+ /**
+ * Checks whether this command group has a command that matches given {@code commandCode}.
+ *
+ * @param commandCode A command code to find.
+ * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}.
+ */
+ public boolean hasCommand(@Session2Command.CommandCode int commandCode) {
+ if (commandCode == COMMAND_CODE_CUSTOM) {
+ throw new IllegalArgumentException("Use hasCommand(Command) for custom command");
+ }
+ for (Session2Command command : mCommands) {
+ if (command.getCommandCode() == commandCode) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets all commands of this command group.
+ */
+ public @NonNull Set<Session2Command> getCommands() {
+ return new HashSet<>(mCommands);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelableArray((Session2Command[]) mCommands.toArray(), 0);
+ }
+
+ /**
+ * Builds a {@link Session2CommandGroup} object.
+ */
+ public static final class Builder {
+ private Set<Session2Command> mCommands;
+
+ public Builder() {
+ mCommands = new HashSet<>();
+ }
+
+ /**
+ * Creates a new builder for {@link Session2CommandGroup} with commands copied from another
+ * {@link Session2CommandGroup} object.
+ * @param commandGroup
+ */
+ public Builder(@NonNull Session2CommandGroup commandGroup) {
+ mCommands = commandGroup.getCommands();
+ }
+
+ /**
+ * Adds a command to this command group.
+ *
+ * @param command A command to add. Shouldn't be {@code null}.
+ */
+ public @NonNull Builder addCommand(@NonNull Session2Command command) {
+ if (command == null) {
+ throw new IllegalArgumentException("command shouldn't be null");
+ }
+ mCommands.add(command);
+ return this;
+ }
+
+ /**
+ * Adds a predefined command with given {@code commandCode} to this command group.
+ *
+ * @param commandCode A command code to add.
+ * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}.
+ */
+ public @NonNull Builder addCommand(@Session2Command.CommandCode int commandCode) {
+ if (commandCode == COMMAND_CODE_CUSTOM) {
+ throw new IllegalArgumentException(
+ "Use addCommand(Session2Command) for COMMAND_CODE_CUSTOM.");
+ }
+ mCommands.add(new Session2Command(commandCode));
+ return this;
+ }
+
+ /**
+ * Adds all predefined session commands except for the commands added after the specified
+ * version without default implementation. This provides convenient way to add commands
+ * with implementation.
+ *
+ * @param version command version
+ * @see Session2Command#COMMAND_VERSION_1
+ * @see
+ * MediaSession2.Session2Callback#onConnect
+ */
+ public @NonNull Builder addAllPredefinedCommands(
+ @Session2Command.CommandVersion int version) {
+ if (version != COMMAND_VERSION_1) {
+ throw new IllegalArgumentException("Unknown command version " + version);
+ }
+ addAllPlayerCommands(version);
+ addAllVolumeCommands(version);
+ addAllSessionCommands(version);
+ addAllLibraryCommands(version);
+ return this;
+ }
+
+ /**
+ * Removes a command from this group which matches given {@code command}.
+ *
+ * @param command A command to find. Shouldn't be {@code null}.
+ */
+ public @NonNull Builder removeCommand(@NonNull Session2Command command) {
+ if (command == null) {
+ throw new IllegalArgumentException("command shouldn't be null");
+ }
+ mCommands.remove(command);
+ return this;
+ }
+
+ /**
+ * Removes a command from this group which matches given {@code commandCode}.
+ *
+ * @param commandCode A command code to find.
+ * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}.
+ */
+ public @NonNull Builder removeCommand(@Session2Command.CommandCode int commandCode) {
+ if (commandCode == COMMAND_CODE_CUSTOM) {
+ throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
+ }
+ mCommands.remove(new Session2Command(commandCode));
+ return this;
+ }
+
+ @NonNull Builder addAllPlayerCommands(@Session2Command.CommandVersion int version) {
+ addCommands(version, Session2Command.VERSION_PLAYER_COMMANDS_MAP);
+ return this;
+ }
+
+ @NonNull Builder addAllPlayerCommands(@Session2Command.CommandVersion int version,
+ boolean includePlaylistCommands) {
+ if (includePlaylistCommands) {
+ return addAllPlayerCommands(version);
+ }
+ for (int i = COMMAND_VERSION_1; i <= version; i++) {
+ Range include = Session2Command.VERSION_PLAYER_COMMANDS_MAP.get(i);
+ Range exclude = Session2Command.VERSION_PLAYER_PLAYLIST_COMMANDS_MAP.get(i);
+ for (int code = include.lower; code <= include.upper; code++) {
+ if (code < exclude.lower && code > exclude.upper) {
+ addCommand(code);
+ }
+ }
+ }
+ return this;
+ }
+
+ @NonNull Builder addAllVolumeCommands(@Session2Command.CommandVersion int version) {
+ addCommands(version, Session2Command.VERSION_VOLUME_COMMANDS_MAP);
+ return this;
+ }
+
+ @NonNull Builder addAllSessionCommands(@Session2Command.CommandVersion int version) {
+ addCommands(version, Session2Command.VERSION_SESSION_COMMANDS_MAP);
+ return this;
+ }
+
+ @NonNull Builder addAllLibraryCommands(@Session2Command.CommandVersion int version) {
+ addCommands(version, Session2Command.VERSION_LIBRARY_COMMANDS_MAP);
+ return this;
+ }
+
+ private void addCommands(
+ @Session2Command.CommandVersion int version, ArrayMap<Integer, Range> map) {
+ for (int i = COMMAND_VERSION_1; i <= version; i++) {
+ Range range = map.get(i);
+ for (int code = range.lower; code <= range.upper; code++) {
+ addCommand(code);
+ }
+ }
+ }
+
+ /**
+ * Builds {@link Session2CommandGroup}.
+ *
+ * @return a new {@link Session2CommandGroup}.
+ */
+ public @NonNull Session2CommandGroup build() {
+ return new Session2CommandGroup(mCommands);
+ }
+ }
+}
diff --git a/media/java/android/media/Session2Token.java b/media/java/android/media/Session2Token.java
new file mode 100644
index 0000000..af14078
--- /dev/null
+++ b/media/java/android/media/Session2Token.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 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.media;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents an ongoing {@link MediaSession2} or a {@link MediaSession2Service}.
+ * If it's representing a session service, it may not be ongoing.
+ * <p>
+ * This API is not generally intended for third party application developers.
+ * Use the <a href="{@docRoot}jetpack/androidx/">Support Library</a> instead.
+ * {@link androidx.media2.SessionToken} for consistent behavior across all devices.
+ * <p>
+ * This may be passed to apps by the session owner to allow them to create a
+ * {@link MediaController2} to communicate with the session.
+ * <p>
+ * It can be also obtained by {@link MediaSessionManager}.
+ *
+ * @hide
+ */
+// New version of MediaSession2.Token for following reasons
+// - Stop implementing Parcelable for updatable support
+// - Represent session and library service (formerly browser service) in one class.
+// Previously MediaSession2.Token was for session and ComponentName was for service.
+// This helps controller apps to keep target of dispatching media key events in uniform way.
+// For details about the reason, see following. (Android O+)
+// android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged
+public final class Session2Token implements Parcelable {
+ private static final String TAG = "Session2Token";
+
+ public static final Creator<Session2Token> CREATOR = new Creator<Session2Token>() {
+ @Override
+ public Session2Token createFromParcel(Parcel p) {
+ return new Session2Token(p);
+ }
+
+ @Override
+ public Session2Token[] newArray(int size) {
+ return new Session2Token[size];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE})
+ public @interface TokenType {
+ }
+
+ /**
+ * Type for {@link MediaSession2}.
+ */
+ public static final int TYPE_SESSION = 0;
+
+ /**
+ * Type for {@link MediaSessionService2}.
+ */
+ public static final int TYPE_SESSION_SERVICE = 1;
+
+ /**
+ * Type for {@link MediaLibraryService2}.
+ */
+ public static final int TYPE_LIBRARY_SERVICE = 2;
+
+ private final int mUid;
+ private final @TokenType int mType;
+ private final String mPackageName;
+ private final String mServiceName;
+ private final IBinder mISession;
+ private final ComponentName mComponentName;
+
+ /**
+ * Constructor for the token. You can create token of {@link MediaSessionService2},
+ * {@link MediaLibraryService2} for {@link MediaController2} or {@link MediaBrowser2}.
+ *
+ * @param context The context.
+ * @param serviceComponent The component name of the service.
+ */
+ public Session2Token(@NonNull Context context, @NonNull ComponentName serviceComponent) {
+ if (context == null) {
+ throw new IllegalArgumentException("context shouldn't be null");
+ }
+ if (serviceComponent == null) {
+ throw new IllegalArgumentException("serviceComponent shouldn't be null");
+ }
+
+ final PackageManager manager = context.getPackageManager();
+ final int uid = getUid(manager, serviceComponent.getPackageName());
+
+ // TODO: Uncomment below to stop hardcode type.
+ final int type = TYPE_SESSION_SERVICE;
+// final int type;
+// if (isInterfaceDeclared(manager, MediaLibraryService2.SERVICE_INTERFACE,
+// serviceComponent)) {
+// type = TYPE_LIBRARY_SERVICE;
+// } else if (isInterfaceDeclared(manager, MediaSessionService2.SERVICE_INTERFACE,
+// serviceComponent)) {
+// type = TYPE_SESSION_SERVICE;
+// } else if (isInterfaceDeclared(manager,
+// MediaBrowserServiceCompat.SERVICE_INTERFACE, serviceComponent)) {
+// type = TYPE_BROWSER_SERVICE_LEGACY;
+// } else {
+// throw new IllegalArgumentException(serviceComponent + " doesn't implement none of"
+// + " MediaSessionService2, MediaLibraryService2, MediaBrowserService nor"
+// + " MediaBrowserServiceCompat. Use service's full name.");
+// }
+ mComponentName = serviceComponent;
+ mPackageName = serviceComponent.getPackageName();
+ mServiceName = serviceComponent.getClassName();
+ mUid = uid;
+ mType = type;
+ mISession = null;
+ }
+
+ // TODO: Uncomment below
+// Session2Token(int uid, int type, String packageName, IMediaSession2 iSession) {
+// mUid = uid;
+// mType = type;
+// mPackageName = packageName;
+// mServiceName = null;
+// mComponentName = null;
+// mISession = iSession.asBinder();
+// }
+
+ Session2Token(Parcel in) {
+ mUid = in.readInt();
+ mType = in.readInt();
+ mPackageName = in.readString();
+ mServiceName = in.readString();
+ // TODO: Uncomment below and stop hardcode mISession
+ mISession = null;
+ //mISession = ISession.Stub.asInterface(in.readStrongBinder());
+ mComponentName = ComponentName.unflattenFromString(in.readString());
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mUid);
+ dest.writeInt(mType);
+ dest.writeString(mPackageName);
+ dest.writeString(mServiceName);
+ // TODO: Uncomment below
+ //dest.writeStrongBinder(mISession.asBinder());
+ dest.writeString(mComponentName == null ? "" : mComponentName.flattenToString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mUid, mPackageName, mServiceName, mISession);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Session2Token)) {
+ return false;
+ }
+ Session2Token other = (Session2Token) obj;
+ return mUid == other.mUid
+ && TextUtils.equals(mPackageName, other.mPackageName)
+ && TextUtils.equals(mServiceName, other.mServiceName)
+ && mType == other.mType
+ && Objects.equals(mISession, other.mISession);
+ }
+
+ @Override
+ public String toString() {
+ return "Session2Token {pkg=" + mPackageName + " type=" + mType
+ + " service=" + mServiceName + " IMediaSession2=" + mISession + "}";
+ }
+
+ /**
+ * @return uid of the session
+ */
+ public int getUid() {
+ return mUid;
+ }
+
+ /**
+ * @return package name of the session
+ */
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * @return service name of the session. Can be {@code null} for {@link #TYPE_SESSION}.
+ */
+ @Nullable
+ public String getServiceName() {
+ return mServiceName;
+ }
+
+ /**
+ * @hide
+ * @return component name of the session. Can be {@code null} for {@link #TYPE_SESSION}.
+ */
+ public ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ /**
+ * @return type of the token
+ * @see #TYPE_SESSION
+ * @see #TYPE_SESSION_SERVICE
+ * @see #TYPE_LIBRARY_SERVICE
+ */
+ public @TokenType int getType() {
+ return mType;
+ }
+
+ /**
+ * @hide
+ */
+ public Object getBinder() {
+ return mISession;
+ }
+
+ private static boolean isInterfaceDeclared(PackageManager manager, String serviceInterface,
+ ComponentName serviceComponent) {
+ Intent serviceIntent = new Intent(serviceInterface);
+ // Use queryIntentServices to find services with MediaLibraryService2.SERVICE_INTERFACE.
+ // We cannot use resolveService with intent specified class name, because resolveService
+ // ignores actions if Intent.setClassName() is specified.
+ serviceIntent.setPackage(serviceComponent.getPackageName());
+
+ List<ResolveInfo> list = manager.queryIntentServices(
+ serviceIntent, PackageManager.GET_META_DATA);
+ if (list != null) {
+ for (int i = 0; i < list.size(); i++) {
+ ResolveInfo resolveInfo = list.get(i);
+ if (resolveInfo == null || resolveInfo.serviceInfo == null) {
+ continue;
+ }
+ if (TextUtils.equals(
+ resolveInfo.serviceInfo.name, serviceComponent.getClassName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static int getUid(PackageManager manager, String packageName) {
+ try {
+ return manager.getApplicationInfo(packageName, 0).uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException("Cannot find package " + packageName);
+ }
+ }
+}
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index 1dca10a..2fe740d 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -76,7 +76,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
- systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivity;launchFlags=0x14008000;end"
+ systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivity;launchFlags=0x24000000;end"
/>
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index c039fcc..959f9b2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -16,7 +16,6 @@
package com.android.settingslib.media;
import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
@@ -36,12 +35,6 @@
super(context, MediaDeviceType.TYPE_BLUETOOTH_DEVICE);
mCachedDevice = device;
initDeviceRecord();
- buildConnectedState(device);
- }
-
- private void buildConnectedState(CachedBluetoothDevice device) {
- mIsConnected = device.isActiveDevice(BluetoothProfile.A2DP)
- || device.isActiveDevice(BluetoothProfile.HEARING_AID);
}
@Override
@@ -61,11 +54,6 @@
}
@Override
- public void notifyConnectedChanged() {
- buildConnectedState(mCachedDevice);
- }
-
- @Override
public void connect() {
//TODO(b/117129183): add callback to notify LocalMediaManager connection state.
mIsConnected = mCachedDevice.setActive();
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
index a9fc434..ab1cca0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
@@ -18,7 +18,6 @@
import android.app.Notification;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
@@ -31,7 +30,6 @@
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
/**
@@ -41,8 +39,8 @@
private static final String TAG = "BluetoothMediaManager";
- private final DeviceProfileNotReadyObserverCallback mObserverCallback =
- new DeviceProfileNotReadyObserverCallback();
+ private final DeviceAttributeChangeCallback mCachedDeviceCallback =
+ new DeviceAttributeChangeCallback();
private LocalBluetoothManager mLocalBluetoothManager;
private LocalBluetoothProfileManager mProfileManager;
@@ -50,10 +48,6 @@
private MediaDevice mLastAddedDevice;
private MediaDevice mLastRemovedDevice;
- private boolean mIsA2dpProfileReady = false;
- private boolean mIsHearingAidProfileReady = false;
- private Collection<CachedBluetoothDevice> mCachedDevices;
-
BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
Notification notification) {
super(context, notification);
@@ -68,18 +62,6 @@
mLocalBluetoothManager.getEventManager().registerCallback(this);
buildBluetoothDeviceList();
dispatchDeviceListAdded();
-
- // The profile may not ready when calling startScan().
- // Device status are all disconnected since profiles are not ready to connected.
- // In this case, we observe all devices in CachedDeviceManager.
- // When one of these device is connected to profile, will call buildBluetoothDeviceList()
- // again to find the connected devices.
- if (!mIsA2dpProfileReady && !mIsHearingAidProfileReady) {
- mCachedDevices = mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
- for (CachedBluetoothDevice device : mCachedDevices) {
- device.registerCallback(mObserverCallback);
- }
- }
}
private void buildBluetoothDeviceList() {
@@ -114,8 +96,6 @@
addMediaDevice(cachedDevice);
}
}
-
- mIsA2dpProfileReady = a2dpProfile.isProfileReady();
}
private void addConnectedHearingAidDevices() {
@@ -150,14 +130,13 @@
addMediaDevice(cachedDevice);
}
}
-
- mIsHearingAidProfileReady = hapProfile.isProfileReady();
}
private void addMediaDevice(CachedBluetoothDevice cachedDevice) {
MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
if (mediaDevice == null) {
mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
+ cachedDevice.registerCallback(mCachedDeviceCallback);
mLastAddedDevice = mediaDevice;
mMediaDevices.add(mediaDevice);
}
@@ -166,6 +145,16 @@
@Override
public void stopScan() {
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+ unregisterCachedDeviceCallback();
+ }
+
+ private void unregisterCachedDeviceCallback() {
+ for (MediaDevice device : mMediaDevices) {
+ if (device instanceof BluetoothMediaDevice) {
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mCachedDeviceCallback);
+ }
+ }
}
@Override
@@ -177,6 +166,8 @@
final List<MediaDevice> removeDevicesList = new ArrayList<>();
for (MediaDevice device : mMediaDevices) {
if (device instanceof BluetoothMediaDevice) {
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mCachedDeviceCallback);
removeDevicesList.add(device);
}
}
@@ -221,6 +212,7 @@
private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
if (mediaDevice != null) {
+ cachedDevice.unregisterCallback(mCachedDeviceCallback);
mLastRemovedDevice = mediaDevice;
mMediaDevices.remove(mediaDevice);
}
@@ -260,30 +252,10 @@
dispatchDeviceRemoved(cachedDevice);
}
}
-
- @Override
- public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
- Log.d(TAG, "onActiveDeviceChanged : device : "
- + activeDevice + ", profile : " + bluetoothProfile);
- if (BluetoothProfile.HEARING_AID == bluetoothProfile
- || BluetoothProfile.A2DP == bluetoothProfile) {
- final String id = activeDevice == null
- ? PhoneMediaDevice.ID : MediaDeviceUtils.getId(activeDevice);
- dispatchActiveDeviceChanged(id);
- }
- }
-
- class DeviceProfileNotReadyObserverCallback implements CachedBluetoothDevice.Callback {
-
+ class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
@Override
public void onDeviceAttributesChanged() {
- if (!mIsA2dpProfileReady && !mIsHearingAidProfileReady) {
- for (CachedBluetoothDevice device : mCachedDevices) {
- device.unregisterCallback(mObserverCallback);
- }
- buildBluetoothDeviceList();
- dispatchDeviceListAdded();
- }
+ dispatchDeviceAttributesChanged();
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index a2b161f..21a81e0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -16,7 +16,6 @@
package com.android.settingslib.media;
import android.content.Context;
-import android.widget.Toast;
import androidx.mediarouter.media.MediaRouter;
@@ -54,22 +53,15 @@
}
@Override
- public void notifyConnectedChanged() {
- //TODO(b/117129183): check mIsConnected state
- }
-
- @Override
public void connect() {
//TODO(b/117129183): use MediaController2 to transfer media
mIsConnected = true;
super.connect();
- //mIsConnected = true;
- Toast.makeText(mContext, "This is cast device !", Toast.LENGTH_SHORT).show();
}
@Override
public void disconnect() {
//TODO(b/117129183): disconnected last select device
- //mIsConnected = false;
+ mIsConnected = false;
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 154834e..c9479d4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -39,9 +39,6 @@
private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
private static final String TAG = "LocalMediaManager";
- public static final String NOTIFICATION_EXTRA = "notification_extra";
- public static final String NOTIFICATION_PACKAGE_NAME = "notification_package_name";
-
@Retention(RetentionPolicy.SOURCE)
@IntDef({MediaDeviceState.STATE_CONNECTED,
MediaDeviceState.STATE_CONNECTING,
@@ -61,6 +58,7 @@
private InfoMediaManager mInfoMediaManager;
private LocalBluetoothManager mLocalBluetoothManager;
+ private MediaDevice mLastConnectedDevice;
private MediaDevice mPhoneDevice;
/**
@@ -100,43 +98,29 @@
* @param connectDevice the MediaDevice
*/
public void connectDevice(MediaDevice connectDevice) {
- final MediaDevice currentDevice = getCurrentConnectedDevice();
- final MediaDevice device =
- MediaDeviceUtils.findMediaDevice(mMediaDevices, connectDevice.getId());
- if (device != null && currentDevice != null
- && device.getId().equals(currentDevice.getId())) {
+ if (connectDevice == mLastConnectedDevice) {
return;
}
- //TODO(b/117129183): For demo, will remove check connectDevice is InfoMediaDevice.
- if (currentDevice != null && !(connectDevice instanceof InfoMediaDevice)) {
- currentDevice.disconnect();
+ if (mLastConnectedDevice != null) {
+ mLastConnectedDevice.disconnect();
}
- device.connect();
+ connectDevice.connect();
+ if (connectDevice.isConnected()) {
+ mLastConnectedDevice = connectDevice;
+ }
- final int state = device.isConnected()
+ final int state = connectDevice.isConnected()
? MediaDeviceState.STATE_CONNECTED
: MediaDeviceState.STATE_DISCONNECTED;
- dispatchSelectedDeviceStateChanged(mMediaDevices, device, state);
+ dispatchSelectedDeviceStateChanged(connectDevice, state);
}
- private MediaDevice getCurrentConnectedDevice() {
- for (MediaDevice device : mMediaDevices) {
- if (device.isConnected()) {
- return device;
- }
- }
- Log.w(TAG, "getCurrentConnectedDevice() cannot find current connected device !");
- return null;
- }
-
- void dispatchSelectedDeviceStateChanged(List<MediaDevice> mMediaDevices, MediaDevice device,
- @MediaDeviceState int state) {
+ void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
synchronized (mCallbacks) {
for (DeviceCallback callback : mCallbacks) {
- callback.onSelectedDeviceStateChanged(new ArrayList<>(mMediaDevices), device,
- state);
+ callback.onSelectedDeviceStateChanged(device, state);
}
}
}
@@ -188,6 +172,23 @@
mInfoMediaManager.stopScan();
}
+ /**
+ * Find the MediaDevice through id.
+ *
+ * @param devices the list of MediaDevice
+ * @param id the unique id of MediaDevice
+ * @return MediaDevice
+ */
+ public MediaDevice getMediaDeviceById(List<MediaDevice> devices, String id) {
+ for (MediaDevice mediaDevice : devices) {
+ if (mediaDevice.getId().equals(id)) {
+ return mediaDevice;
+ }
+ }
+ Log.i(TAG, "getMediaDeviceById() can't found device");
+ return null;
+ }
+
class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
@Override
public void onDeviceAdded(MediaDevice device) {
@@ -225,25 +226,6 @@
public void onDeviceAttributesChanged() {
dispatchDeviceListUpdate();
}
-
- @Override
- public void onActiveDeviceChanged(String id) {
- final MediaDevice currentDevice = getCurrentConnectedDevice();
- final MediaDevice connectDevice = MediaDeviceUtils.findMediaDevice(mMediaDevices, id);
-
- if (connectDevice != null && currentDevice != null
- && connectDevice.getId().equals(currentDevice.getId())) {
- return;
- }
- if (currentDevice != null) {
- currentDevice.notifyConnectedChanged();
- }
- if (connectDevice != null) {
- connectDevice.notifyConnectedChanged();
- }
-
- dispatchDeviceListUpdate();
- }
}
@@ -267,7 +249,6 @@
* {@link MediaDeviceState#STATE_CONNECTING},
* {@link MediaDeviceState#STATE_DISCONNECTED}
*/
- void onSelectedDeviceStateChanged(List<MediaDevice> devices, MediaDevice device,
- @MediaDeviceState int state);
+ void onSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index e4aeda6..33b621c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -17,7 +17,6 @@
import android.content.Context;
import android.text.TextUtils;
-import android.util.Log;
import androidx.annotation.IntDef;
@@ -55,7 +54,6 @@
ConnectionRecordManager.getInstance().fetchLastSelectedDevice(mContext);
mConnectedRecord = ConnectionRecordManager.getInstance().fetchConnectionRecord(mContext,
getId());
- Log.d("ttttt", getName() + " used: " + mConnectedRecord);
}
/**
@@ -88,11 +86,6 @@
public abstract String getId();
/**
- * Notify MediaDevice to change their connected state.
- */
- public abstract void notifyConnectedChanged();
-
- /**
* Transfer MediaDevice for media
*/
public void connect() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
index 8066eb0..bdddaf3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
@@ -15,21 +15,14 @@
*/
package com.android.settingslib.media;
-import android.util.Log;
-
import androidx.mediarouter.media.MediaRouter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import java.util.List;
-
/**
* MediaDeviceUtils provides utility function for MediaDevice
*/
public class MediaDeviceUtils {
-
- private static final String TAG = "MediaDeviceUtils";
-
/**
* Use CachedBluetoothDevice address to represent unique id
*
@@ -49,21 +42,4 @@
public static String getId(MediaRouter.RouteInfo route) {
return route.getId();
}
-
- /**
- * Find the MediaDevice through id.
- *
- * @param devices the list of MediaDevice
- * @param id the unique id of MediaDevice
- * @return MediaDevice
- */
- public static MediaDevice findMediaDevice(List<MediaDevice> devices, String id) {
- for (MediaDevice mediaDevice : devices) {
- if (mediaDevice.getId().equals(id)) {
- return mediaDevice;
- }
- }
- Log.e(TAG, "findMediaDevice() can't found device");
- return null;
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
index ee11070..72b6b09 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
@@ -17,6 +17,7 @@
import android.app.Notification;
import android.content.Context;
+import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
@@ -67,7 +68,13 @@
public abstract void stopScan();
protected MediaDevice findMediaDevice(String id) {
- return MediaDeviceUtils.findMediaDevice(mMediaDevices, id);
+ for (MediaDevice mediaDevice : mMediaDevices) {
+ if (mediaDevice.getId().equals(id)) {
+ return mediaDevice;
+ }
+ }
+ Log.e(TAG, "findMediaDevice() can't found device");
+ return null;
}
protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
@@ -89,7 +96,7 @@
protected void dispatchDeviceListAdded() {
synchronized (mCallbacks) {
for (MediaDeviceCallback callback : mCallbacks) {
- callback.onDeviceListAdded(new ArrayList<>(mMediaDevices));
+ callback.onDeviceListAdded(mMediaDevices);
}
}
}
@@ -110,14 +117,6 @@
}
}
- protected void dispatchActiveDeviceChanged(String id) {
- synchronized (mCallbacks) {
- for (MediaDeviceCallback callback : mCallbacks) {
- callback.onActiveDeviceChanged(id);
- }
- }
- }
-
/**
* Callback for notifying device is added, removed and attributes changed.
*/
@@ -154,12 +153,5 @@
* Callback for notifying MediaDevice attributes is changed.
*/
void onDeviceAttributesChanged();
-
- /**
- * Callback for notifying active MediaDevice is changed.
- *
- * @param id the id of MediaDevice
- */
- void onActiveDeviceChanged(String id);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 59150f1..e0f3c2f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -15,7 +15,6 @@
*/
package com.android.settingslib.media;
-import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.util.Log;
@@ -25,8 +24,6 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import java.util.List;
-
/**
* PhoneMediaDevice extends MediaDevice to represents Phone device.
*/
@@ -45,29 +42,6 @@
mLocalBluetoothManager = localBluetoothManager;
mProfileManager = mLocalBluetoothManager.getProfileManager();
initDeviceRecord();
-
- mIsConnected = isPhoneActive();
- }
-
- private boolean isPhoneActive() {
- boolean isActive = true;
-
- final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
- final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
-
- if (a2dpProfile.getActiveDevice() == null) {
- final List<BluetoothDevice> activeDevices = hapProfile.getActiveDevices();
- for (BluetoothDevice btDevice : activeDevices) {
- if (btDevice != null) {
- isActive = false;
- break;
- }
- }
- } else {
- isActive = false;
- }
-
- return isActive;
}
@Override
@@ -88,11 +62,6 @@
}
@Override
- public void notifyConnectedChanged() {
- mIsConnected = isPhoneActive();
- }
-
- @Override
public void connect() {
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 089f773..871e248 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -101,6 +101,9 @@
}
public void handleBroadcast(Intent intent) {
+ if (mWifiManager == null) {
+ return;
+ }
String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
updateWifiState();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 2f082b9..e47ca32 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -212,7 +212,7 @@
mConnectivityManager = connectivityManager;
// check if verbose logging developer option has been turned on or off
- sVerboseLogging = (mWifiManager.getVerboseLoggingLevel() > 0);
+ sVerboseLogging = mWifiManager != null && (mWifiManager.getVerboseLoggingLevel() > 0);
mFilter = filter;
@@ -283,7 +283,7 @@
mScanner = new Scanner();
}
- if (mWifiManager.isWifiEnabled()) {
+ if (isWifiEnabled()) {
mScanner.resume();
}
}
@@ -413,7 +413,7 @@
}
public boolean isWifiEnabled() {
- return mWifiManager.isWifiEnabled();
+ return mWifiManager != null && mWifiManager.isWifiEnabled();
}
/**
@@ -638,7 +638,7 @@
private void updateNetworkInfo(NetworkInfo networkInfo) {
/* Sticky broadcasts can call this when wifi is disabled */
- if (!mWifiManager.isWifiEnabled()) {
+ if (!isWifiEnabled()) {
clearAccessPointsAndConditionallyUpdate();
return;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 1cbf277..9bbdd01 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -25,10 +25,8 @@
import androidx.mediarouter.media.MediaRouter;
-import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.Before;
import org.junit.Test;
@@ -61,8 +59,6 @@
new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
@Mock
- private A2dpProfile mA2dpProfile;
- @Mock
private BluetoothDevice mDevice1;
@Mock
private BluetoothDevice mDevice2;
@@ -77,8 +73,6 @@
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
- private LocalBluetoothProfileManager mProfileManager;
- @Mock
private MediaRouter.RouteInfo mRouteInfo1;
@Mock
private MediaRouter.RouteInfo mRouteInfo2;
@@ -115,9 +109,6 @@
when(mRouteInfo1.getName()).thenReturn(DEVICE_NAME_1);
when(mRouteInfo2.getName()).thenReturn(DEVICE_NAME_2);
when(mRouteInfo3.getName()).thenReturn(DEVICE_NAME_3);
- when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
- when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
- when(mA2dpProfile.getActiveDevice()).thenReturn(mDevice1);
mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1);
mBluetoothMediaDevice2 = new BluetoothMediaDevice(mContext, mCachedDevice2);
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index 7751bb1..cca2d13 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -6,6 +6,8 @@
Go read about Dagger 2.
+ - [User's guide](https://google.github.io/dagger/users-guide)
+
TODO: Add some links.
## State of the world
diff --git a/packages/SystemUI/res/drawable/ic_home_button_outline.xml b/packages/SystemUI/res/drawable/ic_home_button_outline.xml
deleted file mode 100644
index 5bf345d..0000000
--- a/packages/SystemUI/res/drawable/ic_home_button_outline.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- ~ 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
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="28dp"
- android:height="10dp"
- android:viewportWidth="28"
- android:viewportHeight="10">
- <path
- android:pathData="M23,1H5C2.7909,1 1,2.7909 1,5C1,7.2091 2.7909,9 5,9H23C25.2091,9 27,7.2091 27,5C27,2.7909 25.2091,1 23,1ZM5,0C2.2386,0 0,2.2386 0,5C0,7.7614 2.2386,10 5,10H23C25.7614,10 28,7.7614 28,5C28,2.2386 25.7614,0 23,0H5Z"
- android:fillColor="?attr/wallpaperTextColor"
- android:fillType="evenOdd"/>
-</vector>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 5766604..669e6ff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -208,9 +208,11 @@
android.app.slice.SliceItem.FORMAT_IMAGE);
if (icon != null) {
iconDrawable = icon.getIcon().loadDrawable(mContext);
- final int width = (int) (iconDrawable.getIntrinsicWidth()
- / (float) iconDrawable.getIntrinsicHeight() * mIconSize);
- iconDrawable.setBounds(0, 0, Math.max(width, 1), mIconSize);
+ if (iconDrawable != null) {
+ final int width = (int) (iconDrawable.getIntrinsicWidth()
+ / (float) iconDrawable.getIntrinsicHeight() * mIconSize);
+ iconDrawable.setBounds(0, 0, Math.max(width, 1), mIconSize);
+ }
}
button.setCompoundDrawables(iconDrawable, null, null, null);
button.setOnClickListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f51004a..08fa434 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -54,6 +54,7 @@
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
@@ -266,6 +267,8 @@
@Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler;
@Inject Lazy<BubbleController> mBubbleController;
@Inject Lazy<NotificationEntryManager> mNotificationEntryManager;
+ @Inject
+ Lazy<NotificationAlertingManager> mNotificationAlertingManager;
@Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
@Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper;
@Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler;
@@ -439,6 +442,7 @@
mRemoteInputQuickSettingsDisabler::get);
mProviders.put(BubbleController.class, mBubbleController::get);
mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get);
+ mProviders.put(NotificationAlertingManager.class, mNotificationAlertingManager::get);
sDependency = this;
}
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index 23ef030..b93a5fd 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -22,6 +22,8 @@
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.ManagedProfileController;
@@ -224,4 +226,9 @@
*/
@Binds
public abstract PowerUI.WarningsUI provideWarningsUi(PowerNotificationWarnings controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract QSHost provideQsHost(QSTileHost controllerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index 6edc23b..4285af0 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -16,6 +16,8 @@
import android.util.Log;
+import com.android.systemui.statusbar.phone.StatusBar;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -63,6 +65,11 @@
}
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
+ if (mStatusBar instanceof StatusBar) {
+ SystemUIFactory.getInstance().getRootComponent()
+ .getStatusBarInjector()
+ .createStatusBar((StatusBar) mStatusBar);
+ }
mStatusBar.start();
if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 8bac7c5..e3bfdc9 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -34,7 +34,6 @@
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
-import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -52,10 +51,10 @@
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ScrimState;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.InjectionInflationController;
+import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeDialogComponent;
import java.util.function.Consumer;
@@ -144,11 +143,6 @@
return new KeyguardIndicationController(context, indicationArea, lockIcon);
}
- public QSTileHost createQSTileHost(Context context, StatusBar statusBar,
- StatusBarIconController iconController) {
- return new QSTileHost(context, statusBar, iconController);
- }
-
public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) {
return new VolumeDialogComponent(systemUi, context);
}
@@ -227,6 +221,9 @@
@Singleton
Dependency.DependencyInjector createDependency();
+ @Singleton
+ StatusBar.StatusBarInjector getStatusBarInjector();
+
/**
* FragmentCreator generates all Fragments that need injection.
*/
@@ -237,5 +234,8 @@
* ViewCreator generates all Views that need injection.
*/
InjectionInflationController.ViewCreator createViewCreator();
+
+ @Singleton
+ GarbageMonitor createGarbageMonitor();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index c8595eb..881aa18 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -33,7 +33,6 @@
import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
@@ -122,12 +121,12 @@
}
@Inject
- public BubbleController(Context context) {
+ public BubbleController(Context context, StatusBarWindowController statusBarWindowController) {
mContext = context;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplaySize = new Point();
wm.getDefaultDisplay().getSize(mDisplaySize);
- mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
+ mStatusBarWindowController = statusBarWindowController;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java
deleted file mode 100644
index f34d6b3..0000000
--- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.car;
-
-import android.content.Context;
-
-import com.android.systemui.statusbar.NotificationMediaManager;
-
-public class CarNotificationMediaManager extends NotificationMediaManager {
- public CarNotificationMediaManager(Context context) {
- super(context);
- }
-
- @Override
- public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
- // Do nothing, we don't want to display media art in the lock screen for a car.
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dock/DockManager.java b/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
index 233b9c6..47b56d0 100644
--- a/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
+++ b/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
@@ -22,7 +22,7 @@
public interface DockManager {
/**
- * Uninitialized / unknow dock states
+ * Uninitialized / unknown dock states
*/
int STATE_NONE = 0;
/**
@@ -37,14 +37,14 @@
/**
* Add a dock event listener into manager
*
- * @param callback A {@link #DockEventListener} which want to add
+ * @param callback A {@link DockEventListener} which want to add
*/
void addListener(DockEventListener callback);
/**
* Remove the added listener from dock manager
*
- * @param callback A {@link #DockEventListener} which want to remove
+ * @param callback A {@link DockEventListener} which want to remove
*/
void removeListener(DockEventListener callback);
@@ -52,8 +52,6 @@
interface DockEventListener {
/**
* Override to handle dock events
- *
- * Events reference: {@link #DockState}
*/
void onEvent(int event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index fa33cb8..8cd42c7 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -86,12 +86,12 @@
private void requestPulseOutNow() {
final DozeMachine.State state = mMachine.getState();
- final int pulseReason = mMachine.getPulseReason();
-
- if ((state == DozeMachine.State.DOZE_PULSING
- || state == DozeMachine.State.DOZE_REQUEST_PULSE)
- && pulseReason == DozeLog.PULSE_REASON_DOCKING) {
- mDozeHost.stopPulsing();
+ if (state == DozeMachine.State.DOZE_PULSING
+ || state == DozeMachine.State.DOZE_REQUEST_PULSE) {
+ final int pulseReason = mMachine.getPulseReason();
+ if (pulseReason == DozeLog.PULSE_REASON_DOCKING) {
+ mDozeHost.stopPulsing();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index ab77e55..50003e3 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 REASONS = 8;
+ private static final int REASONS = 9;
public static final int PULSE_REASON_NONE = -1;
public static final int PULSE_REASON_INTENT = 0;
@@ -46,6 +46,7 @@
public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
public static final int PULSE_REASON_DOCKING = 6;
public static final int REASON_SENSOR_WAKE_UP = 7;
+ public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8;
private static boolean sRegisterKeyguardCallback = true;
@@ -178,15 +179,6 @@
}
/**
- * Appends lock screen wake up event to the logs.
- * @param wake if we're waking up or sleeping.
- */
- public static void traceLockScreenWakeUp(boolean wake) {
- if (!ENABLED) return;
- log("wakeLockScreen " + wake);
- }
-
- /**
* Appends wake-display event to the logs.
* @param wake if we're waking up or sleeping.
*/
@@ -213,6 +205,7 @@
case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
case PULSE_REASON_DOCKING: return "docking";
+ case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen";
case REASON_SENSOR_WAKE_UP: return "wakeup";
default: throw new IllegalArgumentException("bad reason: " + pulseReason);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index c2676d0..35b64ed 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -17,6 +17,7 @@
package com.android.systemui.doze;
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY;
+import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
import android.annotation.AnyThread;
import android.app.ActivityManager;
@@ -115,10 +116,17 @@
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
- true /* configured */,
+ mConfig.wakeScreenGestureAvailable(),
DozeLog.REASON_SENSOR_WAKE_UP,
false /* reports touch coordinates */,
false /* touchscreen */),
+ new PluginSensor(
+ new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
+ Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
+ mConfig.wakeScreenGestureAvailable(),
+ DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
+ false /* reports touch coordinates */,
+ false /* touchscreen */),
};
mProxSensor = new ProxSensor(policy);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 1e228f2..6a9b689 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -135,11 +135,12 @@
boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
boolean isWakeDisplay = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP;
+ boolean isWakeLockScreen = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN;
boolean wakeEvent = rawValues != null && rawValues.length > 0 && rawValues[0] != 0;
if (isWakeDisplay) {
onWakeScreen(wakeEvent);
- } else if (isLongPress) {
+ } else if (isLongPress || isWakeLockScreen) {
requestPulse(pulseReason, sensorPerformedProxCheck);
} else {
proximityCheckThenCall((result) -> {
@@ -156,7 +157,6 @@
mDozeHost.extendPulse();
}
}, sensorPerformedProxCheck, pulseReason);
- return;
}
if (isPickup) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/LockScreenWakeUpController.java b/packages/SystemUI/src/com/android/systemui/doze/LockScreenWakeUpController.java
deleted file mode 100644
index 70143e2..0000000
--- a/packages/SystemUI/src/com/android/systemui/doze/LockScreenWakeUpController.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.doze;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.SensorManagerPlugin;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.util.AsyncSensorManager;
-
-/**
- * Controller responsible for waking up or making the device sleep based on ambient sensors.
- */
-public class LockScreenWakeUpController implements StatusBarStateController.StateListener,
- SensorManagerPlugin.SensorEventListener {
-
- private static final String TAG = LockScreenWakeUpController.class.getSimpleName();
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private final AsyncSensorManager mAsyncSensorManager;
- private final SensorManagerPlugin.Sensor mSensor;
- private final AmbientDisplayConfiguration mAmbientConfiguration;
- private final PowerManager mPowerManager;
- private final DozeHost mDozeHost;
- private final Handler mHandler;
- private boolean mRegistered;
- private boolean mDozing;
-
- public LockScreenWakeUpController(Context context, DozeHost dozeHost) {
- this(Dependency.get(AsyncSensorManager.class),
- new SensorManagerPlugin.Sensor(SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN),
- new AmbientDisplayConfiguration(context),
- context.getSystemService(PowerManager.class),
- dozeHost, Dependency.get(StatusBarStateController.class), new Handler());
- }
-
- @VisibleForTesting
- public LockScreenWakeUpController(AsyncSensorManager asyncSensorManager,
- SensorManagerPlugin.Sensor sensor, AmbientDisplayConfiguration ambientConfiguration,
- PowerManager powerManager, DozeHost dozeHost,
- StatusBarStateController statusBarStateController, Handler handler) {
- mAsyncSensorManager = asyncSensorManager;
- mSensor = sensor;
- mAmbientConfiguration = ambientConfiguration;
- mPowerManager = powerManager;
- mDozeHost = dozeHost;
- mHandler = handler;
- statusBarStateController.addCallback(this);
- }
-
- @Override
- public void onStateChanged(int newState) {
- boolean isLockScreen = newState == StatusBarState.KEYGUARD
- || newState == StatusBarState.SHADE_LOCKED;
-
- if (!mAmbientConfiguration.wakeLockScreenGestureEnabled(UserHandle.USER_CURRENT)) {
- if (mRegistered) {
- mAsyncSensorManager.unregisterPluginListener(mSensor, this);
- mRegistered = false;
- }
- return;
- }
-
- if (isLockScreen && !mRegistered) {
- mAsyncSensorManager.registerPluginListener(mSensor, this);
- mRegistered = true;
- } else if (!isLockScreen && mRegistered) {
- mAsyncSensorManager.unregisterPluginListener(mSensor, this);
- mRegistered = false;
- }
- }
-
- @Override
- public void onDozingChanged(boolean isDozing) {
- mDozing = isDozing;
- }
-
- @Override
- public void onSensorChanged(SensorManagerPlugin.SensorEvent event) {
- mHandler.post(()-> {
- float[] rawValues = event.getValues();
- boolean wakeEvent = rawValues != null && rawValues.length > 0 && rawValues[0] != 0;
-
- DozeLog.traceLockScreenWakeUp(wakeEvent);
- if (wakeEvent && mDozing) {
- if (DEBUG) Log.d(TAG, "Wake up.");
- mPowerManager.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE");
- } else if (!wakeEvent && !mDozing) {
- if (DEBUG) Log.d(TAG, "Nap time.");
- mPowerManager.goToSleep(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
- } else if (DEBUG) {
- Log.d(TAG, "Skip sensor event. Wake? " + wakeEvent + " dozing: " + mDozing);
- }
- });
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index aba9bb8..e63f88a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -18,6 +18,8 @@
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
@@ -48,7 +50,6 @@
import com.android.settingslib.Utils;
import com.android.settingslib.drawable.UserIconDrawable;
import com.android.settingslib.graph.SignalDrawable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R.dimen;
import com.android.systemui.plugins.ActivityStarter;
@@ -63,11 +64,16 @@
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import com.android.systemui.tuner.TunerService;
+import javax.inject.Inject;
+import javax.inject.Named;
+
public class QSFooterImpl extends FrameLayout implements QSFooter,
OnClickListener, OnUserInfoChangedListener, EmergencyListener, SignalCallback {
- private ActivityStarter mActivityStarter;
- private UserInfoController mUserInfoController;
+ private final ActivityStarter mActivityStarter;
+ private final UserInfoController mUserInfoController;
+ private final NetworkController mNetworkController;
+ private final DeviceProvisionedController mDeviceProvisionedController;
private SettingsButton mSettingsButton;
protected View mSettingsContainer;
private PageIndicator mPageIndicator;
@@ -100,9 +106,17 @@
private final CellSignalState mInfo = new CellSignalState();
private OnClickListener mExpandClickListener;
- public QSFooterImpl(Context context, AttributeSet attrs) {
+ @Inject
+ public QSFooterImpl(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+ ActivityStarter activityStarter, UserInfoController userInfoController,
+ NetworkController networkController,
+ DeviceProvisionedController deviceProvisionedController) {
super(context, attrs);
mColorForeground = Utils.getColorAttrDefaultColor(context, android.R.attr.colorForeground);
+ mActivityStarter = activityStarter;
+ mUserInfoController = userInfoController;
+ mNetworkController = networkController;
+ mDeviceProvisionedController = deviceProvisionedController;
}
@Override
@@ -111,7 +125,7 @@
mDivider = findViewById(R.id.qs_footer_divider);
mEdit = findViewById(android.R.id.edit);
mEdit.setOnClickListener(view ->
- Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
+ mActivityStarter.postQSRunnableDismissingKeyguard(() ->
mQsPanel.showEdit(view)));
mPageIndicator = findViewById(R.id.footer_page_indicator);
@@ -137,8 +151,6 @@
updateResources();
- mUserInfoController = Dependency.get(UserInfoController.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> updateAnimator(right - left));
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
@@ -316,14 +328,14 @@
private void updateListeners() {
if (mListening) {
mUserInfoController.addCallback(this);
- if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
- Dependency.get(NetworkController.class).addEmergencyListener(this);
- Dependency.get(NetworkController.class).addCallback(this);
+ if (mNetworkController.hasVoiceCallingFeature()) {
+ mNetworkController.addEmergencyListener(this);
+ mNetworkController.addCallback(this);
}
} else {
mUserInfoController.removeCallback(this);
- Dependency.get(NetworkController.class).removeEmergencyListener(this);
- Dependency.get(NetworkController.class).removeCallback(this);
+ mNetworkController.removeEmergencyListener(this);
+ mNetworkController.removeCallback(this);
}
}
@@ -344,7 +356,7 @@
}
if (v == mSettingsButton) {
- if (!Dependency.get(DeviceProvisionedController.class).isCurrentUserSetup()) {
+ if (!mDeviceProvisionedController.isCurrentUserSetup()) {
// If user isn't setup just unlock the device and dump them back at SUW.
mActivityStarter.postQSRunnableDismissingKeyguard(() -> { });
return;
@@ -353,7 +365,7 @@
mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
: MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
if (mSettingsButton.isTunerClick()) {
- Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
+ mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
if (TunerService.isTunerEnabled(mContext)) {
TunerService.showResetRequest(mContext, () -> {
// Relaunch settings so that the tuner disappears.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index bedba9a..34d30fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -79,15 +79,18 @@
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
private final InjectionInflationController mInjectionInflater;
+ private final QSTileHost mHost;
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
InjectionInflationController injectionInflater,
- Context context) {
+ Context context,
+ QSTileHost qsTileHost) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mInjectionInflater = injectionInflater;
SysUiServiceProvider.getComponent(context, CommandQueue.class)
.observe(getLifecycle(), this);
+ mHost = qsTileHost;
}
@Override
@@ -122,6 +125,7 @@
mQSPanel.getTileLayout().restoreInstanceState(savedInstanceState);
}
}
+ setHost(mHost);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index ca8e824..3a6b785 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -30,6 +31,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -52,7 +54,12 @@
import java.util.List;
import java.util.function.Predicate;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/** Platform implementation of the quick settings tile host **/
+@Singleton
public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory> {
private static final String TAG = "QSTileHost";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -60,29 +67,44 @@
public static final String TILES_SETTING = Secure.QS_TILES;
private final Context mContext;
- private final StatusBar mStatusBar;
private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>();
protected final ArrayList<String> mTileSpecs = new ArrayList<>();
private final TileServices mServices;
+ private final TunerService mTunerService;
+ private final PluginManager mPluginManager;
private final List<Callback> mCallbacks = new ArrayList<>();
private final AutoTileManager mAutoTiles;
private final StatusBarIconController mIconController;
private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
private int mCurrentUser;
+ private StatusBar mStatusBar;
- public QSTileHost(Context context, StatusBar statusBar,
- StatusBarIconController iconController) {
+ @Inject
+ public QSTileHost(Context context,
+ StatusBarIconController iconController,
+ QSFactoryImpl defaultFactory,
+ @Named(Dependency.MAIN_HANDLER_NAME) Handler mainHandler,
+ @Named(Dependency.BG_LOOPER_NAME) Looper bgLooper,
+ PluginManager pluginManager,
+ TunerService tunerService) {
mIconController = iconController;
mContext = context;
- mStatusBar = statusBar;
+ mTunerService = tunerService;
+ mPluginManager = pluginManager;
- mServices = new TileServices(this, Dependency.get(Dependency.BG_LOOPER));
+ mServices = new TileServices(this, bgLooper);
- mQsFactories.add(new QSFactoryImpl(this));
- Dependency.get(PluginManager.class).addPluginListener(this, QSFactory.class, true);
+ defaultFactory.setHost(this);
+ mQsFactories.add(defaultFactory);
+ pluginManager.addPluginListener(this, QSFactory.class, true);
- Dependency.get(TunerService.class).addTunable(this, TILES_SETTING);
+ mainHandler.post(() -> {
+ // This is technically a hack to avoid circular dependency of
+ // QSTileHost -> XXXTile -> QSTileHost. Posting ensures creation
+ // finishes before creating any tiles.
+ tunerService.addTunable(this, TILES_SETTING);
+ });
// AutoTileManager can modify mTiles so make sure mTiles has already been initialized.
mAutoTiles = new AutoTileManager(context, this);
}
@@ -94,16 +116,16 @@
public void destroy() {
mTiles.values().forEach(tile -> tile.destroy());
mAutoTiles.destroy();
- Dependency.get(TunerService.class).removeTunable(this);
+ mTunerService.removeTunable(this);
mServices.destroy();
- Dependency.get(PluginManager.class).removePluginListener(this);
+ mPluginManager.removePluginListener(this);
}
@Override
public void onPluginConnected(QSFactory plugin, Context pluginContext) {
// Give plugins priority over creation so they can override if they wish.
mQsFactories.add(0, plugin);
- String value = Dependency.get(TunerService.class).getValue(TILES_SETTING);
+ String value = mTunerService.getValue(TILES_SETTING);
// Force remove and recreate of all tiles.
onTuningChanged(TILES_SETTING, "");
onTuningChanged(TILES_SETTING, value);
@@ -113,7 +135,7 @@
public void onPluginDisconnected(QSFactory plugin) {
mQsFactories.remove(plugin);
// Force remove and recreate of all tiles.
- String value = Dependency.get(TunerService.class).getValue(TILES_SETTING);
+ String value = mTunerService.getValue(TILES_SETTING);
onTuningChanged(TILES_SETTING, "");
onTuningChanged(TILES_SETTING, value);
}
@@ -140,16 +162,25 @@
@Override
public void collapsePanels() {
+ if (mStatusBar == null) {
+ mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+ }
mStatusBar.postAnimateCollapsePanels();
}
@Override
public void forceCollapsePanels() {
+ if (mStatusBar == null) {
+ mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+ }
mStatusBar.postAnimateForceCollapsePanels();
}
@Override
public void openPanels() {
+ if (mStatusBar == null) {
+ mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+ }
mStatusBar.postAnimateOpenPanels();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index fd2c4e3..d26cee9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -47,12 +47,79 @@
import com.android.systemui.qs.tiles.WorkModeTile;
import com.android.systemui.util.leak.GarbageMonitor;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+@Singleton
public class QSFactoryImpl implements QSFactory {
private static final String TAG = "QSFactory";
- private final QSTileHost mHost;
- public QSFactoryImpl(QSTileHost host) {
+ private final Provider<WifiTile> mWifiTileProvider;
+ private final Provider<BluetoothTile> mBluetoothTileProvider;
+ private final Provider<CellularTile> mCellularTileProvider;
+ private final Provider<DndTile> mDndTileProvider;
+ private final Provider<ColorInversionTile> mColorInversionTileProvider;
+ private final Provider<AirplaneModeTile> mAirplaneModeTileProvider;
+ private final Provider<WorkModeTile> mWorkModeTileProvider;
+ private final Provider<RotationLockTile> mRotationLockTileProvider;
+ private final Provider<FlashlightTile> mFlashlightTileProvider;
+ private final Provider<LocationTile> mLocationTileProvider;
+ private final Provider<CastTile> mCastTileProvider;
+ private final Provider<HotspotTile> mHotspotTileProvider;
+ private final Provider<UserTile> mUserTileProvider;
+ private final Provider<BatterySaverTile> mBatterySaverTileProvider;
+ private final Provider<DataSaverTile> mDataSaverTileProvider;
+ private final Provider<NightDisplayTile> mNightDisplayTileProvider;
+ private final Provider<NfcTile> mNfcTileProvider;
+ private final Provider<SensorPrivacyTile> mSensorPrivacyTileProvider;
+ private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider;
+
+ private QSTileHost mHost;
+
+ @Inject
+ public QSFactoryImpl(Provider<WifiTile> wifiTileProvider,
+ Provider<BluetoothTile> bluetoothTileProvider,
+ Provider<CellularTile> cellularTileProvider,
+ Provider<DndTile> dndTileProvider,
+ Provider<ColorInversionTile> colorInversionTileProvider,
+ Provider<AirplaneModeTile> airplaneModeTileProvider,
+ Provider<WorkModeTile> workModeTileProvider,
+ Provider<RotationLockTile> rotationLockTileProvider,
+ Provider<FlashlightTile> flashlightTileProvider,
+ Provider<LocationTile> locationTileProvider,
+ Provider<CastTile> castTileProvider,
+ Provider<HotspotTile> hotspotTileProvider,
+ Provider<UserTile> userTileProvider,
+ Provider<BatterySaverTile> batterySaverTileProvider,
+ Provider<DataSaverTile> dataSaverTileProvider,
+ Provider<NightDisplayTile> nightDisplayTileProvider,
+ Provider<NfcTile> nfcTileProvider,
+ Provider<SensorPrivacyTile> sensorPrivacyTileProvider,
+ Provider<GarbageMonitor.MemoryTile> memoryTileProvider) {
+ mWifiTileProvider = wifiTileProvider;
+ mBluetoothTileProvider = bluetoothTileProvider;
+ mCellularTileProvider = cellularTileProvider;
+ mDndTileProvider = dndTileProvider;
+ mColorInversionTileProvider = colorInversionTileProvider;
+ mAirplaneModeTileProvider = airplaneModeTileProvider;
+ mWorkModeTileProvider = workModeTileProvider;
+ mRotationLockTileProvider = rotationLockTileProvider;
+ mFlashlightTileProvider = flashlightTileProvider;
+ mLocationTileProvider = locationTileProvider;
+ mCastTileProvider = castTileProvider;
+ mHotspotTileProvider = hotspotTileProvider;
+ mUserTileProvider = userTileProvider;
+ mBatterySaverTileProvider = batterySaverTileProvider;
+ mDataSaverTileProvider = dataSaverTileProvider;
+ mNightDisplayTileProvider = nightDisplayTileProvider;
+ mNfcTileProvider = nfcTileProvider;
+ mSensorPrivacyTileProvider = sensorPrivacyTileProvider;
+ mMemoryTileProvider = memoryTileProvider;
+ }
+
+ public void setHost(QSTileHost host) {
mHost = host;
}
@@ -68,41 +135,41 @@
// Stock tiles.
switch (tileSpec) {
case "wifi":
- return new WifiTile(mHost);
+ return mWifiTileProvider.get();
case "bt":
- return new BluetoothTile(mHost);
+ return mBluetoothTileProvider.get();
case "cell":
- return new CellularTile(mHost);
+ return mCellularTileProvider.get();
case "dnd":
- return new DndTile(mHost);
+ return mDndTileProvider.get();
case "inversion":
- return new ColorInversionTile(mHost);
+ return mColorInversionTileProvider.get();
case "airplane":
- return new AirplaneModeTile(mHost);
+ return mAirplaneModeTileProvider.get();
case "work":
- return new WorkModeTile(mHost);
+ return mWorkModeTileProvider.get();
case "rotation":
- return new RotationLockTile(mHost);
+ return mRotationLockTileProvider.get();
case "flashlight":
- return new FlashlightTile(mHost);
+ return mFlashlightTileProvider.get();
case "location":
- return new LocationTile(mHost);
+ return mLocationTileProvider.get();
case "cast":
- return new CastTile(mHost);
+ return mCastTileProvider.get();
case "hotspot":
- return new HotspotTile(mHost);
+ return mHotspotTileProvider.get();
case "user":
- return new UserTile(mHost);
+ return mUserTileProvider.get();
case "battery":
- return new BatterySaverTile(mHost);
+ return mBatterySaverTileProvider.get();
case "saver":
- return new DataSaverTile(mHost);
+ return mDataSaverTileProvider.get();
case "night":
- return new NightDisplayTile(mHost);
+ return mNightDisplayTileProvider.get();
case "nfc":
- return new NfcTile(mHost);
+ return mNfcTileProvider.get();
case "sensorprivacy":
- return new SensorPrivacyTile(mHost);
+ return mSensorPrivacyTileProvider.get();
}
// Intent tiles.
@@ -112,7 +179,7 @@
// Debug tiles.
if (Build.IS_DEBUGGABLE) {
if (tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC)) {
- return new GarbageMonitor.MemoryTile(mHost);
+ return mMemoryTileProvider.get();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index cc27135..e1a4378 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -14,6 +14,9 @@
package com.android.systemui.qs.tileimpl;
+import static androidx.lifecycle.Lifecycle.State.DESTROYED;
+import static androidx.lifecycle.Lifecycle.State.RESUMED;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_CLICK;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_LONG_PRESS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_SECONDARY_CLICK;
@@ -38,6 +41,11 @@
import android.util.Log;
import android.util.SparseArray;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.settingslib.RestrictedLockUtils;
@@ -66,7 +74,7 @@
*
* @param <TState> see above
*/
-public abstract class QSTileImpl<TState extends State> implements QSTile {
+public abstract class QSTileImpl<TState extends State> implements QSTile, LifecycleOwner {
protected final String TAG = "Tile." + getClass().getSimpleName();
protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG);
@@ -94,6 +102,8 @@
private boolean mShowingDetail;
private int mIsFullQs;
+ private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
+
public abstract TState newTileState();
abstract protected void handleClick();
@@ -113,6 +123,12 @@
mContext = host.getContext();
}
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycle;
+ }
+
/**
* Adds or removes a listening client for the tile. If the tile has one or more
* listening client it will go into the listening state.
@@ -341,12 +357,14 @@
if (listening) {
if (mListeners.add(listener) && mListeners.size() == 1) {
if (DEBUG) Log.d(TAG, "handleSetListening true");
+ mLifecycle.markState(RESUMED);
handleSetListening(listening);
refreshState(); // Ensure we get at least one refresh after listening.
}
} else {
if (mListeners.remove(listener) && mListeners.size() == 0) {
if (DEBUG) Log.d(TAG, "handleSetListening false");
+ mLifecycle.markState(DESTROYED);
handleSetListening(listening);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index c8c2158..387de71 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -32,7 +32,6 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -40,16 +39,21 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import javax.inject.Inject;
+
/** Quick settings tile: Airplane mode **/
public class AirplaneModeTile extends QSTileImpl<BooleanState> {
private final Icon mIcon =
ResourceIcon.get(R.drawable.ic_signal_airplane);
private final GlobalSetting mSetting;
+ private final ActivityStarter mActivityStarter;
private boolean mListening;
- public AirplaneModeTile(QSHost host) {
+ @Inject
+ public AirplaneModeTile(QSHost host, ActivityStarter activityStarter) {
super(host);
+ mActivityStarter = activityStarter;
mSetting = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
@Override
@@ -70,7 +74,7 @@
MetricsLogger.action(mContext, getMetricsCategory(), !airplaneModeEnabled);
if (!airplaneModeEnabled && Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
- Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(
+ mActivityStarter.postStartActivityDismissingKeyguard(
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS), 0);
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index da2828e..7f76900b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -23,13 +23,14 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
+import javax.inject.Inject;
+
public class BatterySaverTile extends QSTileImpl<BooleanState> implements
BatteryController.BatteryStateChangeCallback {
@@ -40,9 +41,11 @@
private boolean mCharging;
private boolean mPluggedIn;
- public BatterySaverTile(QSHost host) {
+ @Inject
+ public BatterySaverTile(QSHost host, BatteryController batteryController) {
super(host);
- mBatteryController = Dependency.get(BatteryController.class);
+ mBatteryController = batteryController;
+ mBatteryController.observe(getLifecycle(), this);
}
@Override
@@ -57,11 +60,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mBatteryController.addCallback(this);
- } else {
- mBatteryController.removeCallback(this);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 3ab1c21..5b85498 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -36,7 +36,6 @@
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -51,6 +50,8 @@
import java.util.Collection;
import java.util.List;
+import javax.inject.Inject;
+
/** Quick settings tile: Bluetooth **/
public class BluetoothTile extends QSTileImpl<BooleanState> {
private static final Intent BLUETOOTH_SETTINGS = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
@@ -59,11 +60,15 @@
private final BluetoothDetailAdapter mDetailAdapter;
private final ActivityStarter mActivityStarter;
- public BluetoothTile(QSHost host) {
+ @Inject
+ public BluetoothTile(QSHost host,
+ BluetoothController bluetoothController,
+ ActivityStarter activityStarter) {
super(host);
- mController = Dependency.get(BluetoothController.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
+ mController = bluetoothController;
+ mActivityStarter = activityStarter;
mDetailAdapter = (BluetoothDetailAdapter) createDetailAdapter();
+ mController.observe(getLifecycle(), mCallback);
}
@Override
@@ -78,11 +83,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mController.addCallback(mCallback);
- } else {
- mController.removeCallback(mCallback);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 921db69..f05ac4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -33,7 +33,6 @@
import com.android.internal.app.MediaRouteDialogPresenter;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -51,6 +50,8 @@
import java.util.LinkedHashMap;
import java.util.Set;
+import javax.inject.Inject;
+
/** Quick settings tile: Cast **/
public class CastTile extends QSTileImpl<BooleanState> {
private static final Intent CAST_SETTINGS =
@@ -65,13 +66,18 @@
private Dialog mDialog;
private boolean mWifiConnected;
- public CastTile(QSHost host) {
+ @Inject
+ public CastTile(QSHost host, CastController castController, KeyguardMonitor keyguardMonitor,
+ NetworkController networkController, ActivityStarter activityStarter) {
super(host);
- mController = Dependency.get(CastController.class);
+ mController = castController;
mDetailAdapter = new CastDetailAdapter();
- mKeyguard = Dependency.get(KeyguardMonitor.class);
- mNetworkController = Dependency.get(NetworkController.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
+ mKeyguard = keyguardMonitor;
+ mNetworkController = networkController;
+ mActivityStarter = activityStarter;
+ mController.observe(this, mCallback);
+ mKeyguard.observe(this, mCallback);
+ mNetworkController.observe(this, mSignalCallback);
}
@Override
@@ -87,15 +93,8 @@
@Override
public void handleSetListening(boolean listening) {
if (DEBUG) Log.d(TAG, "handleSetListening " + listening);
- if (listening) {
- mController.addCallback(mCallback);
- mKeyguard.addCallback(mCallback);
- mNetworkController.addCallback(mSignalCallback);
- } else {
+ if (!listening) {
mController.setDiscovering(false);
- mController.removeCallback(mCallback);
- mKeyguard.removeCallback(mCallback);
- mNetworkController.removeCallback(mSignalCallback);
}
}
@@ -135,7 +134,7 @@
mDialog = MediaRouteDialogPresenter.createDialog(mContext, ROUTE_TYPE_REMOTE_DISPLAY,
v -> {
mDialog.dismiss();
- Dependency.get(ActivityStarter.class)
+ mActivityStarter
.postStartActivityDismissingKeyguard(getLongClickIntent(), 0);
});
mDialog.getWindow().setType(LayoutParams.TYPE_KEYGUARD_DIALOG);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 9e341e2..1155a41 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -35,7 +35,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
@@ -51,6 +50,8 @@
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import javax.inject.Inject;
+
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTileImpl<SignalState> {
private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
@@ -63,13 +64,16 @@
private final ActivityStarter mActivityStarter;
private final KeyguardMonitor mKeyguardMonitor;
- public CellularTile(QSHost host) {
+ @Inject
+ public CellularTile(QSHost host, NetworkController networkController,
+ ActivityStarter activityStarter, KeyguardMonitor keyguardMonitor) {
super(host);
- mController = Dependency.get(NetworkController.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mController = networkController;
+ mActivityStarter = activityStarter;
+ mKeyguardMonitor = keyguardMonitor;
mDataController = mController.getMobileDataController();
mDetailAdapter = new CellularDetailAdapter();
+ mController.observe(getLifecycle(), mSignalCallback);
}
@Override
@@ -84,11 +88,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mController.addCallback(mSignalCallback);
- } else {
- mController.removeCallback(mSignalCallback);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index c13a07f..ecb4048 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -30,6 +30,8 @@
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import javax.inject.Inject;
+
/** Quick settings tile: Invert colors **/
public class ColorInversionTile extends QSTileImpl<BooleanState> {
@@ -38,6 +40,7 @@
private boolean mListening;
+ @Inject
public ColorInversionTile(QSHost host) {
super(host);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index fd8b9c9..c6c6f87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -20,7 +20,6 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -30,14 +29,18 @@
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.NetworkController;
+import javax.inject.Inject;
+
public class DataSaverTile extends QSTileImpl<BooleanState> implements
DataSaverController.Listener{
private final DataSaverController mDataSaverController;
- public DataSaverTile(QSHost host) {
+ @Inject
+ public DataSaverTile(QSHost host, NetworkController networkController) {
super(host);
- mDataSaverController = Dependency.get(NetworkController.class).getDataSaverController();
+ mDataSaverController = networkController.getDataSaverController();
+ mDataSaverController.observe(getLifecycle(), this);
}
@Override
@@ -47,11 +50,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mDataSaverController.addCallback(this);
- } else {
- mDataSaverController.removeCallback(this);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 50c8698..5f04e56 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -49,7 +49,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.notification.EnableZenModeDialog;
-import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
@@ -62,6 +61,8 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
+import javax.inject.Inject;
+
/** Quick settings tile: Do not disturb **/
public class DndTile extends QSTileImpl<BooleanState> {
@@ -76,17 +77,22 @@
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
+ private final ActivityStarter mActivityStarter;
private boolean mListening;
private boolean mShowingDetail;
private boolean mReceiverRegistered;
- public DndTile(QSHost host) {
+ @Inject
+ public DndTile(QSHost host, ZenModeController zenModeController,
+ ActivityStarter activityStarter) {
super(host);
- mController = Dependency.get(ZenModeController.class);
+ mController = zenModeController;
+ mActivityStarter = activityStarter;
mDetailAdapter = new DndDetailAdapter();
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
mReceiverRegistered = true;
+ mController.observe(getLifecycle(), mZenCallback);
}
@Override
@@ -157,7 +163,7 @@
// show on-boarding screen
Intent intent = new Intent(Settings.ZEN_MODE_ONBOARDING);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(intent, 0);
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
} else {
switch (zenDuration) {
case Settings.Secure.ZEN_DURATION_PROMPT:
@@ -281,10 +287,8 @@
if (mListening == listening) return;
mListening = listening;
if (mListening) {
- mController.addCallback(mZenCallback);
Prefs.registerListener(mContext, mPrefListener);
} else {
- mController.removeCallback(mZenCallback);
Prefs.unregisterListener(mContext, mPrefListener);
}
}
@@ -445,7 +449,7 @@
private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
@Override
public void onPrioritySettings() {
- Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(
+ mActivityStarter.postStartActivityDismissingKeyguard(
ZEN_PRIORITY_SETTINGS, 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index d7ac253..dfa3fb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -23,13 +23,14 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.FlashlightController;
+import javax.inject.Inject;
+
/** Quick settings tile: Control flashlight **/
public class FlashlightTile extends QSTileImpl<BooleanState> implements
FlashlightController.FlashlightListener {
@@ -37,9 +38,11 @@
private final Icon mIcon = ResourceIcon.get(R.drawable.ic_signal_flashlight);
private final FlashlightController mFlashlightController;
- public FlashlightTile(QSHost host) {
+ @Inject
+ public FlashlightTile(QSHost host, FlashlightController flashlightController) {
super(host);
- mFlashlightController = Dependency.get(FlashlightController.class);
+ mFlashlightController = flashlightController;
+ mFlashlightController.observe(getLifecycle(), this);
}
@Override
@@ -56,11 +59,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mFlashlightController.addCallback(this);
- } else {
- mFlashlightController.removeCallback(this);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 6bf0793..b7e07f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -25,7 +25,6 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.AirplaneBooleanState;
import com.android.systemui.qs.GlobalSetting;
@@ -34,6 +33,8 @@
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import javax.inject.Inject;
+
/** Quick settings tile: Hotspot **/
public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
private static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
@@ -48,16 +49,20 @@
private final GlobalSetting mAirplaneMode;
private boolean mListening;
- public HotspotTile(QSHost host) {
+ @Inject
+ public HotspotTile(QSHost host, HotspotController hotspotController,
+ DataSaverController dataSaverController) {
super(host);
- mHotspotController = Dependency.get(HotspotController.class);
- mDataSaverController = Dependency.get(DataSaverController.class);
+ mHotspotController = hotspotController;
+ mDataSaverController = dataSaverController;
mAirplaneMode = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
@Override
protected void handleValueChanged(int value) {
refreshState();
}
};
+ mHotspotController.observe(this, mCallbacks);
+ mDataSaverController.observe(this, mCallbacks);
}
@Override
@@ -80,12 +85,7 @@
if (mListening == listening) return;
mListening = listening;
if (listening) {
- mHotspotController.addCallback(mCallbacks);
- mDataSaverController.addCallback(mCallbacks);
refreshState();
- } else {
- mHotspotController.removeCallback(mCallbacks);
- mDataSaverController.removeCallback(mCallbacks);
}
mAirplaneMode.setListening(listening);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index b5f2d00..d740033 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -23,7 +23,6 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R.drawable;
import com.android.systemui.plugins.ActivityStarter;
@@ -34,6 +33,8 @@
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
+import javax.inject.Inject;
+
/** Quick settings tile: Location **/
public class LocationTile extends QSTileImpl<BooleanState> {
@@ -41,12 +42,18 @@
private final LocationController mController;
private final KeyguardMonitor mKeyguard;
+ private final ActivityStarter mActivityStarter;
private final Callback mCallback = new Callback();
- public LocationTile(QSHost host) {
+ @Inject
+ public LocationTile(QSHost host, LocationController locationController,
+ KeyguardMonitor keyguardMonitor, ActivityStarter activityStarter) {
super(host);
- mController = Dependency.get(LocationController.class);
- mKeyguard = Dependency.get(KeyguardMonitor.class);
+ mController = locationController;
+ mKeyguard = keyguardMonitor;
+ mActivityStarter = activityStarter;
+ mController.observe(this, mCallback);
+ mKeyguard.observe(this, mCallback);
}
@Override
@@ -56,13 +63,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mController.addCallback(mCallback);
- mKeyguard.addCallback(mCallback);
- } else {
- mController.removeCallback(mCallback);
- mKeyguard.removeCallback(mCallback);
- }
}
@Override
@@ -73,7 +73,7 @@
@Override
protected void handleClick() {
if (mKeyguard.isSecure() && mKeyguard.isShowing()) {
- Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
+ mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
final boolean wasEnabled = mState.value;
mHost.openPanels();
mController.setLocationEnabled(!wasEnabled);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index a365e4c..476a239 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -33,6 +33,8 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import javax.inject.Inject;
+
/** Quick settings tile: Enable/Disable NFC **/
public class NfcTile extends QSTileImpl<BooleanState> {
@@ -40,6 +42,7 @@
private boolean mListening;
+ @Inject
public NfcTile(QSHost host) {
super(host);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 90890c0..b04132d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -44,6 +44,8 @@
import java.util.Calendar;
import java.util.TimeZone;
+import javax.inject.Inject;
+
public class NightDisplayTile extends QSTileImpl<BooleanState>
implements ColorDisplayController.Callback {
@@ -58,6 +60,7 @@
private ColorDisplayController mController;
private boolean mIsListening;
+ @Inject
public NightDisplayTile(QSHost host) {
super(host);
mController = new ColorDisplayController(mContext, ActivityManager.getCurrentUser());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 63458163..21f3d6e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -24,7 +24,6 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
@@ -32,15 +31,19 @@
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
+import javax.inject.Inject;
+
/** Quick settings tile: Rotation **/
public class RotationLockTile extends QSTileImpl<BooleanState> {
private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_auto_rotate);
private final RotationLockController mController;
- public RotationLockTile(QSHost host) {
+ @Inject
+ public RotationLockTile(QSHost host, RotationLockController rotationLockController) {
super(host);
- mController = Dependency.get(RotationLockController.class);
+ mController = rotationLockController;
+ mController.observe(this, mCallback);
}
@Override
@@ -49,11 +52,6 @@
}
public void handleSetListening(boolean listening) {
- if (listening) {
- mController.addCallback(mCallback);
- } else {
- mController.removeCallback(mCallback);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
index ff368f8..5230cea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
@@ -23,7 +23,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -31,6 +30,8 @@
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import javax.inject.Inject;
+
/** Quick settings tile: SensorPrivacy mode **/
public class SensorPrivacyTile extends QSTileImpl<BooleanState> implements
SensorPrivacyManager.OnSensorPrivacyChangedListener {
@@ -39,12 +40,16 @@
ResourceIcon.get(R.drawable.ic_signal_sensors);
private final KeyguardMonitor mKeyguard;
private final SensorPrivacyManager mSensorPrivacyManager;
+ private final ActivityStarter mActivityStarter;
- public SensorPrivacyTile(QSHost host) {
+ @Inject
+ public SensorPrivacyTile(QSHost host, SensorPrivacyManager sensorPrivacyManager,
+ KeyguardMonitor keyguardMonitor, ActivityStarter activityStarter) {
super(host);
- mSensorPrivacyManager = Dependency.get(SensorPrivacyManager.class);
- mKeyguard = Dependency.get(KeyguardMonitor.class);
+ mSensorPrivacyManager = sensorPrivacyManager;
+ mKeyguard = keyguardMonitor;
+ mActivityStarter = activityStarter;
}
@Override
@@ -57,7 +62,7 @@
final boolean wasEnabled = mState.value;
// Don't allow disabling from the lockscreen.
if (wasEnabled && mKeyguard.isSecure() && mKeyguard.isShowing()) {
- Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
+ mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled);
setEnabled(!wasEnabled);
});
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index e5c51a6..7c1ffde 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -22,7 +22,6 @@
import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
@@ -31,16 +30,21 @@
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import javax.inject.Inject;
+
public class UserTile extends QSTileImpl<State> implements UserInfoController.OnUserInfoChangedListener {
private final UserSwitcherController mUserSwitcherController;
private final UserInfoController mUserInfoController;
private Pair<String, Drawable> mLastUpdate;
- public UserTile(QSHost host) {
+ @Inject
+ public UserTile(QSHost host, UserSwitcherController userSwitcherController,
+ UserInfoController userInfoController) {
super(host);
- mUserSwitcherController = Dependency.get(UserSwitcherController.class);
- mUserInfoController = Dependency.get(UserInfoController.class);
+ mUserSwitcherController = userSwitcherController;
+ mUserInfoController = userInfoController;
+ mUserInfoController.observe(getLifecycle(), this);
}
@Override
@@ -70,11 +74,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mUserInfoController.addCallback(this);
- } else {
- mUserInfoController.removeCallback(this);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 6939ae7..52a8814 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -30,7 +30,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.wifi.AccessPoint;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -51,6 +50,8 @@
import java.util.List;
+import javax.inject.Inject;
+
/** Quick settings tile: Wifi **/
public class WifiTile extends QSTileImpl<SignalState> {
private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
@@ -64,12 +65,15 @@
private final ActivityStarter mActivityStarter;
private boolean mExpectDisabled;
- public WifiTile(QSHost host) {
+ @Inject
+ public WifiTile(QSHost host, NetworkController networkController,
+ ActivityStarter activityStarter) {
super(host);
- mController = Dependency.get(NetworkController.class);
+ mController = networkController;
mWifiController = mController.getAccessPointController();
mDetailAdapter = (WifiDetailAdapter) createDetailAdapter();
- mActivityStarter = Dependency.get(ActivityStarter.class);
+ mActivityStarter = activityStarter;
+ mController.observe(getLifecycle(), mSignalCallback);
}
@Override
@@ -79,11 +83,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mController.addCallback(mSignalCallback);
- } else {
- mController.removeCallback(mSignalCallback);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 3109dea..f921eb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -22,13 +22,14 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.ManagedProfileController;
+import javax.inject.Inject;
+
/** Quick settings tile: Work profile on/off */
public class WorkModeTile extends QSTileImpl<BooleanState> implements
ManagedProfileController.Callback {
@@ -36,9 +37,11 @@
private final ManagedProfileController mProfileController;
- public WorkModeTile(QSHost host) {
+ @Inject
+ public WorkModeTile(QSHost host, ManagedProfileController managedProfileController) {
super(host);
- mProfileController = Dependency.get(ManagedProfileController.class);
+ mProfileController = managedProfileController;
+ mProfileController.observe(getLifecycle(), this);
}
@Override
@@ -48,11 +51,6 @@
@Override
public void handleSetListening(boolean listening) {
- if (listening) {
- mProfileController.addCallback(this);
- } else {
- mProfileController.removeCallback(this);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 538e0f0..81757d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -44,7 +44,6 @@
import android.view.MotionEvent;
import com.android.internal.policy.ScreenDecorationsUtils;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.Prefs;
import com.android.systemui.SysUiServiceProvider;
@@ -90,8 +89,7 @@
private final Handler mHandler;
private final Runnable mConnectionRunnable = this::internalConnectToCurrentUser;
private final ComponentName mRecentsComponentName;
- private final DeviceProvisionedController mDeviceProvisionedController
- = Dependency.get(DeviceProvisionedController.class);
+ private final DeviceProvisionedController mDeviceProvisionedController;
private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>();
private final Intent mQuickStepIntent;
@@ -343,9 +341,10 @@
= this::cleanupAfterDeath;
@Inject
- public OverviewProxyService(Context context) {
+ public OverviewProxyService(Context context, DeviceProvisionedController provisionController) {
mContext = context;
mHandler = new Handler();
+ mDeviceProvisionedController = provisionController;
mConnectionBackoffAttempts = 0;
mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 1a93b0f..e4c6981 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -37,6 +37,7 @@
import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@@ -45,8 +46,8 @@
import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
@@ -64,6 +65,8 @@
import javax.inject.Inject;
import javax.inject.Singleton;
+import dagger.Lazy;
+
/**
* Handles tasks and state related to media notifications. For example, there is a 'current' media
* notification, which this class keeps track of.
@@ -83,9 +86,9 @@
// Late binding, also @Nullable due to being in com.android.systemui.statusbar.phone package
@Nullable
- private ShadeController mShadeController;
+ private Lazy<ShadeController> mShadeController;
@Nullable
- private StatusBarWindowController mStatusBarWindowController;
+ private Lazy<StatusBarWindowController> mStatusBarWindowController;
@Nullable
private BiometricUnlockController mBiometricUnlockController;
@@ -135,37 +138,34 @@
}
};
- @Nullable
- private ShadeController getShadeController() {
- if (mShadeController == null) {
- mShadeController = Dependency.get(ShadeController.class);
- }
- return mShadeController;
- }
-
- @Nullable
- private StatusBarWindowController getWindowController() {
- if (mStatusBarWindowController == null) {
- mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
- }
- return mStatusBarWindowController;
- }
-
- private NotificationEntryManager getEntryManager() {
- if (mEntryManager == null) {
- mEntryManager = Dependency.get(NotificationEntryManager.class);
- }
- return mEntryManager;
- }
-
@Inject
- public NotificationMediaManager(Context context) {
+ public NotificationMediaManager(
+ Context context,
+ Lazy<ShadeController> shadeController,
+ Lazy<StatusBarWindowController> statusBarWindowController,
+ NotificationEntryManager notificationEntryManager) {
mContext = context;
mMediaListeners = new ArrayList<>();
mMediaSessionManager
= (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
// TODO: use MediaSessionManager.SessionListener to hook us up to future updates
// in session state
+ mShadeController = shadeController;
+ mStatusBarWindowController = statusBarWindowController;
+ mEntryManager = notificationEntryManager;
+ notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+ @Override
+ public void onEntryRemoved(
+ Entry entry,
+ String key,
+ StatusBarNotification old,
+ boolean lifetimeExtended,
+ boolean removedByUser) {
+ if (!lifetimeExtended) {
+ onNotificationRemoved(key);
+ }
+ }
+ });
}
public void setUpWithPresenter(NotificationPresenter presenter) {
@@ -191,9 +191,8 @@
if (mMediaNotificationKey == null) {
return null;
}
- NotificationEntryManager manager = getEntryManager();
- synchronized (manager.getNotificationData()) {
- Entry entry = manager.getNotificationData().get(mMediaNotificationKey);
+ synchronized (mEntryManager.getNotificationData()) {
+ Entry entry = mEntryManager.getNotificationData().get(mMediaNotificationKey);
if (entry == null || entry.expandedIcon == null) {
return null;
}
@@ -214,10 +213,9 @@
public void findAndUpdateMediaNotifications() {
boolean metaDataChanged = false;
- NotificationEntryManager manager = getEntryManager();
- synchronized (manager.getNotificationData()) {
- ArrayList<Entry> activeNotifications = manager
- .getNotificationData().getActiveNotifications();
+ synchronized (mEntryManager.getNotificationData()) {
+ ArrayList<Entry> activeNotifications =
+ mEntryManager.getNotificationData().getActiveNotifications();
final int N = activeNotifications.size();
// Promote the media notification with a controller in 'playing' state, if any.
@@ -305,7 +303,7 @@
}
if (metaDataChanged) {
- getEntryManager().updateNotifications();
+ mEntryManager.updateNotifications();
}
dispatchUpdateMediaMetaData(metaDataChanged, true /* allowEnterAnimation */);
@@ -440,8 +438,9 @@
}
}
- boolean hideBecauseOccluded = getShadeController() != null
- && getShadeController().isOccluded();
+ ShadeController shadeController = mShadeController.get();
+ StatusBarWindowController windowController = mStatusBarWindowController.get();
+ boolean hideBecauseOccluded = shadeController != null && shadeController.isOccluded();
final boolean hasArtwork = artworkDrawable != null;
mColorExtractor.setHasBackdrop(hasArtwork);
@@ -464,8 +463,8 @@
mBackdrop.animate().cancel();
mBackdrop.setAlpha(1f);
}
- if (getWindowController() != null) {
- getWindowController().setBackdropShowing(true);
+ if (windowController != null) {
+ windowController.setBackdropShowing(true);
}
metaDataChanged = true;
if (DEBUG_MEDIA) {
@@ -512,8 +511,8 @@
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
}
- boolean cannotAnimateDoze = getShadeController() != null
- && getShadeController().isDozing()
+ boolean cannotAnimateDoze = shadeController != null
+ && shadeController.isDozing()
&& !ScrimState.AOD.getAnimateChange();
if (mBiometricUnlockController != null && mBiometricUnlockController.getMode()
== BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
@@ -522,12 +521,12 @@
// We are unlocking directly - no animation!
mBackdrop.setVisibility(View.GONE);
mBackdropBack.setImageDrawable(null);
- if (getWindowController() != null) {
- getWindowController().setBackdropShowing(false);
+ if (windowController != null) {
+ windowController.setBackdropShowing(false);
}
} else {
- if (getWindowController() != null) {
- getWindowController().setBackdropShowing(false);
+ if (windowController != null) {
+ windowController.setBackdropShowing(false);
}
mBackdrop.animate()
.alpha(0)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index d1556fb..2e9f6d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -17,6 +17,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -26,6 +28,7 @@
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -46,9 +49,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -60,8 +63,11 @@
import java.util.Set;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
+import dagger.Lazy;
+
/**
* Class for handling remote input state over a set of notifications. This class handles things
* like keeping notifications temporarily that were cancelled as a response to a remote input
@@ -100,15 +106,12 @@
new ArraySet<>();
// Dependencies:
- protected final NotificationLockscreenUserManager mLockscreenUserManager =
- Dependency.get(NotificationLockscreenUserManager.class);
- protected final SmartReplyController mSmartReplyController =
- Dependency.get(SmartReplyController.class);
- private final NotificationEntryManager mEntryManager
- = Dependency.get(NotificationEntryManager.class);
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final SmartReplyController mSmartReplyController;
+ private final NotificationEntryManager mEntryManager;
+ private final Handler mMainHandler;
- // Lazy
- private ShadeController mShadeController;
+ private final Lazy<ShadeController> mShadeController;
protected final Context mContext;
private final UserManager mUserManager;
@@ -126,7 +129,7 @@
@Override
public boolean onClickHandler(
View view, PendingIntent pendingIntent, RemoteViews.RemoteResponse response) {
- getShadeController().wakeUpIfDozing(SystemClock.uptimeMillis(), view);
+ mShadeController.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view);
if (handleRemoteInput(view, pendingIntent)) {
return true;
@@ -226,21 +229,39 @@
}
};
- private ShadeController getShadeController() {
- if (mShadeController == null) {
- mShadeController = Dependency.get(ShadeController.class);
- }
- return mShadeController;
- }
-
@Inject
- public NotificationRemoteInputManager(Context context) {
+ public NotificationRemoteInputManager(
+ Context context,
+ NotificationLockscreenUserManager lockscreenUserManager,
+ SmartReplyController smartReplyController,
+ NotificationEntryManager notificationEntryManager,
+ Lazy<ShadeController> shadeController,
+ @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
mContext = context;
+ mLockscreenUserManager = lockscreenUserManager;
+ mSmartReplyController = smartReplyController;
+ mEntryManager = notificationEntryManager;
+ mShadeController = shadeController;
+ mMainHandler = mainHandler;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
addLifetimeExtenders();
mKeyguardManager = context.getSystemService(KeyguardManager.class);
+
+ notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+ @Override
+ public void onEntryRemoved(
+ NotificationData.Entry entry,
+ String key,
+ StatusBarNotification old,
+ boolean lifetimeExtended,
+ boolean removedByUser) {
+ if (removedByUser) {
+ onPerformRemoveNotification(entry, key);
+ }
+ }
+ });
}
/** Initializes this component with the provided dependencies. */
@@ -258,7 +279,7 @@
// view it is already canceled, so we'll need to cancel it on the apps behalf
// after sending - unless the app posts an update in the mean time, so wait a
// bit.
- Dependency.get(Dependency.MAIN_HANDLER).postDelayed(() -> {
+ mMainHandler.postDelayed(() -> {
if (mEntriesKeptForRemoteInputActive.remove(entry)) {
mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
}
@@ -392,10 +413,10 @@
return mRemoteInputController;
}
- public void onPerformRemoveNotification(StatusBarNotification n,
- NotificationData.Entry entry) {
- if (mKeysKeptForRemoteInputHistory.contains(n.getKey())) {
- mKeysKeptForRemoteInputHistory.remove(n.getKey());
+ @VisibleForTesting
+ void onPerformRemoveNotification(NotificationData.Entry entry, final String key) {
+ if (mKeysKeptForRemoteInputHistory.contains(key)) {
+ mKeysKeptForRemoteInputHistory.remove(key);
}
if (mRemoteInputController.isRemoteInputActive(entry)) {
mRemoteInputController.removeRemoteInput(entry, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 6f1548d..9e91133 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -21,7 +21,6 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -36,15 +35,16 @@
*/
@Singleton
public class SmartReplyController {
- private IStatusBarService mBarService;
+ private final IStatusBarService mBarService;
+ private final NotificationEntryManager mEntryManager;
private Set<String> mSendingKeys = new ArraySet<>();
private Callback mCallback;
- private final NotificationEntryManager mEntryManager =
- Dependency.get(NotificationEntryManager.class);
@Inject
- public SmartReplyController() {
- mBarService = Dependency.get(IStatusBarService.class);
+ public SmartReplyController(NotificationEntryManager entryManager,
+ IStatusBarService statusBarService) {
+ mBarService = statusBarService;
+ mEntryManager = entryManager;
}
public void setCallback(Callback callback) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
new file mode 100644
index 0000000..099b503
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -0,0 +1,186 @@
+/*
+ * 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.statusbar.notification;
+
+import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import com.android.systemui.statusbar.AlertingNotificationManager;
+import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.notification.row.NotificationInflater;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/** Handles heads-up and pulsing behavior driven by notification changes. */
+@Singleton
+public class NotificationAlertingManager {
+
+ private static final String TAG = "NotifAlertManager";
+
+ private final AmbientPulseManager mAmbientPulseManager;
+ private final NotificationRemoteInputManager mRemoteInputManager;
+ private final VisualStabilityManager mVisualStabilityManager;
+ private final Lazy<ShadeController> mShadeController;
+ private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final NotificationListener mNotificationListener;
+
+ private HeadsUpManager mHeadsUpManager;
+
+ @Inject
+ public NotificationAlertingManager(
+ NotificationEntryManager notificationEntryManager,
+ AmbientPulseManager ambientPulseManager,
+ NotificationRemoteInputManager remoteInputManager,
+ VisualStabilityManager visualStabilityManager,
+ Lazy<ShadeController> shadeController,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationListener notificationListener) {
+ mAmbientPulseManager = ambientPulseManager;
+ mRemoteInputManager = remoteInputManager;
+ mVisualStabilityManager = visualStabilityManager;
+ mShadeController = shadeController;
+ mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mNotificationListener = notificationListener;
+
+ notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+ @Override
+ public void onEntryInflated(NotificationData.Entry entry, int inflatedFlags) {
+ showAlertingView(entry, inflatedFlags);
+ }
+
+ @Override
+ public void onEntryUpdated(NotificationData.Entry entry) {
+ updateAlertState(entry);
+ }
+
+ @Override
+ public void onEntryRemoved(
+ NotificationData.Entry entry,
+ String key,
+ StatusBarNotification old,
+ boolean lifetimeExtended,
+ boolean removedByUser) {
+ stopAlerting(key);
+ }
+ });
+ }
+
+ public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+ mHeadsUpManager = headsUpManager;
+ }
+
+ /**
+ * Adds the entry to the respective alerting manager if the content view was inflated and
+ * the entry should still alert.
+ *
+ * @param entry entry to add
+ * @param inflatedFlags flags representing content views that were inflated
+ */
+ private void showAlertingView(NotificationData.Entry entry,
+ @NotificationInflater.InflationFlag int inflatedFlags) {
+ if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
+ // Possible for shouldHeadsUp to change between the inflation starting and ending.
+ // If it does and we no longer need to heads up, we should free the view.
+ if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
+ mHeadsUpManager.showNotification(entry);
+ // Mark as seen immediately
+ setNotificationShown(entry.notification);
+ } else {
+ entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
+ }
+ }
+ if ((inflatedFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
+ if (mNotificationInterruptionStateProvider.shouldPulse(entry)) {
+ mAmbientPulseManager.showNotification(entry);
+ } else {
+ entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
+ }
+ }
+ }
+
+ private void updateAlertState(NotificationData.Entry entry) {
+ boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
+ AlertingNotificationManager alertManager;
+ boolean shouldAlert;
+ if (mShadeController.get().isDozing()) {
+ alertManager = mAmbientPulseManager;
+ shouldAlert = mNotificationInterruptionStateProvider.shouldPulse(entry);
+ } else {
+ alertManager = mHeadsUpManager;
+ shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
+ }
+ final boolean wasAlerting = alertManager.isAlerting(entry.key);
+ if (wasAlerting) {
+ if (!shouldAlert) {
+ // We don't want this to be interrupting anymore, let's remove it
+ alertManager.removeNotification(entry.key,
+ false /* ignoreEarliestRemovalTime */);
+ } else {
+ alertManager.updateNotification(entry.key, alertAgain);
+ }
+ } else if (shouldAlert && alertAgain) {
+ // This notification was updated to be alerting, show it!
+ alertManager.showNotification(entry);
+ }
+ }
+
+ private static boolean alertAgain(
+ NotificationData.Entry oldEntry, Notification newNotification) {
+ return oldEntry == null || !oldEntry.hasInterrupted()
+ || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+ }
+
+ private void setNotificationShown(StatusBarNotification n) {
+ try {
+ mNotificationListener.setNotificationsShown(new String[]{n.getKey()});
+ } catch (RuntimeException e) {
+ Log.d(TAG, "failed setNotificationsShown: ", e);
+ }
+ }
+
+ private void stopAlerting(final String key) {
+ // Attempt to remove notifications from their alert managers (heads up, ambient pulse).
+ // Though the remove itself may fail, it lets the manager know to remove as soon as
+ // possible.
+ if (mHeadsUpManager.isAlerting(key)) {
+ // A cancel() in response to a remote input shouldn't be delayed, as it makes the
+ // sending look longer than it takes.
+ // Also we should not defer the removal if reordering isn't allowed since otherwise
+ // some notifications can't disappear before the panel is closed.
+ boolean ignoreEarliestRemovalTime =
+ mRemoteInputManager.getController().isSpinning(key)
+ && !FORCE_REMOTE_INPUT_HISTORY
+ || !mVisualStabilityManager.isReorderingAllowed();
+ mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime);
+ }
+ if (mAmbientPulseManager.isAlerting(key)) {
+ mAmbientPulseManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index 433a994..27c2837 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -827,6 +827,14 @@
return removed;
}
+ /** Updates the given notification entry with the provided ranking. */
+ public void update(Entry entry, RankingMap ranking, StatusBarNotification notification) {
+ updateRanking(ranking);
+ final StatusBarNotification oldNotification = entry.notification;
+ entry.notification = notification;
+ mGroupManager.onEntryUpdated(entry, oldNotification);
+ }
+
public void updateRanking(RankingMap ranking) {
updateRankingAndSort(ranking);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 361ae8b..8351c40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -17,6 +17,8 @@
import android.service.notification.StatusBarNotification;
+import com.android.systemui.statusbar.notification.row.NotificationInflater;
+
/**
* Listener interface for changes sent by NotificationEntryManager.
*/
@@ -37,12 +39,21 @@
/**
* Called when a notification was updated.
*/
- default void onNotificationUpdated(StatusBarNotification notification) {
+ default void onEntryUpdated(NotificationData.Entry entry) {
+ }
+
+ /**
+ * Called when a notification's views are inflated for the first time.
+ */
+ default void onEntryInflated(NotificationData.Entry entry,
+ @NotificationInflater.InflationFlag int inflatedFlags) {
}
/**
* Called when an existing notification's views are reinflated (usually due to an update being
* posted to that notification).
+ *
+ * @param entry notification data entry that was reinflated.
*/
default void onEntryReinflated(NotificationData.Entry entry) {
}
@@ -50,26 +61,18 @@
/**
* Called when a notification has been removed (either because the user swiped it away or
* because the developer retracted it).
- *
- * TODO: combine this with onNotificationRemoved().
- */
- default void onEntryRemoved(NotificationData.Entry entry) {
- }
-
- /**
- * Called when a notification was removed.
- *
+ * @param entry notification data entry that was removed. Null if no entry existed for the
+ * removed key at the time of removal.
* @param key key of notification that was removed
* @param old StatusBarNotification of the notification before it was removed
+ * @param lifetimeExtended true if something is artificially extending how long the notification
+ * @param removedByUser true if the notification was removed by a user action
*/
- default void onNotificationRemoved(String key, StatusBarNotification old) {
- }
-
- /**
- * Removes a notification immediately.
- *
- * TODO: combine this with onNotificationRemoved().
- */
- default void onPerformRemoveNotification(StatusBarNotification statusBarNotification) {
+ default void onEntryRemoved(
+ NotificationData.Entry entry,
+ String key,
+ StatusBarNotification old,
+ boolean lifetimeExtended,
+ boolean removedByUser) {
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 98ddd6b..39236fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.notification;
import static com.android.systemui.bubbles.BubbleController.DEBUG_DEMOTE_TO_NOTIF;
-import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.Nullable;
import android.app.Notification;
@@ -42,11 +39,8 @@
import com.android.systemui.Dumpable;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationUiAdjustment;
@@ -57,8 +51,6 @@
import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -89,27 +81,18 @@
protected final Context mContext;
protected final HashMap<String, NotificationData.Entry> mPendingNotifications = new HashMap<>();
- private final NotificationGroupManager mGroupManager =
- Dependency.get(NotificationGroupManager.class);
private final NotificationGutsManager mGutsManager =
Dependency.get(NotificationGutsManager.class);
private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
- private final VisualStabilityManager mVisualStabilityManager =
- Dependency.get(VisualStabilityManager.class);
private final ForegroundServiceController mForegroundServiceController =
Dependency.get(ForegroundServiceController.class);
private final AmbientPulseManager mAmbientPulseManager =
Dependency.get(AmbientPulseManager.class);
private final BubbleController mBubbleController = Dependency.get(BubbleController.class);
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
- Dependency.get(NotificationInterruptionStateProvider.class);
// Lazily retrieved dependencies
private NotificationRemoteInputManager mRemoteInputManager;
- private NotificationMediaManager mMediaManager;
- private NotificationListener mNotificationListener;
- private ShadeController mShadeController;
private NotificationRowBinder mNotificationRowBinder;
private final Handler mDeferredNotificationViewUpdateHandler;
@@ -117,7 +100,6 @@
protected IStatusBarService mBarService;
private NotificationPresenter mPresenter;
- private NotificationEntryListener mCallback;
protected PowerManager mPowerManager;
private NotificationListenerService.RankingMap mLatestRankingMap;
protected HeadsUpManager mHeadsUpManager;
@@ -179,27 +161,6 @@
return mRemoteInputManager;
}
- private NotificationMediaManager getMediaManager() {
- if (mMediaManager == null) {
- mMediaManager = Dependency.get(NotificationMediaManager.class);
- }
- return mMediaManager;
- }
-
- private NotificationListener getNotificationListener() {
- if (mNotificationListener == null) {
- mNotificationListener = Dependency.get(NotificationListener.class);
- }
- return mNotificationListener;
- }
-
- private ShadeController getShadeController() {
- if (mShadeController == null) {
- mShadeController = Dependency.get(ShadeController.class);
- }
- return mShadeController;
- }
-
private NotificationRowBinder getRowBinder() {
if (mNotificationRowBinder == null) {
mNotificationRowBinder = Dependency.get(NotificationRowBinder.class);
@@ -208,11 +169,10 @@
}
public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationListContainer listContainer, NotificationEntryListener callback,
+ NotificationListContainer listContainer,
HeadsUpManager headsUpManager) {
mPresenter = presenter;
mUpdateNotificationViewsCallback = mPresenter::updateNotificationViews;
- mCallback = callback;
mHeadsUpManager = headsUpManager;
mNotificationData.setHeadsUpManager(mHeadsUpManager);
mListContainer = listContainer;
@@ -255,9 +215,7 @@
final int count = mNotificationData.getActiveNotifications().size();
final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
true);
- NotificationData.Entry entry = mNotificationData.get(n.getKey());
- getRemoteInputManager().onPerformRemoveNotification(n, entry);
final String pkg = n.getPackageName();
final String tag = n.getTag();
final int id = n.getId();
@@ -272,13 +230,11 @@
int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), dismissalSurface,
dismissalSentiment, nv);
- removeNotification(n.getKey(), null);
-
+ removeNotificationInternal(
+ n.getKey(), null, false /* forceRemove */, true /* removedByUser */);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
-
- mCallback.onPerformRemoveNotification(n);
}
@Override
@@ -318,7 +274,8 @@
*/
@Override
public void handleInflationException(StatusBarNotification n, Exception e) {
- removeNotificationInternal(n.getKey(), null, true /* forceRemove */);
+ removeNotificationInternal(
+ n.getKey(), null, true /* forceRemove */, false /* removedByUser */);
try {
mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
n.getInitialPid(), e.getMessage(), n.getUserId());
@@ -335,7 +292,9 @@
mNotificationData.add(shadeEntry);
tagForeground(shadeEntry.notification);
updateNotifications();
- mCallback.onNotificationAdded(shadeEntry);
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onNotificationAdded(shadeEntry);
+ }
maybeScheduleUpdateNotificationViews(shadeEntry);
}
@@ -349,35 +308,6 @@
}
}
- /**
- * Adds the entry to the respective alerting manager if the content view was inflated and
- * the entry should still alert.
- *
- * @param entry entry to add
- * @param inflatedFlags flags representing content views that were inflated
- */
- private void showAlertingView(NotificationData.Entry entry,
- @InflationFlag int inflatedFlags) {
- if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
- // Possible for shouldHeadsUp to change between the inflation starting and ending.
- // If it does and we no longer need to heads up, we should free the view.
- if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
- mHeadsUpManager.showNotification(entry);
- // Mark as seen immediately
- setNotificationShown(entry.notification);
- } else {
- entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
- }
- }
- if ((inflatedFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
- if (mNotificationInterruptionStateProvider.shouldPulse(entry)) {
- mAmbientPulseManager.showNotification(entry);
- } else {
- entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
- }
- }
- }
-
@Override
public void onAsyncInflationFinished(NotificationData.Entry entry,
@InflationFlag int inflatedFlags) {
@@ -387,13 +317,11 @@
if (!entry.isRowRemoved()) {
boolean isNew = mNotificationData.get(entry.key) == null;
if (isNew) {
- showAlertingView(entry, inflatedFlags);
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onEntryInflated(entry, inflatedFlags);
+ }
addEntry(entry);
} else {
- if (entry.getRow().hasLowPriorityStateUpdated()) {
- mVisualStabilityManager.onLowPriorityUpdated(entry);
- mPresenter.updateNotificationViews();
- }
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onEntryReinflated(entry);
}
@@ -404,75 +332,61 @@
@Override
public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
- removeNotificationInternal(key, ranking, false /* forceRemove */);
+ removeNotificationInternal(
+ key, ranking, false /* forceRemove */, false /* removedByUser */);
}
- private void removeNotificationInternal(String key,
- @Nullable NotificationListenerService.RankingMap ranking, boolean forceRemove) {
+ private void removeNotificationInternal(
+ String key,
+ @Nullable NotificationListenerService.RankingMap ranking,
+ boolean forceRemove,
+ boolean removedByUser) {
final NotificationData.Entry entry = mNotificationData.get(key);
abortExistingInflation(key);
+
+ StatusBarNotification old = null;
+ boolean lifetimeExtended = false;
+
if (entry != null) {
- for (NotificationEntryListener listener : mNotificationEntryListeners) {
- listener.onEntryRemoved(entry);
- }
- }
-
- // Attempt to remove notifications from their alert managers (heads up, ambient pulse).
- // Though the remove itself may fail, it lets the manager know to remove as soon as
- // possible.
- if (mHeadsUpManager.isAlerting(key)) {
- // A cancel() in response to a remote input shouldn't be delayed, as it makes the
- // sending look longer than it takes.
- // Also we should not defer the removal if reordering isn't allowed since otherwise
- // some notifications can't disappear before the panel is closed.
- boolean ignoreEarliestRemovalTime = getRemoteInputManager().getController().isSpinning(key)
- && !FORCE_REMOTE_INPUT_HISTORY
- || !mVisualStabilityManager.isReorderingAllowed();
- mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime);
- }
- if (mAmbientPulseManager.isAlerting(key)) {
- mAmbientPulseManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
- }
-
- if (entry == null) {
- mCallback.onNotificationRemoved(key, null /* old */);
- return;
- }
-
- // If a manager needs to keep the notification around for whatever reason, we return early
- // and keep the notification
- if (!forceRemove) {
- for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
- if (extender.shouldExtendLifetime(entry)) {
- mLatestRankingMap = ranking;
- extender.setShouldManageLifetime(entry, true /* shouldManage */);
- return;
+ // If a manager needs to keep the notification around for whatever reason, we
+ // keep the notification
+ if (!forceRemove) {
+ for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
+ if (extender.shouldExtendLifetime(entry)) {
+ mLatestRankingMap = ranking;
+ extender.setShouldManageLifetime(entry, true /* shouldManage */);
+ lifetimeExtended = true;
+ break;
+ }
}
}
+
+ if (!lifetimeExtended) {
+ // At this point, we are guaranteed the notification will be removed
+
+ // Ensure any managers keeping the lifetime extended stop managing the entry
+ for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
+ extender.setShouldManageLifetime(entry, false /* shouldManage */);
+ }
+
+ mForegroundServiceController.removeNotification(entry.notification);
+
+ if (entry.rowExists()) {
+ entry.removeRow();
+ mListContainer.cleanUpViewStateForEntry(entry);
+ }
+
+ // Let's remove the children if this was a summary
+ handleGroupSummaryRemoved(key);
+
+ old = removeNotificationViews(key, ranking);
+ }
}
- // At this point, we are guaranteed the notification will be removed
-
- // Ensure any managers keeping the lifetime extended stop managing the entry
- for (NotificationLifetimeExtender extender: mNotificationLifetimeExtenders) {
- extender.setShouldManageLifetime(entry, false /* shouldManage */);
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onEntryRemoved(entry, key, old, lifetimeExtended, removedByUser);
}
-
- getMediaManager().onNotificationRemoved(key);
- mForegroundServiceController.removeNotification(entry.notification);
-
- if (entry.rowExists()) {
- entry.removeRow();
- mListContainer.cleanUpViewStateForEntry(entry);
- }
-
- // Let's remove the children if this was a summary
- handleGroupSummaryRemoved(key);
-
- StatusBarNotification old = removeNotificationViews(key, ranking);
-
- mCallback.onNotificationRemoved(key, old);
}
private StatusBarNotification removeNotificationViews(String key,
@@ -616,11 +530,6 @@
}
}
- private boolean alertAgain(NotificationData.Entry oldEntry, Notification newNotification) {
- return oldEntry == null || !oldEntry.hasInterrupted()
- || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
- }
-
private void updateNotificationInternal(StatusBarNotification notification,
NotificationListenerService.RankingMap ranking) throws InflationException {
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
@@ -638,11 +547,7 @@
extender.setShouldManageLifetime(entry, false /* shouldManage */);
}
- mNotificationData.updateRanking(ranking);
-
- final StatusBarNotification oldNotification = entry.notification;
- entry.notification = notification;
- mGroupManager.onEntryUpdated(entry, oldNotification);
+ mNotificationData.update(entry, ranking, notification);
entry.updateIcons(mContext, notification);
getRowBinder().inflateViews(entry, () -> performRemoveNotification(notification),
@@ -651,14 +556,6 @@
mForegroundServiceController.updateNotification(notification,
mNotificationData.getImportance(key));
- boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
- if (getShadeController().isDozing()) {
- updateAlertState(entry, mNotificationInterruptionStateProvider.shouldPulse(entry),
- alertAgain, mAmbientPulseManager);
- } else {
- updateAlertState(entry, mNotificationInterruptionStateProvider.shouldHeadsUp(entry),
- alertAgain, mHeadsUpManager);
- }
updateNotifications();
if (!notification.isClearable()) {
@@ -674,7 +571,9 @@
Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
}
- mCallback.onNotificationUpdated(notification);
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onEntryUpdated(entry);
+ }
maybeScheduleUpdateNotificationViews(entry);
}
@@ -739,43 +638,6 @@
}
}
- private void setNotificationShown(StatusBarNotification n) {
- setNotificationsShown(new String[]{n.getKey()});
- }
-
- protected void setNotificationsShown(String[] keys) {
- try {
- getNotificationListener().setNotificationsShown(keys);
- } catch (RuntimeException e) {
- Log.d(TAG, "failed setNotificationsShown: ", e);
- }
- }
-
- /**
- * Update the entry's alert state and call the appropriate {@link AlertingNotificationManager}
- * method.
- * @param entry entry to update
- * @param shouldAlert whether or not it should be alerting
- * @param alertAgain whether or not an alert should actually come in as if it were new
- * @param alertManager the alerting notification manager that manages the alert state
- */
- private void updateAlertState(NotificationData.Entry entry, boolean shouldAlert,
- boolean alertAgain, AlertingNotificationManager alertManager) {
- final boolean wasAlerting = alertManager.isAlerting(entry.key);
- if (wasAlerting) {
- if (!shouldAlert) {
- // We don't want this to be interrupting anymore, lets remove it
- alertManager.removeNotification(entry.key,
- false /* ignoreEarliestRemovalTime */);
- } else {
- alertManager.updateNotification(entry.key, alertAgain);
- }
- } else if (shouldAlert && alertAgain) {
- // This notification was updated to be alerting, show it!
- alertManager.showNotification(entry);
- }
- }
-
/**
* @return An iterator for all "pending" notifications. Pending notifications are newly-posted
* notifications whose views have not yet been inflated. In general, the system pretends like
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index abb7b416..8e6a93d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -20,6 +20,7 @@
import androidx.collection.ArraySet;
+import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -37,6 +38,7 @@
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private NotificationPresenter mPresenter;
private boolean mPanelExpanded;
private boolean mScreenOn;
private boolean mReorderingAllowed;
@@ -47,7 +49,22 @@
private boolean mPulsing;
@Inject
- public VisualStabilityManager() {
+ public VisualStabilityManager(NotificationEntryManager notificationEntryManager) {
+ notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+ @Override
+ public void onEntryReinflated(NotificationData.Entry entry) {
+ if (entry.hasLowPriorityStateUpdated()) {
+ onLowPriorityUpdated(entry);
+ if (mPresenter != null) {
+ mPresenter.updateNotificationViews();
+ }
+ }
+ }
+ });
+ }
+
+ public void setUpWithPresenter(NotificationPresenter presenter) {
+ mPresenter = presenter;
}
/**
@@ -154,7 +171,7 @@
}
}
- public void onLowPriorityUpdated(NotificationData.Entry entry) {
+ private void onLowPriorityUpdated(NotificationData.Entry entry) {
mLowPriorityReorderingViews.add(entry.getRow());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index eb1fc30..75bad6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -27,7 +27,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarStateController;
@@ -59,11 +58,9 @@
new ArraySet<>();
// Dependencies:
- private final NotificationListenerService mNotificationListener =
- Dependency.get(NotificationListener.class);
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
- protected NotificationEntryManager mEntryManager
- = Dependency.get(NotificationEntryManager.class);
+ private final NotificationListenerService mNotificationListener;
+ private final UiOffloadThread mUiOffloadThread;
+ protected NotificationEntryManager mEntryManager;
protected Handler mHandler = new Handler();
protected IStatusBarService mBarService;
@@ -150,11 +147,17 @@
};
@Inject
- public NotificationLogger() {
+ public NotificationLogger(NotificationListener notificationListener,
+ UiOffloadThread uiOffloadThread,
+ NotificationEntryManager entryManager,
+ StatusBarStateController statusBarStateController) {
+ mNotificationListener = notificationListener;
+ mUiOffloadThread = uiOffloadThread;
+ mEntryManager = entryManager;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
// Not expected to be destroyed, don't need to unsubscribe
- Dependency.get(StatusBarStateController.class).addCallback(this);
+ statusBarStateController.addCallback(this);
}
public void setUpWithContainer(NotificationListContainer listContainer) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 92a9efe..6f2b63d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -158,8 +158,11 @@
* @return duration in millis.
*/
public long getWallpaperAodDuration() {
- return shouldControlScreenOff() ? DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY
- : mAlwaysOnPolicy.wallpaperVisibilityDuration;
+ if (mAmbientDisplayConfiguration.wakeLockScreenGestureEnabled(UserHandle.USER_CURRENT)
+ || shouldControlScreenOff()) {
+ return DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY;
+ }
+ return mAlwaysOnPolicy.wallpaperVisibilityDuration;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 21c506b..2e9d9bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,7 +19,6 @@
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
@@ -54,7 +53,6 @@
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.MathUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
@@ -172,8 +170,6 @@
private boolean mDozing;
private int mIndicationBottomMargin;
private float mDarkAmount;
- private int mBurnInXOffset;
- private int mBurnInYOffset;
public KeyguardBottomAreaView(Context context) {
this(context, null);
@@ -250,8 +246,6 @@
mIndicationText = findViewById(R.id.keyguard_indication_text);
mIndicationBottomMargin = getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_margin_bottom);
- mBurnInYOffset = getResources().getDimensionPixelSize(
- R.dimen.default_burn_in_prevention_offset);
updateCameraVisibility();
mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
mUnlockMethodCache.addListener(this);
@@ -322,8 +316,6 @@
super.onConfigurationChanged(newConfig);
mIndicationBottomMargin = getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_margin_bottom);
- mBurnInYOffset = getResources().getDimensionPixelSize(
- R.dimen.default_burn_in_prevention_offset);
MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
if (mlp.bottomMargin != mIndicationBottomMargin) {
mlp.bottomMargin = mIndicationBottomMargin;
@@ -569,7 +561,15 @@
mDarkAmount = darkAmount;
mIndicationController.setDarkAmount(darkAmount);
mLockIcon.setDarkAmount(darkAmount);
- dozeTimeTick();
+ }
+
+ /**
+ * When keyguard is in pulsing (AOD2) state.
+ * @param pulsing {@code true} when pulsing.
+ * @param animated if transition should be animated.
+ */
+ public void setPulsing(boolean pulsing, boolean animated) {
+ mLockIcon.setPulsing(pulsing, animated);
}
private static boolean isSuccessfulLaunch(int result) {
@@ -830,6 +830,7 @@
updateCameraVisibility();
updateLeftAffordanceIcon();
+ mLockIcon.setDozing(dozing);
if (dozing) {
mOverlayContainer.setVisibility(INVISIBLE);
@@ -841,21 +842,6 @@
}
}
- public void dozeTimeTick() {
- // Move views every minute to avoid burn-in
- int burnInYOffset = -getBurnInOffset(mBurnInYOffset, false /* xAxis */);
- burnInYOffset = (int) MathUtils.lerp(0, burnInYOffset, mDarkAmount);
- mLockIcon.setTranslationY(burnInYOffset);
- }
-
- public void setBurnInXOffset(int burnInXOffset) {
- if (mBurnInXOffset == burnInXOffset) {
- return;
- }
- mBurnInXOffset = burnInXOffset;
- mLockIcon.setTranslationX(burnInXOffset);
- }
-
private class DefaultLeftButton implements IntentButton {
private IconState mIconState = new IconState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
index b3423a8..927228e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
@@ -22,7 +22,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -34,8 +33,6 @@
Dependency.get(NotificationLockscreenUserManager.class);
private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
- private final NotificationMediaManager mMediaManager =
- Dependency.get(NotificationMediaManager.class);
public KeyguardEnvironmentImpl() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index e156e77..6632d58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -25,7 +25,6 @@
import android.view.View;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -83,10 +82,11 @@
private final Context mContext;
@Inject
- public LightBarController(Context ctx) {
+ public LightBarController(Context ctx, DarkIconDispatcher darkIconDispatcher,
+ BatteryController batteryController) {
mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
- mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
- mBatteryController = Dependency.get(BatteryController.class);
+ mStatusBarIconController = darkIconDispatcher;
+ mBatteryController = batteryController;
mBatteryController.addCallback(this);
mContext = ctx;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 1be3975..d934d95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -45,8 +45,6 @@
private static final int STATE_FACE_UNLOCK = 2;
private static final int STATE_FINGERPRINT = 3;
private static final int STATE_FINGERPRINT_ERROR = 4;
- private static final boolean HOLLOW_PILL = SystemProperties
- .getBoolean("persist.sysui.hollow_pill", false);
private int mLastState = 0;
private boolean mLastDeviceInteractive;
@@ -60,6 +58,8 @@
private boolean mHasFingerPrintIcon;
private boolean mHasFaceUnlockIcon;
private int mDensity;
+ private boolean mPulsing;
+ private boolean mDozing;
private final Runnable mDrawOffTimeout = () -> update(true /* forceUpdate */);
private float mDarkAmount;
@@ -159,6 +159,7 @@
mLastScreenOn = mScreenOn;
}
+ setVisibility(mDozing && !mPulsing ? GONE : VISIBLE);
updateClickability();
}
@@ -224,16 +225,6 @@
throw new IllegalArgumentException();
}
- if (HOLLOW_PILL && deviceInteractive) {
- switch (state) {
- case STATE_FINGERPRINT:
- case STATE_LOCK_OPEN:
- case STATE_LOCKED:
- case STATE_FACE_UNLOCK:
- iconRes = R.drawable.ic_home_button_outline;
- }
- }
-
return mContext.getDrawable(iconRes);
}
@@ -281,6 +272,24 @@
updateDarkTint();
}
+ /**
+ * When keyguard is in pulsing (AOD2) state.
+ * @param pulsing {@code true} when pulsing.
+ * @param animated if transition should be animated.
+ */
+ public void setPulsing(boolean pulsing, boolean animated) {
+ mPulsing = pulsing;
+ update();
+ }
+
+ /**
+ * Sets the dozing state of the keyguard.
+ */
+ public void setDozing(boolean dozing) {
+ mDozing = dozing;
+ update();
+ }
+
private void updateDarkTint() {
Drawable drawable = getDrawable().mutate();
int color = ColorUtils.blendARGB(Color.TRANSPARENT, Color.WHITE, mDarkAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index b1f74c8..1a78302 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -216,11 +216,16 @@
}
@Override
- public void onEntryRemoved(Entry entry) {
+ public void onEntryRemoved(
+ Entry entry,
+ String key,
+ StatusBarNotification old,
+ boolean lifetimeExtended,
+ boolean removedByUser) {
// Removes any alerts pending on this entry. Note that this will not stop any inflation
// tasks started by a transfer, so this should only be used as clean-up for when
// inflation is stopped and the pending alert no longer needs to happen.
- mPendingAlerts.remove(entry.key);
+ mPendingAlerts.remove(key);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 242573d..1b18c6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -579,7 +579,6 @@
}
mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX);
- mKeyguardBottomArea.setBurnInXOffset(mClockPositionResult.clockX);
mStackScrollerMeasuringPass++;
requestScrollerTopPaddingUpdate(animate);
@@ -2806,6 +2805,7 @@
}
mNotificationStackScroller.setPulsing(pulsing, animatePulse);
mKeyguardStatusView.setPulsing(pulsing, animatePulse);
+ mKeyguardBottomArea.setPulsing(pulsing, animatePulse);
}
public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
@@ -2818,7 +2818,6 @@
public void dozeTimeTick() {
mKeyguardStatusBar.dozeTimeTick();
mKeyguardStatusView.dozeTimeTick();
- mKeyguardBottomArea.dozeTimeTick();
if (mInterpolatedDarkAmount > 0) {
positionClockAndNotifications();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 6a4da98..e25c829 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -93,12 +93,12 @@
* A scrim varies its opacity based on a busyness factor, for example
* how many notifications are currently visible.
*/
- public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.70f;
+ public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.7f;
/**
- * A scrim varies its opacity based on a busyness factor, for example
- * how many notifications are currently visible.
+ * Scrim opacity when a wallpaper doesn't support ambient mode.
*/
- public static final float GRADIENT_SCRIM_DARK_KEYGUARD = 0.80f;
+ public static final float PULSING_WALLPAPER_SCRIM_ALPHA = 0.6f;
+
/**
* The most common scrim, the one under the keyguard.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 226665e..fb3c4aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -141,7 +141,8 @@
@Override
public float getBehindAlpha(float busyness) {
- return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
+ return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f
+ : ScrimController.PULSING_WALLPAPER_SCRIM_ALPHA;
}
},
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 40e2aae..efe734e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -148,7 +148,6 @@
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.doze.LockScreenWakeUpController;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -160,7 +159,6 @@
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSTileHost;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -188,6 +186,7 @@
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
@@ -221,6 +220,7 @@
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.volume.VolumeComponent;
import java.io.FileDescriptor;
@@ -229,6 +229,10 @@
import java.util.ArrayList;
import java.util.Map;
+import javax.inject.Inject;
+
+import dagger.Subcomponent;
+
public class StatusBar extends SystemUI implements DemoMode,
ActivityStarter, OnUnlockMethodChangedListener,
OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
@@ -354,6 +358,8 @@
private final Object mQueueLock = new Object();
protected StatusBarIconController mIconController;
+ @Inject
+ InjectionInflationController mInjectionInflater;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -386,6 +392,8 @@
protected AppOpsController mAppOpsController;
protected KeyguardViewMediator mKeyguardViewMediator;
private ZenModeController mZenController;
+ private final NotificationAlertingManager mNotificationAlertingManager =
+ Dependency.get(NotificationAlertingManager.class);
// for disabling the status bar
private int mDisabled1 = 0;
@@ -588,7 +596,6 @@
protected NotificationPresenter mPresenter;
private NotificationActivityStarter mNotificationActivityStarter;
private boolean mPulsing;
- private LockScreenWakeUpController mLockScreenWakeUpController;
@Override
public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
@@ -940,8 +947,6 @@
.withPlugin(QS.class)
.withDefault(this::createDefaultQSFragment)
.build());
- final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
- mIconController);
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow,
(visible) -> {
mBrightnessMirrorVisible = visible;
@@ -950,7 +955,6 @@
fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
QS qs = (QS) f;
if (qs instanceof QSFragment) {
- ((QSFragment) qs).setHost(qsh);
mQSPanel = ((QSFragment) qs).getQsPanel();
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
}
@@ -999,7 +1003,6 @@
for (int i = 0; i < pattern.length; i++) {
mCameraLaunchGestureVibePattern[i] = pattern[i];
}
- mLockScreenWakeUpController = new LockScreenWakeUpController(mContext, mDozeServiceHost);
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -1039,7 +1042,8 @@
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
- mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager);
+ mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager,
+ mNotificationAlertingManager);
mAppOpsController.addCallback(APP_OPS, this);
mNotificationListener.setUpWithPresenter(mPresenter);
@@ -1199,8 +1203,8 @@
}
protected void inflateStatusBarWindow(Context context) {
- mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
- R.layout.super_status_bar, null);
+ mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
+ LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
}
protected void startKeyguard() {
@@ -4507,4 +4511,9 @@
public NotificationGutsManager getGutsManager() {
return mGutsManager;
}
+
+ @Subcomponent
+ public interface StatusBarInjector {
+ void createStatusBar(StatusBar statusbar);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index d643f07..252b92c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -56,11 +56,13 @@
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -97,6 +99,8 @@
Dependency.get(NotificationInterruptionStateProvider.class);
private final NotificationMediaManager mMediaManager =
Dependency.get(NotificationMediaManager.class);
+ private final VisualStabilityManager mVisualStabilityManager =
+ Dependency.get(VisualStabilityManager.class);
protected AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
private final NotificationPanelView mNotificationPanel;
@@ -129,7 +133,8 @@
DozeScrimController dozeScrimController,
ScrimController scrimController,
ActivityLaunchAnimator activityLaunchAnimator,
- StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ NotificationAlertingManager notificationAlertingManager) {
mContext = context;
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
@@ -181,37 +186,44 @@
}
@Override
- public void onNotificationUpdated(StatusBarNotification notification) {
+ public void onEntryUpdated(Entry entry) {
mShadeController.updateAreThereNotifications();
}
@Override
- public void onNotificationRemoved(String key, StatusBarNotification old) {
- StatusBarNotificationPresenter.this.onNotificationRemoved(key, old);
- }
-
- @Override
- public void onPerformRemoveNotification(
- StatusBarNotification statusBarNotification) {
- StatusBarNotificationPresenter.this.onPerformRemoveNotification();
+ public void onEntryRemoved(
+ Entry entry,
+ String key,
+ StatusBarNotification old,
+ boolean lifetimeExtended,
+ boolean removedByUser) {
+ if (!lifetimeExtended) {
+ StatusBarNotificationPresenter.this.onNotificationRemoved(key, old);
+ }
+ if (removedByUser) {
+ maybeEndAmbientPulse();
+ }
}
};
mViewHierarchyManager.setUpWithPresenter(this, notifListContainer);
- mEntryManager.setUpWithPresenter(
- this, notifListContainer, notificationEntryListener, mHeadsUpManager);
+ mEntryManager.setUpWithPresenter(this, notifListContainer, mHeadsUpManager);
+ mEntryManager.addNotificationEntryListener(notificationEntryListener);
mNotificationRowBinder.setUpWithPresenter(this, notifListContainer, mHeadsUpManager,
mEntryManager, this);
mNotificationInterruptionStateProvider.setUpWithPresenter(
this, mHeadsUpManager, this::canHeadsUp);
mLockscreenUserManager.setUpWithPresenter(this);
mMediaManager.setUpWithPresenter(this);
+ mVisualStabilityManager.setUpWithPresenter(this);
Dependency.get(NotificationGutsManager.class).setUpWithPresenter(this,
notifListContainer, mCheckSaveListener, mOnSettingsClickListener);
onUserSwitched(mLockscreenUserManager.getCurrentUserId());
});
Dependency.get(ConfigurationController.class).addCallback(this);
+
+ notificationAlertingManager.setHeadsUpManager(mHeadsUpManager);
}
@Override
@@ -253,7 +265,7 @@
|| mActivityLaunchAnimator.isAnimationRunning();
}
- private void onPerformRemoveNotification() {
+ private void maybeEndAmbientPulse() {
if (mNotificationPanel.hasPulsingNotifications() &&
!mAmbientPulseManager.hasNotifications()) {
// We were showing a pulse for a notification, but no notifications are pulsing anymore.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 5d61f4a..6190c8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -30,7 +30,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.utils.PowerUtil;
-import com.android.systemui.Dependency;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.Estimate;
@@ -55,7 +54,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60;
- private final EnhancedEstimates mEstimates = Dependency.get(EnhancedEstimates.class);
+ private final EnhancedEstimates mEstimates;
private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
private final Handler mHandler;
@@ -73,15 +72,17 @@
private long mLastEstimateTimestamp = -1;
@Inject
- public BatteryControllerImpl(Context context) {
- this(context, context.getSystemService(PowerManager.class));
+ public BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates) {
+ this(context, enhancedEstimates, context.getSystemService(PowerManager.class));
}
@VisibleForTesting
- BatteryControllerImpl(Context context, PowerManager powerManager) {
+ BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
+ PowerManager powerManager) {
mContext = context;
mHandler = new Handler();
mPowerManager = powerManager;
+ mEstimates = enhancedEstimates;
registerReceiver();
updatePowerSave();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index c855000..8916242 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -18,6 +18,7 @@
import static com.android.systemui.Dependency.BG_LOOPER_NAME;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -34,7 +35,6 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.systemui.Dependency;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -73,8 +73,9 @@
/**
*/
@Inject
- public BluetoothControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
- mLocalBluetoothManager = Dependency.get(LocalBluetoothManager.class);
+ public BluetoothControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
+ @Nullable LocalBluetoothManager localBluetoothManager) {
+ mLocalBluetoothManager = localBluetoothManager;
mBgHandler = new Handler(bgLooper);
if (mLocalBluetoothManager != null) {
mLocalBluetoothManager.getEventManager().registerCallback(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index c995162..f5e745f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -14,6 +14,8 @@
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -21,13 +23,14 @@
import android.net.Uri;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
+import android.os.Handler;
-import com.android.systemui.Dependency;
import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -41,16 +44,28 @@
private final Context mContext;
private final Uri mDeviceProvisionedUri;
private final Uri mUserSetupUri;
+ protected final ContentObserver mSettingsObserver;
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context) {
+ public DeviceProvisionedControllerImpl(Context context,
+ @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
super(context);
mContext = context;
mContentResolver = context.getContentResolver();
mDeviceProvisionedUri = Global.getUriFor(Global.DEVICE_PROVISIONED);
mUserSetupUri = Secure.getUriFor(Secure.USER_SETUP_COMPLETE);
+ mSettingsObserver = new ContentObserver(mainHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (mUserSetupUri.equals(uri)) {
+ notifySetupChanged();
+ } else {
+ notifyProvisionedChanged();
+ }
+ }
+ };
}
@Override
@@ -127,17 +142,4 @@
mListeners.get(i).onDeviceProvisionedChanged();
}
}
-
- protected final ContentObserver mSettingsObserver = new ContentObserver(Dependency.get(
- Dependency.MAIN_HANDLER)) {
-
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- if (mUserSetupUri.equals(uri)) {
- notifySetupChanged();
- } else {
- notifyProvisionedChanged();
- }
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 420abe8..b561ac1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,20 +16,22 @@
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.app.ActivityManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
+import android.os.Handler;
import android.os.UserManager;
import android.util.Log;
-import com.android.systemui.Dependency;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -43,6 +45,7 @@
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private final ConnectivityManager mConnectivityManager;
private final WifiManager mWifiManager;
+ private final Handler mMainHandler;
private final Context mContext;
private int mHotspotState;
@@ -52,11 +55,12 @@
/**
*/
@Inject
- public HotspotControllerImpl(Context context) {
+ public HotspotControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
mContext = context;
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mMainHandler = mainHandler;
}
@Override
@@ -118,10 +122,13 @@
* @param shouldListen whether we should start listening to various wifi statuses
*/
private void updateWifiStateListeners(boolean shouldListen) {
+ if (mWifiManager == null) {
+ return;
+ }
if (shouldListen) {
mWifiManager.registerSoftApCallback(
this,
- Dependency.get(Dependency.MAIN_HANDLER));
+ mMainHandler);
} else {
mWifiManager.unregisterSoftApCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
index 2a10db6..630bd18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
@@ -21,7 +21,6 @@
import android.content.res.Configuration;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.CommandQueue;
@@ -44,11 +43,12 @@
@VisibleForTesting CommandQueue mCommandQueue;
@Inject
- public RemoteInputQuickSettingsDisabler(Context context) {
+ public RemoteInputQuickSettingsDisabler(Context context,
+ ConfigurationController configController) {
mContext = context;
mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
mLastOrientation = mContext.getResources().getConfiguration().orientation;
- Dependency.get(ConfigurationController.class).addCallback(this);
+ configController.addCallback(this);
}
public int adjustDisableFlags(int state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index e0259c9..d88ae78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -15,6 +15,8 @@
*/
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.Dependency.BG_HANDLER_NAME;
+
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
@@ -47,7 +49,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.settings.CurrentUserTracker;
@@ -56,6 +57,7 @@
import java.util.ArrayList;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
/**
@@ -84,6 +86,7 @@
private final DevicePolicyManager mDevicePolicyManager;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
+ private final Handler mBgHandler;
@GuardedBy("mCallbacks")
private final ArrayList<SecurityControllerCallback> mCallbacks = new ArrayList<>();
@@ -99,13 +102,15 @@
/**
*/
@Inject
- public SecurityControllerImpl(Context context) {
- this(context, null);
+ public SecurityControllerImpl(Context context, @Named(BG_HANDLER_NAME) Handler bgHandler) {
+ this(context, bgHandler, null);
}
- public SecurityControllerImpl(Context context, SecurityControllerCallback callback) {
+ public SecurityControllerImpl(Context context, Handler bgHandler,
+ SecurityControllerCallback callback) {
super(context);
mContext = context;
+ mBgHandler = bgHandler;
mDevicePolicyManager = (DevicePolicyManager)
context.getSystemService(Context.DEVICE_POLICY_SERVICE);
mConnectivityManager = (ConnectivityManager)
@@ -121,7 +126,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null,
- new Handler(Dependency.get(Dependency.BG_LOOPER)));
+ bgHandler);
// TODO: re-register network callback on user change.
mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
@@ -413,7 +418,7 @@
return new Pair<Integer, Boolean>(userId[0], hasCACerts);
} catch (RemoteException | InterruptedException | AssertionError e) {
Log.i(TAG, "failed to get CA certs", e);
- new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(
+ mBgHandler.postDelayed(
() -> new CACertLoader().execute(userId[0]),
CA_CERT_LOADING_RETRY_TIME_IN_MS);
return new Pair<Integer, Boolean>(userId[0], null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index e412e09..9343bf1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -51,7 +51,6 @@
import com.android.internal.util.UserIcons;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.GuestResumeSessionReceiver;
import com.android.systemui.Prefs;
@@ -597,7 +596,7 @@
protected BaseUserAdapter(UserSwitcherController controller) {
mController = controller;
- mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mKeyguardMonitor = controller.mKeyguardMonitor;
controller.addAdapter(new WeakReference<>(this));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 693df88..6f63544 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -53,7 +53,9 @@
connectivityManager, this::handleStatusUpdated);
mWifiTracker.setListening(true);
mHasMobileData = hasMobileData;
- wifiManager.registerTrafficStateCallback(new WifiTrafficStateCallback(), null);
+ if (wifiManager != null) {
+ wifiManager.registerTrafficStateCallback(new WifiTrafficStateCallback(), null);
+ }
// WiFi only has one state.
mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
"Wi-Fi Icons",
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
index 81d77a6..8f3a8f6 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
@@ -38,8 +38,9 @@
private final View mView;
private final int mDefaultSize;
private final float mDensity;
+ private final TunerService mTunerService;
- private TunablePadding(String key, int def, int flags, View view) {
+ private TunablePadding(String key, int def, int flags, View view, TunerService tunerService) {
mDefaultSize = def;
mFlags = flags;
mView = view;
@@ -47,7 +48,8 @@
view.getContext().getSystemService(WindowManager.class)
.getDefaultDisplay().getMetrics(metrics);
mDensity = metrics.density;
- Dependency.get(TunerService.class).addTunable(this, key);
+ mTunerService = tunerService;
+ mTunerService.addTunable(this, key);
}
@Override
@@ -69,7 +71,7 @@
}
public void destroy() {
- Dependency.get(TunerService.class).removeTunable(this);
+ mTunerService.removeTunable(this);
}
/**
@@ -78,17 +80,20 @@
@Singleton
public static class TunablePaddingService {
+ private final TunerService mTunerService;
+
/**
*/
@Inject
- public TunablePaddingService() {
+ public TunablePaddingService(TunerService tunerService) {
+ mTunerService = tunerService;
}
public TunablePadding add(View view, String key, int defaultSize, int flags) {
if (view == null) {
throw new IllegalArgumentException();
}
- return new TunablePadding(key, defaultSize, flags, view);
+ return new TunablePadding(key, defaultSize, flags, view, mTunerService);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 0a47f19..6185063 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -15,6 +15,8 @@
*/
package com.android.systemui.tuner;
+import static com.android.systemui.Dependency.BG_HANDLER_NAME;
+
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -33,7 +35,6 @@
import com.android.internal.util.ArrayUtils;
import com.android.systemui.DemoMode;
-import com.android.systemui.Dependency;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -44,6 +45,7 @@
import java.util.Set;
import javax.inject.Inject;
+import javax.inject.Named;
import javax.inject.Singleton;
@@ -71,6 +73,7 @@
// Set of all tunables, used for leak detection.
private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
private final Context mContext;
+ private final LeakDetector mLeakDetector;
private ContentResolver mContentResolver;
private int mCurrentUser;
@@ -79,14 +82,16 @@
/**
*/
@Inject
- public TunerServiceImpl(Context context) {
+ public TunerServiceImpl(Context context, @Named(BG_HANDLER_NAME) Handler bgHandler,
+ LeakDetector leakDetector) {
mContext = context;
mContentResolver = mContext.getContentResolver();
+ mLeakDetector = leakDetector;
for (UserInfo user : UserManager.get(mContext).getUsers()) {
mCurrentUser = user.getUserHandle().getIdentifier();
if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
- upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION);
+ upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, bgHandler);
}
}
@@ -107,7 +112,7 @@
mUserTracker.stopTracking();
}
- private void upgradeTuner(int oldVersion, int newVersion) {
+ private void upgradeTuner(int oldVersion, int newVersion, Handler bgHandler) {
if (oldVersion < 1) {
String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
if (blacklistStr != null) {
@@ -129,7 +134,7 @@
if (oldVersion < 4) {
// Delay this so that we can wait for everything to be registered first.
final int user = mCurrentUser;
- new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(
+ bgHandler.postDelayed(
() -> clearAllFromUser(user), 5000);
}
setValue(TUNER_VERSION, newVersion);
@@ -176,7 +181,7 @@
mTunableLookup.get(key).add(tunable);
if (LeakDetector.ENABLED) {
mTunables.add(tunable);
- Dependency.get(LeakDetector.class).trackCollection(mTunables, "TunerService.mTunables");
+ mLeakDetector.trackCollection(mTunables, "TunerService.mTunables");
}
Uri uri = Settings.Secure.getUriFor(key);
if (!mListeningUris.containsKey(uri)) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index e458e63..59aa522 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -24,6 +24,7 @@
import android.view.View;
import com.android.systemui.SystemUIFactory;
+import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QuickStatusBarHeader;
import java.lang.reflect.InvocationTargetException;
@@ -107,6 +108,10 @@
* Creates the QuickStatusBarHeader.
*/
QuickStatusBarHeader createQsHeader();
+ /**
+ * Creates the QSFooterImpl.
+ */
+ QSFooterImpl createQsFooter();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 7bc9626..b590e77 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -43,9 +43,9 @@
import android.util.Log;
import android.util.LongSparseArray;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
@@ -346,9 +346,10 @@
private final GarbageMonitor gm;
private ProcessMemInfo pmi;
+ @Inject
public MemoryTile(QSHost host) {
super(host);
- gm = Dependency.get(GarbageMonitor.class);
+ gm = SystemUIFactory.getInstance().getRootComponent().createGarbageMonitor();
}
@Override
@@ -453,7 +454,8 @@
Settings.Secure.getInt(
mContext.getContentResolver(), FORCE_ENABLE_LEAK_REPORTING, 0)
!= 0;
- mGarbageMonitor = Dependency.get(GarbageMonitor.class);
+ mGarbageMonitor = SystemUIFactory.getInstance().getRootComponent()
+ .createGarbageMonitor();
if (LEAK_REPORTING_ENABLED || forceEnable) {
mGarbageMonitor.startLeakMonitor();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 16ef63f..8f2b2d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -144,8 +144,7 @@
TestableBubbleController(Context context,
StatusBarWindowController statusBarWindowController) {
- super(context);
- mStatusBarWindowController = statusBarWindowController;
+ super(context, statusBarWindowController);
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index e1c0cd4..9946317 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -119,7 +119,7 @@
@Test
public void testOnEvent_undockedWhenDoze_neverRequestPulseOut() throws Exception {
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
- when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_PULSING);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
mDockManagerFake.setDockEvent(DockManager.STATE_UNDOCKING);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/LockScreenWakeUpControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/LockScreenWakeUpControllerTest.java
deleted file mode 100644
index 8963b59..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/LockScreenWakeUpControllerTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.doze;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.os.Handler;
-import android.os.PowerManager;
-import android.support.test.filters.SmallTest;
-
-import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.SensorManagerPlugin;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.util.AsyncSensorManager;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(JUnit4.class)
-@SmallTest
-public class LockScreenWakeUpControllerTest extends SysuiTestCase {
-
- @Mock
- private AsyncSensorManager mAsyncSensorManager;
- @Mock
- private SensorManagerPlugin.Sensor mSensor;
- @Mock
- private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
- @Mock
- private PowerManager mPowerManager;
- @Mock
- private DozeHost mDozeHost;
- @Mock
- private StatusBarStateController mStatusBarStateController;
- @Mock
- private Handler mHandler;
-
- private LockScreenWakeUpController mLockScreenWakeUpController;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- doAnswer(invocation -> {
- ((Runnable) invocation.getArgument(0)).run();
- return null;
- }).when(mHandler).post(any());
-
- mLockScreenWakeUpController = new LockScreenWakeUpController(mAsyncSensorManager, mSensor,
- mAmbientDisplayConfiguration, mPowerManager, mDozeHost, mStatusBarStateController,
- mHandler);
- }
-
- @Test
- public void testOnStateChanged_registersUnregistersListener() {
- when(mAmbientDisplayConfiguration.wakeLockScreenGestureEnabled(anyInt())).thenReturn(true);
- mLockScreenWakeUpController.onStateChanged(StatusBarState.KEYGUARD);
- mLockScreenWakeUpController.onStateChanged(StatusBarState.SHADE);
-
- verify(mAsyncSensorManager, times(1)).registerPluginListener(eq(mSensor),
- eq(mLockScreenWakeUpController));
-
- mLockScreenWakeUpController.onStateChanged(StatusBarState.SHADE);
- verify(mAsyncSensorManager).unregisterPluginListener(eq(mSensor),
- eq(mLockScreenWakeUpController));
- }
-
- @Test
- public void testOnStateChanged_disabledSensor() {
- when(mAmbientDisplayConfiguration.wakeLockScreenGestureEnabled(anyInt()))
- .thenReturn(false);
- mLockScreenWakeUpController.onStateChanged(StatusBarState.KEYGUARD);
- mLockScreenWakeUpController.onStateChanged(StatusBarState.SHADE);
-
- verify(mAsyncSensorManager, never()).registerPluginListener(eq(mSensor),
- eq(mLockScreenWakeUpController));
- }
-
- @Test
- public void testOnSensorChanged_postsToMainThread() {
- SensorManagerPlugin.SensorEvent event = new SensorManagerPlugin.SensorEvent(mSensor, 0);
- mLockScreenWakeUpController.onSensorChanged(event);
-
- verify(mHandler).post(any());
- }
-
- @Test
- public void testOnSensorChanged_wakeUpWhenDozing() {
- SensorManagerPlugin.SensorEvent event =
- new SensorManagerPlugin.SensorEvent(mSensor, 0, new float[] {1});
- mLockScreenWakeUpController.onSensorChanged(event);
- verify(mPowerManager, never()).wakeUp(anyLong(), any());
-
- mLockScreenWakeUpController.onDozingChanged(true);
- mLockScreenWakeUpController.onSensorChanged(event);
- verify(mPowerManager).wakeUp(anyLong(), any());
- }
-
- @Test
- public void testOnSensorChanged_sleepsWhenAwake() {
- boolean[] goToSleep = new boolean[] {false};
- doAnswer(invocation -> goToSleep[0] = true)
- .when(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
- SensorManagerPlugin.SensorEvent event =
- new SensorManagerPlugin.SensorEvent(mSensor, 0, new float[] {0});
- mLockScreenWakeUpController.onDozingChanged(true);
- mLockScreenWakeUpController.onSensorChanged(event);
- Assert.assertFalse("goToSleep should have never been called.", goToSleep[0]);
-
- mLockScreenWakeUpController.onDozingChanged(false);
- mLockScreenWakeUpController.onSensorChanged(event);
- Assert.assertTrue("goToSleep should have been called.", goToSleep[0]);
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 45e49df..2cb326e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -21,6 +21,7 @@
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
+import android.os.Handler;
import android.os.Looper;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -36,10 +37,14 @@
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.Clock;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
@@ -85,7 +90,9 @@
QSFragment qs = (QSFragment) mFragment;
mFragments.dispatchResume();
processAllMessages();
- QSTileHost host = new QSTileHost(mContext, null, mock(StatusBarIconController.class));
+ QSTileHost host = new QSTileHost(mContext, mock(StatusBarIconController.class),
+ mock(QSFactoryImpl.class), new Handler(), Looper.myLooper(),
+ mock(PluginManager.class), mock(TunerService.class));
qs.setHost(host);
qs.setListening(true);
@@ -124,8 +131,10 @@
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
- return new QSFragment(new RemoteInputQuickSettingsDisabler(context),
+ return new QSFragment(
+ new RemoteInputQuickSettingsDisabler(context, mock(ConfigurationController.class)),
new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
- context);
+ context,
+ mock(QSTileHost.class));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index c6597b9..63f4bbc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.mock;
import android.content.ComponentName;
+import android.os.Handler;
import android.os.Looper;
import android.service.quicksettings.Tile;
import android.test.suitebuilder.annotation.SmallTest;
@@ -30,8 +31,11 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.tuner.TunerService;
import org.junit.After;
import org.junit.Before;
@@ -55,8 +59,13 @@
public void setUp() throws Exception {
mDependency.injectMockDependency(BluetoothController.class);
mManagers = new ArrayList<>();
- QSTileHost host = new QSTileHost(mContext, null,
- mock(StatusBarIconController.class));
+ QSTileHost host = new QSTileHost(mContext,
+ mock(StatusBarIconController.class),
+ mock(QSFactoryImpl.class),
+ new Handler(),
+ Looper.myLooper(),
+ mock(PluginManager.class),
+ mock(TunerService.class));
mTileService = new TestTileServices(host, Looper.getMainLooper());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index d9412ec..efcbb76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -15,8 +15,8 @@
package com.android.systemui.qs.tiles;
import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -26,6 +26,8 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.lifecycle.LifecycleOwner;
+
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter;
@@ -79,7 +81,8 @@
when(mHost.getContext()).thenReturn(mContext);
- mCastTile = new CastTile(mHost);
+ mCastTile = new CastTile(mHost, mController, mKeyguard, mNetworkController,
+ mActivityStarter);
// We are not setting the mocks to listening, so we trigger a first refresh state to
// set the initial state
@@ -88,7 +91,8 @@
mCastTile.handleSetListening(true);
ArgumentCaptor<NetworkController.SignalCallback> signalCallbackArgumentCaptor =
ArgumentCaptor.forClass(NetworkController.SignalCallback.class);
- verify(mNetworkController).addCallback(signalCallbackArgumentCaptor.capture());
+ verify(mNetworkController).observe(any(LifecycleOwner.class),
+ signalCallbackArgumentCaptor.capture());
mCallback = signalCallbackArgumentCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java
index 90792e3..751a616 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.qs.tiles;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +28,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -64,7 +66,8 @@
when(mHost.getContext()).thenReturn(mContext);
- mSensorPrivacyTile = new SensorPrivacyTile(mHost);
+ mSensorPrivacyTile = new SensorPrivacyTile(mHost, mSensorPrivacyManager, mKeyguard,
+ mock(ActivityStarter.class));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index 894ef3d..425ca58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -57,7 +57,7 @@
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationListContainer mListContainer;
@Mock
- private NotificationEntryListener mEntryManagerCallback;
+ private NotificationEntryListener mEntryListener;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private RemoteInputController.Delegate mDelegate;
@Mock private NotificationRemoteInputManager.Callback mRemoteInputManagerCallback;
@@ -87,8 +87,8 @@
NotificationViewHierarchyManager viewHierarchyManager =
Dependency.get(NotificationViewHierarchyManager.class);
Dependency.get(InitController.class).executePostInitTasks();
- entryManager.setUpWithPresenter(mPresenter, mListContainer, mEntryManagerCallback,
- mHeadsUpManager);
+ entryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
+ entryManager.addNotificationEntryListener(mEntryListener);
gutsManager.setUpWithPresenter(mPresenter, mListContainer,
mCheckSaveListener, mOnSettingsClickListener);
notificationLogger.setUpWithContainer(mListContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index bee931f..150dcb9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -20,7 +20,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputActiveExtender;
import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputHistoryExtender;
@@ -28,6 +27,7 @@
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.google.android.collect.Sets;
@@ -37,6 +37,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import dagger.Lazy;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -66,14 +68,11 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
- mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
- mLockscreenUserManager);
- mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
- mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
- Handler.createAsync(Looper.myLooper()));
- mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext);
+ mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext,
+ mLockscreenUserManager, mSmartReplyController, mEntryManager,
+ () -> mock(ShadeController.class),
+ Handler.createAsync(Looper.myLooper()));
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
0, new Notification(), UserHandle.CURRENT, null, 0);
mEntry = new NotificationData.Entry(mSbn);
@@ -90,7 +89,7 @@
@Test
public void testPerformOnRemoveNotification() {
when(mController.isRemoteInputActive(mEntry)).thenReturn(true);
- mRemoteInputManager.onPerformRemoveNotification(mSbn, mEntry);
+ mRemoteInputManager.onPerformRemoveNotification(mEntry, mSbn.getKey());
verify(mController).removeRemoteInput(mEntry, null);
}
@@ -196,8 +195,15 @@
private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {
- public TestableNotificationRemoteInputManager(Context context) {
- super(context);
+
+ TestableNotificationRemoteInputManager(Context context,
+ NotificationLockscreenUserManager lockscreenUserManager,
+ SmartReplyController smartReplyController,
+ NotificationEntryManager notificationEntryManager,
+ Lazy<ShadeController> shadeController,
+ Handler mainHandler) {
+ super(context, lockscreenUserManager, smartReplyController, notificationEntryManager,
+ shadeController, mainHandler);
}
public void setUpWithPresenterForTest(Callback callback,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 14e611a..e7a1f05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -19,10 +19,13 @@
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
import android.app.Notification;
+import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
@@ -35,6 +38,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import org.junit.Before;
import org.junit.Test;
@@ -70,13 +74,16 @@
MockitoAnnotations.initMocks(this);
mDependency.injectTestDependency(NotificationEntryManager.class,
mNotificationEntryManager);
- mDependency.injectTestDependency(IStatusBarService.class, mIStatusBarService);
- mSmartReplyController = new SmartReplyController();
+ mSmartReplyController = new SmartReplyController(mNotificationEntryManager,
+ mIStatusBarService);
mDependency.injectTestDependency(SmartReplyController.class,
mSmartReplyController);
- mRemoteInputManager = new NotificationRemoteInputManager(mContext);
+ mRemoteInputManager = new NotificationRemoteInputManager(mContext,
+ mock(NotificationLockscreenUserManager.class), mSmartReplyController,
+ mNotificationEntryManager, () -> mock(ShadeController.class),
+ Handler.createAsync(Looper.myLooper()));
mRemoteInputManager.setUpWithCallback(mCallback, mDelegate);
mNotification = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 701ea7d..cb02dc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -61,7 +61,6 @@
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.RemoteInputController;
@@ -104,7 +103,7 @@
@Mock private ExpandableNotificationRow mRow;
@Mock private NotificationListContainer mListContainer;
@Mock
- private NotificationEntryListener mCallback;
+ private NotificationEntryListener mEntryListener;
@Mock
private NotificationRowBinder.BindRowCallback mBindCallback;
@Mock private HeadsUpManager mHeadsUpManager;
@@ -118,7 +117,6 @@
@Mock private NotificationGroupManager mGroupManager;
@Mock private NotificationGutsManager mGutsManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
- @Mock private NotificationMediaManager mMediaManager;
@Mock private NotificationListener mNotificationListener;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private VisualStabilityManager mVisualStabilityManager;
@@ -204,7 +202,6 @@
mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager);
mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager);
- mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
mDependency.injectTestDependency(DeviceProvisionedController.class,
mDeviceProvisionedController);
@@ -232,7 +229,8 @@
mEntryManager = new TestableNotificationEntryManager(mContext, mBarService);
Dependency.get(InitController.class).executePostInitTasks();
- mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mCallback, mHeadsUpManager);
+ mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
+ mEntryManager.addNotificationEntryListener(mEntryListener);
NotificationRowBinder notificationRowBinder = Dependency.get(NotificationRowBinder.class);
notificationRowBinder.setUpWithPresenter(
@@ -272,7 +270,7 @@
verify(mRemoteInputManager).bindRow(entry.getRow());
// Row content inflation:
- verify(mCallback).onNotificationAdded(entry);
+ verify(mEntryListener).onNotificationAdded(entry);
verify(mPresenter).updateNotificationViews();
assertEquals(mEntryManager.getNotificationData().get(mSbn.getKey()), entry);
@@ -300,7 +298,7 @@
verify(mPresenter).updateNotificationViews();
verify(mForegroundServiceController).updateNotification(eq(mSbn), anyInt());
- verify(mCallback).onNotificationUpdated(mSbn);
+ verify(mEntryListener).onEntryUpdated(mEntry);
assertNotNull(mEntry.getRow());
assertEquals(mEntry.userSentiment,
NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
@@ -318,11 +316,11 @@
verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
any(), anyInt());
- verify(mMediaManager).onNotificationRemoved(mSbn.getKey());
verify(mForegroundServiceController).removeNotification(mSbn);
verify(mListContainer).cleanUpViewStateForEntry(mEntry);
verify(mPresenter).updateNotificationViews();
- verify(mCallback).onNotificationRemoved(mSbn.getKey(), mSbn);
+ verify(mEntryListener).onEntryRemoved(mEntry, mSbn.getKey(), mSbn,
+ false /* lifetimeExtended */, false /* removedByUser */);
verify(mRow).setRemoved();
assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
@@ -346,6 +344,8 @@
assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
verify(extender).setShouldManageLifetime(mEntry, true /* shouldManage */);
+ verify(mEntryListener).onEntryRemoved(mEntry, mSbn.getKey(), null,
+ true /* lifetimeExtended */, false /* removedByUser */);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index f190979..6fbd8c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -16,28 +16,31 @@
package com.android.systemui.statusbar.notification;
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.service.notification.StatusBarNotification;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class VisualStabilityManagerTest extends SysuiTestCase {
- private VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager();
+ private VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager(
+ mock(NotificationEntryManager.class));
private VisualStabilityManager.Callback mCallback = mock(VisualStabilityManager.Callback.class);
private VisibilityLocationProvider mLocationProvider = mock(VisibilityLocationProvider.class);
private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class);
@@ -45,6 +48,7 @@
@Before
public void setUp() {
+ mVisualStabilityManager.setUpWithPresenter(mock(NotificationPresenter.class));
mVisualStabilityManager.setVisibilityLocationProvider(mLocationProvider);
mEntry = new NotificationData.Entry(mock(StatusBarNotification.class));
mEntry.setRow(mRow);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 512acd0..caa3ca6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -36,9 +37,12 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -91,7 +95,8 @@
mEntry = new NotificationData.Entry(mSbn);
mEntry.setRow(mRow);
- mLogger = new TestableNotificationLogger(mBarService);
+ mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
+ mEntryManager, mock(StatusBarStateController.class), mBarService);
mLogger.setUpWithContainer(mListContainer);
}
@@ -153,7 +158,12 @@
private class TestableNotificationLogger extends NotificationLogger {
- public TestableNotificationLogger(IStatusBarService barService) {
+ public TestableNotificationLogger(NotificationListener notificationListener,
+ UiOffloadThread uiOffloadThread,
+ NotificationEntryManager entryManager,
+ StatusBarStateController statusBarStateController,
+ IStatusBarService barService) {
+ super(notificationListener, uiOffloadThread, entryManager, statusBarStateController);
mBarService = barService;
// Make this on the current thread so we can wait for it during tests.
mHandler = Handler.createAsync(Looper.myLooper());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index b4f99c4..b8c7ee09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -130,7 +130,7 @@
mContext);
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
Dependency.get(InitController.class).executePostInitTasks();
- mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, null, mHeadsUpManager,
+ mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager,
mNotificationData);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 728723b4..babd452 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -40,7 +40,6 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import org.junit.Before;
import org.junit.Test;
@@ -105,7 +104,7 @@
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
DeviceProvisionedController deviceProvisionedController =
- new DeviceProvisionedControllerImpl(context);
+ mock(DeviceProvisionedController.class);
assertNotNull(mAccessibilityWrapper);
return new NavigationBarFragment(mAccessibilityWrapper,
deviceProvisionedController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index 490288e..916232b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -237,7 +237,7 @@
mGroupManager.onEntryAdded(summaryEntry);
mGroupManager.onEntryAdded(childEntry);
- mNotificationEntryListener.onEntryRemoved(childEntry);
+ mNotificationEntryListener.onEntryRemoved(childEntry, childEntry.key, null, false, false);
assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 0bc304e..146c5d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -220,9 +220,9 @@
mScrimController.transitionTo(ScrimState.PULSING);
mScrimController.finishAnimationsImmediately();
// Front scrim should be transparent
- // Back scrim should be visible with tint
+ // Back scrim should be semi-transparent so the user can see the wallpaper
// Pulse callback should have been invoked
- assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
assertScrimTint(mScrimBehind, true /* tinted */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 02f8949..4fabe7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -37,6 +37,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -70,7 +71,8 @@
mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
statusBarWindowView, mock(NotificationListContainerViewGroup.class),
mock(DozeScrimController.class), mock(ScrimController.class),
- mock(ActivityLaunchAnimator.class), mock(StatusBarKeyguardViewManager.class));
+ mock(ActivityLaunchAnimator.class), mock(StatusBarKeyguardViewManager.class),
+ mock(NotificationAlertingManager.class));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index c584d02..e80694c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -67,7 +67,9 @@
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.InitController;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiOffloadThread;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.appops.AppOpsControllerImpl;
import com.android.systemui.assist.AssistManager;
@@ -90,6 +92,7 @@
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -148,10 +151,12 @@
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private NotificationPresenter mNotificationPresenter;
@Mock
- private NotificationEntryListener mCallback;
+ private NotificationEntryListener mEntryListener;
@Mock private BubbleController mBubbleController;
@Mock
private NotificationFilter mNotificationFilter;
+ @Mock
+ private NotificationAlertingManager mNotificationAlertingManager;
private TestableStatusBar mStatusBar;
private FakeMetricsLogger mMetricsLogger;
@@ -179,6 +184,8 @@
mDeviceProvisionedController);
mDependency.injectMockDependency(BubbleController.class);
mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter);
+ mDependency.injectTestDependency(NotificationAlertingManager.class,
+ mNotificationAlertingManager);
IPowerManager powerManagerService = mock(IPowerManager.class);
mPowerManager = new PowerManager(mContext, powerManagerService,
@@ -195,8 +202,10 @@
mMetricsLogger = new FakeMetricsLogger();
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
+ mEntryManager = new TestableNotificationEntryManager(mPowerManager, mContext);
+ mNotificationLogger = new NotificationLogger(mNotificationListener,
+ Dependency.get(UiOffloadThread.class), mEntryManager, mStatusBarStateController);
mDependency.injectTestDependency(NotificationLogger.class, mNotificationLogger);
- mNotificationLogger = new NotificationLogger();
DozeLog.traceDozing(mContext, false /* dozing */);
mCommandQueue = mock(CommandQueue.class);
@@ -225,7 +234,6 @@
mNotificationInterruptionStateProvider.setUpWithPresenter(mNotificationPresenter,
mHeadsUpManager, mHeadsUpSuppressor);
- mEntryManager = new TestableNotificationEntryManager(mPowerManager, mContext);
when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
@@ -240,10 +248,14 @@
mock(BubbleController.class));
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
+ SystemUIFactory.getInstance().getRootComponent()
+ .getStatusBarInjector()
+ .createStatusBar(mStatusBar);
mStatusBar.putComponent(StatusBar.class, mStatusBar);
Dependency.get(InitController.class).executePostInitTasks();
mEntryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
- mCallback, mHeadsUpManager, mNotificationData);
+ mHeadsUpManager, mNotificationData);
+ mEntryManager.addNotificationEntryListener(mEntryListener);
mNotificationLogger.setUpWithContainer(mStackScroller);
TestableLooper.get(this).setMessageHandler(m -> {
@@ -747,10 +759,9 @@
public void setUpForTest(NotificationPresenter presenter,
NotificationListContainer listContainer,
- NotificationEntryListener callback,
HeadsUpManagerPhone headsUpManager,
NotificationData notificationData) {
- super.setUpWithPresenter(presenter, listContainer, callback, headsUpManager);
+ super.setUpWithPresenter(presenter, listContainer, headsUpManager);
mNotificationData = notificationData;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index d54c295..e626d08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Intent;
@@ -26,6 +27,7 @@
import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.power.EnhancedEstimates;
import org.junit.Assert;
import org.junit.Before;
@@ -47,7 +49,8 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mBatteryController = new BatteryControllerImpl(getContext(), mPowerManager);
+ mBatteryController = new BatteryControllerImpl(getContext(), mock(EnhancedEstimates.class),
+ mPowerManager);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index d246350..b65b0f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -74,7 +74,8 @@
.thenReturn(mock(LocalBluetoothProfileManager.class));
mBluetoothControllerImpl = new BluetoothControllerImpl(mContext,
- mTestableLooper.getLooper());
+ mTestableLooper.getLooper(),
+ mMockBluetoothManager);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
index 3b47eae..e3a41be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
@@ -29,6 +29,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.Before;
import org.junit.Test;
@@ -49,7 +50,8 @@
mCommandQueue = mock(CommandQueue.class);
mContext.putComponent(CommandQueue.class, mCommandQueue);
- mRemoteInputQuickSettingsDisabler = new RemoteInputQuickSettingsDisabler(mContext);
+ mRemoteInputQuickSettingsDisabler = new RemoteInputQuickSettingsDisabler(mContext,
+ mock(ConfigurationController.class));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index f76de5a..3ac42de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -39,6 +39,8 @@
import android.net.ConnectivityManager.NetworkCallback;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.os.Handler;
+import android.os.Looper;
import android.os.UserManager;
import android.security.IKeyChainService;
import android.support.test.runner.AndroidJUnit4;
@@ -98,7 +100,10 @@
// Wait for callbacks from 1) the CACertLoader and 2) the onUserSwitched() function in the
// constructor of mSecurityController
mStateChangedLatch = new CountDownLatch(2);
- mSecurityController = new SecurityControllerImpl(mContext, this);
+ // TODO: Migrate this test to TestableLooper and use a handler attached
+ // to that.
+ mSecurityController = new SecurityControllerImpl(mContext,
+ new Handler(Looper.getMainLooper()), this);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java b/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java
index 3bfefe7..1e27915 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java
@@ -48,7 +48,9 @@
mView = mock(View.class);
when(mView.getContext()).thenReturn(mContext);
- mTunerService = mDependency.injectMockDependency(TunerService.class);
+ mTunerService = mock(TunerService.class);
+ mDependency.injectTestDependency(TunablePadding.TunablePaddingService.class,
+ new TunablePadding.TunablePaddingService(mTunerService));
Tracker tracker = mLeakCheck.getTracker("tuner");
doAnswer(invocation -> {
tracker.getLeakInfo(invocation.getArguments()[0]).addAllocation(new Throwable());
@@ -118,4 +120,4 @@
mTunablePadding.destroy();
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index dd4afaf..ad08861 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -179,6 +179,7 @@
import java.security.InvalidParameterException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -3077,10 +3078,10 @@
}
}
- @Override
- public void setInputMethod(IBinder token, String id) {
+ @BinderThread
+ private void setInputMethod(IBinder token, String id) {
synchronized (mMethodMap) {
- if (!calledFromValidUserLocked()) {
+ if (!calledWithValidTokenLocked(token)) {
return;
}
setInputMethodWithSubtypeIdLocked(token, id, NOT_A_SUBTYPE_ID);
@@ -4587,6 +4588,25 @@
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
+ final int callingUid = Binder.getCallingUid();
+ // Reject any incoming calls from non-shell users, including ones from the system user.
+ if (callingUid != Process.ROOT_UID && callingUid != Process.SHELL_UID) {
+ // Note that Binder#onTransact() will automatically close "in", "out", and "err" when
+ // returned from this method, hence there is no need to close those FDs.
+ // "resultReceiver" is the only thing that needs to be taken care of here.
+ if (resultReceiver != null) {
+ resultReceiver.send(ShellCommandResult.FAILURE, null);
+ }
+ final String errorMsg = "InputMethodManagerService does not support shell commands from"
+ + " non-shell users. callingUid=" + callingUid
+ + " args=" + Arrays.toString(args);
+ if (Process.isCoreUid(callingUid)) {
+ // Let's not crash the calling process if the caller is one of core components.
+ Slog.e(TAG, errorMsg);
+ return;
+ }
+ throw new SecurityException(errorMsg);
+ }
new ShellCommandImpl(this).exec(
this, in, out, err, args, callback, resultReceiver);
}
@@ -4599,10 +4619,30 @@
mService = service;
}
+ @RequiresPermission(allOf = {
+ Manifest.permission.WRITE_SECURE_SETTINGS,
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL})
@BinderThread
@ShellCommandResult
@Override
public int onCommand(@Nullable String cmd) {
+ // For shell command, require all the permissions here in favor of code simplicity.
+ mService.mContext.enforceCallingPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+ mService.mContext.enforceCallingPermission(
+ Manifest.permission.WRITE_SECURE_SETTINGS, null);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return onCommandWithSystemIdentity(cmd);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @BinderThread
+ @ShellCommandResult
+ private int onCommandWithSystemIdentity(@Nullable String cmd) {
if ("refresh_debug_properties".equals(cmd)) {
return refreshDebugProperties();
}
@@ -4747,25 +4787,13 @@
*/
@BinderThread
@ShellCommandResult
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
private int handleShellCommandEnableDisableInputMethod(
@NonNull ShellCommand shellCommand, boolean enabled) {
final String id = shellCommand.getNextArgRequired();
final boolean previouslyEnabled;
synchronized (mMethodMap) {
- if (!calledFromValidUserLocked()) {
- shellCommand.getErrPrintWriter().print("Must be called from the foreground user or"
- + " with INTERACT_ACROSS_USERS_FULL");
- return ShellCommandResult.FAILURE;
- }
- mContext.enforceCallingPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null);
- final long ident = Binder.clearCallingIdentity();
- try {
- previouslyEnabled = setInputMethodEnabledLocked(id, enabled);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ previouslyEnabled = setInputMethodEnabledLocked(id, enabled);
}
final PrintWriter pr = shellCommand.getOutPrintWriter();
pr.print("Input method ");
@@ -4785,7 +4813,9 @@
@ShellCommandResult
private int handleShellCommandSetInputMethod(@NonNull ShellCommand shellCommand) {
final String id = shellCommand.getNextArgRequired();
- setInputMethod(null, id);
+ synchronized (mMethodMap) {
+ setInputMethodLocked(id, NOT_A_SUBTYPE_ID);
+ }
final PrintWriter pr = shellCommand.getOutPrintWriter();
pr.print("Input method ");
pr.print(id);
@@ -4800,55 +4830,29 @@
*/
@BinderThread
@ShellCommandResult
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
private int handleShellCommandResetInputMethod(@NonNull ShellCommand shellCommand) {
synchronized (mMethodMap) {
- if (!calledFromValidUserLocked()) {
- shellCommand.getErrPrintWriter().print("Must be called from the foreground user or"
- + " with INTERACT_ACROSS_USERS_FULL");
- return ShellCommandResult.FAILURE;
- }
- mContext.enforceCallingPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null);
final String nextIme;
final List<InputMethodInfo> nextEnabledImes;
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mMethodMap) {
- hideCurrentInputLocked(0, null);
- unbindCurrentMethodLocked();
- // Reset the current IME
- resetSelectedInputMethodAndSubtypeLocked(null);
- // Also reset the settings of the current IME
- mSettings.putSelectedInputMethod(null);
- // Disable all enabled IMEs.
- {
- final ArrayList<InputMethodInfo> enabledImes =
- mSettings.getEnabledInputMethodListLocked();
- final int N = enabledImes.size();
- for (int i = 0; i < N; ++i) {
- setInputMethodEnabledLocked(enabledImes.get(i).getId(), false);
- }
- }
- // Re-enable with default enabled IMEs.
- {
- final ArrayList<InputMethodInfo> defaultEnabledIme =
- InputMethodUtils.getDefaultEnabledImes(mContext, mMethodList);
- final int N = defaultEnabledIme.size();
- for (int i = 0; i < N; ++i) {
- setInputMethodEnabledLocked(defaultEnabledIme.get(i).getId(), true);
- }
- }
- updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
- InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
- mSettings.getEnabledInputMethodListLocked(),
- mSettings.getCurrentUserId(),
- mContext.getBasePackageName());
- nextIme = mSettings.getSelectedInputMethod();
- nextEnabledImes = getEnabledInputMethodList();
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ hideCurrentInputLocked(0, null);
+ unbindCurrentMethodLocked();
+ // Reset the current IME
+ resetSelectedInputMethodAndSubtypeLocked(null);
+ // Also reset the settings of the current IME
+ mSettings.putSelectedInputMethod(null);
+ // Disable all enabled IMEs.
+ mSettings.getEnabledInputMethodListLocked().forEach(
+ imi -> setInputMethodEnabledLocked(imi.getId(), false));
+ // Re-enable with default enabled IMEs.
+ InputMethodUtils.getDefaultEnabledImes(mContext, mMethodList).forEach(
+ imi -> setInputMethodEnabledLocked(imi.getId(), true));
+ updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
+ InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
+ mSettings.getEnabledInputMethodListLocked(),
+ mSettings.getCurrentUserId(),
+ mContext.getBasePackageName());
+ nextIme = mSettings.getSelectedInputMethod();
+ nextEnabledImes = getEnabledInputMethodList();
final PrintWriter pr = shellCommand.getOutPrintWriter();
pr.println("Reset current and enabled IMEs");
pr.println("Newly selected IME:");
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index ffe14d9f..98ed3ea 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1513,12 +1513,6 @@
@BinderThread
@Override
- public void setInputMethod(IBinder token, String id) {
- reportNotSupported();
- }
-
- @BinderThread
- @Override
public void registerSuggestionSpansForNotification(SuggestionSpan[] suggestionSpans) {
reportNotSupported();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 90619e2..2ef3315 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15461,10 +15461,15 @@
return result;
}
+ /**
+ * Compare the newly scanned package with current system state to see which of its declared
+ * shared libraries should be allowed to be added to the system.
+ */
private static List<SharedLibraryInfo> getAllowedSharedLibInfos(
ScanResult scanResult,
Map<String, LongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
- final PackageParser.Package pkg = scanResult.pkgSetting.pkg;
+ // Let's used the parsed package as scanResult.pkgSetting may be null
+ final PackageParser.Package pkg = scanResult.request.pkg;
if (scanResult.staticSharedLibraryInfo == null
&& scanResult.dynamicSharedLibraryInfos == null) {
return null;
@@ -15496,8 +15501,12 @@
// have allowed apps on the device which aren't compatible
// with it. Better to just have the restriction here, be
// conservative, and create many fewer cases that can negatively
- // impact the user experience.
- final PackageSetting sysPs = scanResult.request.disabledPkgSetting;
+ // impact the user experience. We may not yet have disabled the
+ // updated package yet, so be sure to grab the current setting if
+ // that's the case.
+ final PackageSetting sysPs = scanResult.request.disabledPkgSetting == null
+ ? scanResult.request.oldPkgSetting
+ : scanResult.request.disabledPkgSetting;
if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
for (int j = 0; j < sysPs.pkg.libraryNames.size(); j++) {
if (name.equals(sysPs.pkg.libraryNames.get(j))) {
diff --git a/services/core/java/com/android/server/security/VerityUtils.java b/services/core/java/com/android/server/security/VerityUtils.java
index 514dfed..667d21d 100644
--- a/services/core/java/com/android/server/security/VerityUtils.java
+++ b/services/core/java/com/android/server/security/VerityUtils.java
@@ -16,13 +16,11 @@
package com.android.server.security;
-import static android.system.OsConstants.PROT_READ;
-import static android.system.OsConstants.PROT_WRITE;
-
import android.annotation.NonNull;
import android.os.SharedMemory;
import android.system.ErrnoException;
import android.system.Os;
+import android.system.OsConstants;
import android.util.Pair;
import android.util.Slog;
import android.util.apk.ApkSignatureVerifier;
@@ -56,6 +54,21 @@
private static final boolean DEBUG = false;
+ /** Returns whether the file has fs-verity enabled. */
+ public static boolean hasFsverity(@NonNull String filePath) {
+ // NB: only measure but not check the actual measurement here. As long as this succeeds,
+ // the file is on readable if the measurement can be verified against a trusted key, and
+ // this is good enough for installed apps.
+ int errno = measureFsverityNative(filePath);
+ if (errno != 0) {
+ if (errno != OsConstants.ENODATA) {
+ Slog.e(TAG, "Failed to measure fs-verity, errno " + errno + ": " + filePath);
+ }
+ return false;
+ }
+ return true;
+ }
+
/**
* Generates Merkle tree and fs-verity metadata.
*
@@ -213,6 +226,7 @@
return md.digest();
}
+ private static native int measureFsverityNative(@NonNull String filePath);
private static native byte[] constructFsveritySignedDataNative(@NonNull byte[] measurement);
private static native byte[] constructFsverityDescriptorNative(long fileSize);
private static native byte[] constructFsverityExtensionNative(short extensionId,
@@ -249,7 +263,7 @@
if (shm == null) {
throw new IllegalStateException("Failed to generate verity tree into shared memory");
}
- if (!shm.setProtect(PROT_READ)) {
+ if (!shm.setProtect(OsConstants.PROT_READ)) {
throw new SecurityException("Failed to set up shared memory correctly");
}
return Pair.create(shm, contentSize);
@@ -323,7 +337,7 @@
throw new IllegalStateException("Multiple instantiation from this factory");
}
mShm = SharedMemory.create("apkverity", capacity);
- if (!mShm.setProtect(PROT_READ | PROT_WRITE)) {
+ if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) {
throw new SecurityException("Failed to set protection");
}
mBuffer = mShm.mapReadWrite();
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index ec94e3c9..3c87e42 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -20,13 +20,22 @@
#include "jni.h"
#include <utils/Log.h>
+#include <errno.h>
+#include <fcntl.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <android-base/unique_fd.h>
// TODO(112037636): Always include once fsverity.h is upstreamed and backported.
#define HAS_FSVERITY 0
#if HAS_FSVERITY
#include <linux/fsverity.h>
+
+const int kSha256Bytes = 32;
#endif
namespace android {
@@ -66,9 +75,26 @@
jbyte* mElements;
};
+int measureFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
+#if HAS_FSVERITY
+ auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest) + kSha256Bytes);
+ fsverity_digest* data = reinterpret_cast<fsverity_digest*>(raii->getRaw());
+ data->digest_size = kSha256Bytes; // the only input/output parameter
+
+ const char* path = env->GetStringUTFChars(filePath, nullptr);
+ ::android::base::unique_fd rfd(open(path, O_RDONLY));
+ if (ioctl(rfd.get(), FS_IOC_MEASURE_VERITY, data) < 0) {
+ return errno;
+ }
+ return 0;
+#else
+ LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
+ return -1;
+#endif // HAS_FSVERITY
+}
+
jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteArray digest) {
#if HAS_FSVERITY
- const int kSha256Bytes = 32;
auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest_disk) + kSha256Bytes);
fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii->getRaw());
@@ -146,6 +172,7 @@
}
const JNINativeMethod sMethods[] = {
+ { "measureFsverityNative", "(Ljava/lang/String;)I", (void *)measureFsverity },
{ "constructFsveritySignedDataNative", "([B)[B", (void *)constructFsveritySignedData },
{ "constructFsverityDescriptorNative", "(J)[B", (void *)constructFsverityDescriptor },
{ "constructFsverityExtensionNative", "(SI)[B", (void *)constructFsverityExtension },
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1862636..333b3e3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1264,6 +1264,16 @@
}
traceEnd();
+ traceBeginAndSlog("StartNetworkStack");
+ try {
+ final android.net.NetworkStack networkStack =
+ context.getSystemService(android.net.NetworkStack.class);
+ networkStack.start(context);
+ } catch (Throwable e) {
+ reportWtf("starting Network Stack", e);
+ }
+ traceEnd();
+
traceBeginAndSlog("StartNsdService");
try {
serviceDiscovery = NsdService.create(context);
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 598f567..fa19867 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,7 +16,6 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.telephony.cdma.CdmaCellLocation;
@@ -71,30 +70,13 @@
* to 2592000
* @param lat Latitude is a decimal number ranges from -1296000
* to 1296000
- *
- * @hide
- */
- @UnsupportedAppUsage
- public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat) {
- this(nid, sid, bid, lon, lat, null, null);
- }
-
- /**
- * public constructor
- * @param nid Network Id 0..65535
- * @param sid CDMA System Id 0..32767
- * @param bid Base Station Id 0..65535
- * @param lon Longitude is a decimal number ranges from -2592000
- * to 2592000
- * @param lat Latitude is a decimal number ranges from -1296000
- * to 1296000
* @param alphal long alpha Operator Name String or Enhanced Operator Name String
* @param alphas short alpha Operator Name String or Enhanced Operator Name String
*
* @hide
*/
- public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, String alphal,
- String alphas) {
+ public CellIdentityCdma(
+ int nid, int sid, int bid, int lon, int lat, String alphal, String alphas) {
super(TAG, CellInfo.TYPE_CDMA, null, null, alphal, alphas);
mNetworkId = nid;
mSystemId = sid;
@@ -107,6 +89,17 @@
}
}
+ /** @hide */
+ public CellIdentityCdma(android.hardware.radio.V1_0.CellIdentityCdma cid) {
+ this(cid.networkId, cid.systemId, cid.baseStationId, cid.longitude, cid.latitude, "", "");
+ }
+
+ /** @hide */
+ public CellIdentityCdma(android.hardware.radio.V1_2.CellIdentityCdma cid) {
+ this(cid.base.networkId, cid.base.systemId, cid.base.baseStationId, cid.base.longitude,
+ cid.base.latitude, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort);
+ }
+
private CellIdentityCdma(CellIdentityCdma cid) {
this(cid.mNetworkId, cid.mSystemId, cid.mBasestationId, cid.mLongitude, cid.mLatitude,
cid.mAlphaLong, cid.mAlphaShort);
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index c8a899b..9a24e47 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -36,10 +36,8 @@
// 16-bit GSM Cell Identity described in TS 27.007, 0..65535
private final int mCid;
// 16-bit GSM Absolute RF Channel Number
- @UnsupportedAppUsage
private final int mArfcn;
// 6-bit Base Station Identity Code
- @UnsupportedAppUsage
private final int mBsic;
/**
@@ -53,34 +51,6 @@
mArfcn = CellInfo.UNAVAILABLE;
mBsic = CellInfo.UNAVAILABLE;
}
- /**
- * public constructor
- * @param mcc 3-digit Mobile Country Code, 0..999
- * @param mnc 2 or 3-digit Mobile Network Code, 0..999
- * @param lac 16-bit Location Area Code, 0..65535
- * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
- *
- * @hide
- */
- public CellIdentityGsm(int mcc, int mnc, int lac, int cid) {
- this(lac, cid, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
- String.valueOf(mcc), String.valueOf(mnc), null, null);
- }
-
- /**
- * public constructor
- * @param mcc 3-digit Mobile Country Code, 0..999
- * @param mnc 2 or 3-digit Mobile Network Code, 0..999
- * @param lac 16-bit Location Area Code, 0..65535
- * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
- * @param arfcn 16-bit GSM Absolute RF Channel Number
- * @param bsic 6-bit Base Station Identity Code
- *
- * @hide
- */
- public CellIdentityGsm(int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
- this(lac, cid, arfcn, bsic, String.valueOf(mcc), String.valueOf(mnc), null, null);
- }
/**
* public constructor
@@ -101,9 +71,21 @@
mLac = lac;
mCid = cid;
mArfcn = arfcn;
- // In RIL BSIC is a UINT8, so 0xFF is the 'INVALID' designator
- // for inbound parcels
- mBsic = (bsic == 0xFF) ? CellInfo.UNAVAILABLE : bsic;
+ mBsic = bsic;
+ }
+
+ /** @hide */
+ public CellIdentityGsm(android.hardware.radio.V1_0.CellIdentityGsm cid) {
+ this(cid.lac, cid.cid, cid.arfcn,
+ cid.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.bsic,
+ cid.mcc, cid.mnc, "", "");
+ }
+
+ /** @hide */
+ public CellIdentityGsm(android.hardware.radio.V1_2.CellIdentityGsm cid) {
+ this(cid.base.lac, cid.base.cid, cid.base.arfcn,
+ cid.base.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.base.bsic, cid.base.mcc,
+ cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort);
}
private CellIdentityGsm(CellIdentityGsm cid) {
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 8e1877d..d957d07 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -38,7 +38,6 @@
// 16-bit tracking area code
private final int mTac;
// 18-bit Absolute RF Channel Number
- @UnsupportedAppUsage
private final int mEarfcn;
// cell bandwidth, in kHz
private final int mBandwidth;
@@ -74,22 +73,6 @@
/**
*
- * @param mcc 3-digit Mobile Country Code, 0..999
- * @param mnc 2 or 3-digit Mobile Network Code, 0..999
- * @param ci 28-bit Cell Identity
- * @param pci Physical Cell Id 0..503
- * @param tac 16-bit Tracking Area Code
- * @param earfcn 18-bit LTE Absolute RF Channel Number
- *
- * @hide
- */
- public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
- this(ci, pci, tac, earfcn, CellInfo.UNAVAILABLE, String.valueOf(mcc), String.valueOf(mnc),
- null, null);
- }
-
- /**
- *
* @param ci 28-bit Cell Identity
* @param pci Physical Cell Id 0..503
* @param tac 16-bit Tracking Area Code
@@ -112,6 +95,18 @@
mBandwidth = bandwidth;
}
+ /** @hide */
+ public CellIdentityLte(android.hardware.radio.V1_0.CellIdentityLte cid) {
+ this(cid.ci, cid.pci, cid.tac, cid.earfcn, CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", "");
+ }
+
+ /** @hide */
+ public CellIdentityLte(android.hardware.radio.V1_2.CellIdentityLte cid) {
+ this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, cid.bandwidth,
+ cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong,
+ cid.operatorNames.alphaShort);
+ }
+
private CellIdentityLte(CellIdentityLte cid) {
this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBandwidth, cid.mMccStr,
cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort);
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index f77c468..3814333 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -51,22 +51,6 @@
}
/**
- * @param mcc 3-digit Mobile Country Code, 0..999
- * @param mnc 2 or 3-digit Mobile Network Code, 0..999
- * @param lac 16-bit Location Area Code, 0..65535, CellInfo.UNAVAILABLE if unknown
- * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, CellInfo.
- * UNAVAILABLE if unknown
- * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, CellInfo.UNAVAILABLE
- * if unknown
- * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
- *
- * @hide
- */
- public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid, int uarfcn) {
- this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid, uarfcn, null, null);
- }
-
- /**
* @param mcc 3-digit Mobile Country Code in string format
* @param mnc 2 or 3-digit Mobile Network Code in string format
* @param lac 16-bit Location Area Code, 0..65535, CellInfo.UNAVAILABLE if unknown
@@ -94,6 +78,17 @@
cid.mCpid, cid.mUarfcn, cid.mAlphaLong, cid.mAlphaShort);
}
+ /** @hide */
+ public CellIdentityTdscdma(android.hardware.radio.V1_0.CellIdentityTdscdma cid) {
+ this(cid.mcc, cid.mnc, cid.lac, cid.cid, cid.cpid, CellInfo.UNAVAILABLE, "", "");
+ }
+
+ /** @hide */
+ public CellIdentityTdscdma(android.hardware.radio.V1_2.CellIdentityTdscdma cid) {
+ this(cid.base.mcc, cid.base.mnc, cid.base.lac, cid.base.cid, cid.base.cpid,
+ cid.uarfcn, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort);
+ }
+
CellIdentityTdscdma copy() {
return new CellIdentityTdscdma(this);
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 31f9e6d..6e09784 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -51,35 +51,6 @@
mPsc = CellInfo.UNAVAILABLE;
mUarfcn = CellInfo.UNAVAILABLE;
}
- /**
- * public constructor
- * @param mcc 3-digit Mobile Country Code, 0..999
- * @param mnc 2 or 3-digit Mobile Network Code, 0..999
- * @param lac 16-bit Location Area Code, 0..65535
- * @param cid 28-bit UMTS Cell Identity
- * @param psc 9-bit UMTS Primary Scrambling Code
- *
- * @hide
- */
- public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc) {
- this(lac, cid, psc, CellInfo.UNAVAILABLE, String.valueOf(mcc), String.valueOf(mnc),
- null, null);
- }
-
- /**
- * public constructor
- * @param mcc 3-digit Mobile Country Code, 0..999
- * @param mnc 2 or 3-digit Mobile Network Code, 0..999
- * @param lac 16-bit Location Area Code, 0..65535
- * @param cid 28-bit UMTS Cell Identity
- * @param psc 9-bit UMTS Primary Scrambling Code
- * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
- *
- * @hide
- */
- public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc, int uarfcn) {
- this(lac, cid, psc, uarfcn, String.valueOf(mcc), String.valueOf(mnc), null, null);
- }
/**
* public constructor
@@ -103,6 +74,18 @@
mUarfcn = uarfcn;
}
+ /** @hide */
+ public CellIdentityWcdma(android.hardware.radio.V1_0.CellIdentityWcdma cid) {
+ this(cid.lac, cid.cid, cid.psc, cid.uarfcn, cid.mcc, cid.mnc, "", "");
+ }
+
+ /** @hide */
+ public CellIdentityWcdma(android.hardware.radio.V1_2.CellIdentityWcdma cid) {
+ this(cid.base.lac, cid.base.cid, cid.base.psc, cid.base.uarfcn,
+ cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong,
+ cid.operatorNames.alphaShort);
+ }
+
private CellIdentityWcdma(CellIdentityWcdma cid) {
this(cid.mLac, cid.mCid, cid.mPsc, cid.mUarfcn, cid.mMccStr,
cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index d0b26876..b761bd7 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -132,7 +132,8 @@
/** Connection status is unknown. */
public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;
- private int mCellConnectionStatus = CONNECTION_NONE;
+ /** A cell connection status */
+ private int mCellConnectionStatus;
// True if device is mRegistered to the mobile network
private boolean mRegistered;
@@ -144,6 +145,7 @@
protected CellInfo() {
this.mRegistered = false;
this.mTimeStamp = Long.MAX_VALUE;
+ mCellConnectionStatus = CONNECTION_NONE;
}
/** @hide */
@@ -300,4 +302,44 @@
return new CellInfo[size];
}
};
+
+ /** @hide */
+ protected CellInfo(android.hardware.radio.V1_0.CellInfo ci) {
+ this.mRegistered = ci.registered;
+ this.mTimeStamp = ci.timeStamp;
+ this.mCellConnectionStatus = CONNECTION_UNKNOWN;
+ }
+
+ /** @hide */
+ protected CellInfo(android.hardware.radio.V1_2.CellInfo ci) {
+ this.mRegistered = ci.registered;
+ this.mTimeStamp = ci.timeStamp;
+ this.mCellConnectionStatus = ci.connectionStatus;
+ }
+
+ /** @hide */
+ public static CellInfo create(android.hardware.radio.V1_0.CellInfo ci) {
+ if (ci == null) return null;
+ switch(ci.cellInfoType) {
+ case android.hardware.radio.V1_0.CellInfoType.GSM: return new CellInfoGsm(ci);
+ case android.hardware.radio.V1_0.CellInfoType.CDMA: return new CellInfoCdma(ci);
+ case android.hardware.radio.V1_0.CellInfoType.LTE: return new CellInfoLte(ci);
+ case android.hardware.radio.V1_0.CellInfoType.WCDMA: return new CellInfoWcdma(ci);
+ case android.hardware.radio.V1_0.CellInfoType.TD_SCDMA: return new CellInfoTdscdma(ci);
+ default: return null;
+ }
+ }
+
+ /** @hide */
+ public static CellInfo create(android.hardware.radio.V1_2.CellInfo ci) {
+ if (ci == null) return null;
+ switch(ci.cellInfoType) {
+ case android.hardware.radio.V1_0.CellInfoType.GSM: return new CellInfoGsm(ci);
+ case android.hardware.radio.V1_0.CellInfoType.CDMA: return new CellInfoCdma(ci);
+ case android.hardware.radio.V1_0.CellInfoType.LTE: return new CellInfoLte(ci);
+ case android.hardware.radio.V1_0.CellInfoType.WCDMA: return new CellInfoWcdma(ci);
+ case android.hardware.radio.V1_0.CellInfoType.TD_SCDMA: return new CellInfoTdscdma(ci);
+ default: return null;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index f67733d..8c76eae 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -48,6 +48,24 @@
this.mCellSignalStrengthCdma = ci.mCellSignalStrengthCdma.copy();
}
+ /** @hide */
+ public CellInfoCdma(android.hardware.radio.V1_0.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_0.CellInfoCdma cic = ci.cdma.get(0);
+ mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma);
+ mCellSignalStrengthCdma =
+ new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo);
+ }
+
+ /** @hide */
+ public CellInfoCdma(android.hardware.radio.V1_2.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_2.CellInfoCdma cic = ci.cdma.get(0);
+ mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma);
+ mCellSignalStrengthCdma =
+ new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo);
+ }
+
@Override
public CellIdentityCdma getCellIdentity() {
return mCellIdentityCdma;
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 7211de1..ad16dfa 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -43,8 +43,24 @@
/** @hide */
public CellInfoGsm(CellInfoGsm ci) {
super(ci);
- this.mCellIdentityGsm = ci.mCellIdentityGsm.copy();
- this.mCellSignalStrengthGsm = ci.mCellSignalStrengthGsm.copy();
+ mCellIdentityGsm = ci.mCellIdentityGsm.copy();
+ mCellSignalStrengthGsm = ci.mCellSignalStrengthGsm.copy();
+ }
+
+ /** @hide */
+ public CellInfoGsm(android.hardware.radio.V1_0.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_0.CellInfoGsm cig = ci.gsm.get(0);
+ mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm);
+ mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
+ }
+
+ /** @hide */
+ public CellInfoGsm(android.hardware.radio.V1_2.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_2.CellInfoGsm cig = ci.gsm.get(0);
+ mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm);
+ mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
}
@Override
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 7d5388b..8ca6a1a 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -51,6 +51,24 @@
this.mCellConfig = new CellConfigLte(ci.mCellConfig);
}
+ /** @hide */
+ public CellInfoLte(android.hardware.radio.V1_0.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_0.CellInfoLte cil = ci.lte.get(0);
+ mCellIdentityLte = new CellIdentityLte(cil.cellIdentityLte);
+ mCellSignalStrengthLte = new CellSignalStrengthLte(cil.signalStrengthLte);
+ mCellConfig = new CellConfigLte();
+ }
+
+ /** @hide */
+ public CellInfoLte(android.hardware.radio.V1_2.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_2.CellInfoLte cil = ci.lte.get(0);
+ mCellIdentityLte = new CellIdentityLte(cil.cellIdentityLte);
+ mCellSignalStrengthLte = new CellSignalStrengthLte(cil.signalStrengthLte);
+ mCellConfig = new CellConfigLte();
+ }
+
@Override
public CellIdentityLte getCellIdentity() {
if (DBG) log("getCellIdentity: " + mCellIdentityLte);
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index 40cadde..a8c49b7 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -48,8 +48,23 @@
this.mCellSignalStrengthTdscdma = ci.mCellSignalStrengthTdscdma.copy();
}
- @Override
- public CellIdentityTdscdma getCellIdentity() {
+ /** @hide */
+ public CellInfoTdscdma(android.hardware.radio.V1_0.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_0.CellInfoTdscdma cit = ci.tdscdma.get(0);
+ mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma);
+ mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
+ }
+
+ /** @hide */
+ public CellInfoTdscdma(android.hardware.radio.V1_2.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.tdscdma.get(0);
+ mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma);
+ mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
+ }
+
+ @Override public CellIdentityTdscdma getCellIdentity() {
return mCellIdentityTdscdma;
}
/** @hide */
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index 4f9dcb1..a427e80 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -47,6 +47,22 @@
this.mCellSignalStrengthWcdma = ci.mCellSignalStrengthWcdma.copy();
}
+ /** @hide */
+ public CellInfoWcdma(android.hardware.radio.V1_0.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_0.CellInfoWcdma ciw = ci.wcdma.get(0);
+ mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma);
+ mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
+ }
+
+ /** @hide */
+ public CellInfoWcdma(android.hardware.radio.V1_2.CellInfo ci) {
+ super(ci);
+ final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.wcdma.get(0);
+ mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma);
+ mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
+ }
+
@Override
public CellIdentityWcdma getCellIdentity() {
return mCellIdentityWcdma;
diff --git a/telephony/java/android/telephony/ModemInfo.java b/telephony/java/android/telephony/ModemInfo.java
index 564effe..27a5121 100644
--- a/telephony/java/android/telephony/ModemInfo.java
+++ b/telephony/java/android/telephony/ModemInfo.java
@@ -32,6 +32,11 @@
public final boolean isVoiceSupported;
public final boolean isDataSupported;
+ // TODO b/121394331: Clean up this class after V1_1.PhoneCapability cleanup.
+ public ModemInfo(int modemId) {
+ this(modemId, 0, true, true);
+ }
+
public ModemInfo(int modemId, int rat, boolean isVoiceSupported, boolean isDataSupported) {
this.modemId = modemId;
this.rat = rat;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3b2a05b..d8b430f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3196,6 +3196,29 @@
}
/**
+ * Gets information about currently inserted UICCs and eUICCs. See {@link UiccCardInfo} for more
+ * details on the kind of information available.
+ *
+ * @return UiccCardInfo an array of UiccCardInfo objects, representing information on the
+ * currently inserted UICCs and eUICCs.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public UiccCardInfo[] getUiccCardsInfo() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) {
+ return null;
+ }
+ return telephony.getUiccCardsInfo();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Gets all the UICC slots. The objects in the array can be null if the slot info is not
* available, which is possible between phone process starting and getting slot info from modem.
*
diff --git a/telephony/java/android/telephony/UiccCardInfo.aidl b/telephony/java/android/telephony/UiccCardInfo.aidl
new file mode 100644
index 0000000..882c233
--- /dev/null
+++ b/telephony/java/android/telephony/UiccCardInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.telephony;
+
+parcelable UiccCardInfo;
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
new file mode 100644
index 0000000..45e4704
--- /dev/null
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -0,0 +1,156 @@
+/*
+ * 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.telephony;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The UiccCardInfo represents information about a currently inserted UICC or embedded eUICC.
+ * @hide
+ */
+@SystemApi
+public class UiccCardInfo implements Parcelable {
+
+ private final boolean mIsEuicc;
+ private final int mCardId;
+ private final String mEid;
+ private final String mIccId;
+ private final int mSlotIndex;
+
+ public static final Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() {
+ @Override
+ public UiccCardInfo createFromParcel(Parcel in) {
+ return new UiccCardInfo(in);
+ }
+
+ @Override
+ public UiccCardInfo[] newArray(int size) {
+ return new UiccCardInfo[size];
+ }
+ };
+
+ private UiccCardInfo(Parcel in) {
+ mIsEuicc = in.readByte() != 0;
+ mCardId = in.readInt();
+ mEid = in.readString();
+ mIccId = in.readString();
+ mSlotIndex = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByte((byte) (mIsEuicc ? 1 : 0));
+ dest.writeInt(mCardId);
+ dest.writeString(mEid);
+ dest.writeString(mIccId);
+ dest.writeInt(mSlotIndex);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public UiccCardInfo(boolean isEuicc, int cardId, String eid, String iccId, int slotIndex) {
+ this.mIsEuicc = isEuicc;
+ this.mCardId = cardId;
+ this.mEid = eid;
+ this.mIccId = iccId;
+ this.mSlotIndex = slotIndex;
+ }
+
+ /**
+ * Return whether the UiccCardInfo is an eUICC.
+ * @return true if the UICC is an eUICC.
+ */
+ public boolean isEuicc() {
+ return mIsEuicc;
+ }
+
+ /**
+ * Get the card ID of the UICC. See {@link TelephonyManager#getCardIdForDefaultEuicc()} for more
+ * details on card ID.
+ */
+ public int getCardId() {
+ return mCardId;
+ }
+
+ /**
+ * Get the embedded ID (EID) of the eUICC. If the UiccCardInfo is not an eUICC
+ * (see {@link #isEuicc()}), returns null.
+ */
+ public String getEid() {
+ if (!mIsEuicc) {
+ return null;
+ }
+ return mEid;
+ }
+
+ /**
+ * Get the ICCID of the UICC.
+ */
+ public String getIccId() {
+ return mIccId;
+ }
+
+ /**
+ * Gets the slot index for the slot that the UICC is currently inserted in.
+ */
+ public int getSlotIndex() {
+ return mSlotIndex;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ UiccCardInfo that = (UiccCardInfo) obj;
+ return ((mIsEuicc == that.mIsEuicc)
+ && (mCardId == that.mCardId)
+ && (Objects.equals(mEid, that.mEid))
+ && (Objects.equals(mIccId, that.mIccId))
+ && (mSlotIndex == that.mSlotIndex));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mSlotIndex);
+ }
+
+ @Override
+ public String toString() {
+ return "UiccCardInfo (mIsEuicc="
+ + mIsEuicc
+ + ", mCardId="
+ + mCardId
+ + ", mEid="
+ + mEid
+ + ", mIccId="
+ + mIccId
+ + ", mSlotIndex="
+ + mSlotIndex
+ + ")";
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 0fdca5d..96f7a1b 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -24,7 +24,7 @@
/**
* IDLE: ready to start data connection setup, default state
* CONNECTING: state of issued startPppd() but not finish yet
- * SCANNING: data connection fails with one apn but other apns are available
+ * RETRYING: data connection fails with one apn but other apns are available
* ready to start data connection on other apns (before INITING)
* CONNECTED: IP connection is setup
* DISCONNECTING: Connection.disconnect() has been called, but PDP
@@ -34,19 +34,16 @@
*
* getDataConnectionState() maps State to DataState
* FAILED or IDLE : DISCONNECTED
- * RETRYING or CONNECTING or SCANNING: CONNECTING
+ * RETRYING or CONNECTING: CONNECTING
* CONNECTED : CONNECTED or DISCONNECTING
*/
public enum State {
IDLE,
CONNECTING,
- SCANNING,
+ RETRYING,
CONNECTED,
DISCONNECTING,
FAILED,
- RETRYING // After moving retry manager to ApnContext, we'll never enter this state!
- // Todo: Remove this state and other places that use this state and then
- // rename SCANNING to RETRYING.
}
public enum Activity {
@@ -81,7 +78,6 @@
public static final int EVENT_RESTART_RADIO = BASE + 26;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 29;
public static final int EVENT_ICC_CHANGED = BASE + 33;
- public static final int EVENT_DISCONNECT_DC_RETRYING = BASE + 34;
public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35;
public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 36;
public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37;
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 399e255..c5d82c5 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -56,6 +56,7 @@
import java.util.List;
import java.util.Map;
+import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo;
/**
@@ -1494,6 +1495,17 @@
int getCardIdForDefaultEuicc(int subId, String callingPackage);
/**
+ * Gets information about currently inserted UICCs and eUICCs. See {@link UiccCardInfo} for more
+ * details on the kind of information available.
+ *
+ * @return UiccCardInfo an array of UiccCardInfo objects, representing information on the
+ * currently inserted UICCs and eUICCs.
+ *
+ * @hide
+ */
+ UiccCardInfo[] getUiccCardsInfo();
+
+ /**
* Get slot info for all the UICC slots.
* @return UiccSlotInfo array.
* @hide
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index f2cb653..1c103a9 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -498,6 +498,7 @@
int RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA = 203;
int RIL_REQUEST_SET_PREFERRED_DATA_MODEM = 204;
int RIL_REQUEST_EMERGENCY_DIAL = 205;
+ int RIL_REQUEST_GET_PHONE_CAPABILITY = 206;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;