Merge "Update mGlobalBluetoothA2dpOn when active device changed" into pi-dev
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index fcab8c1..c58b91e 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1555,6 +1555,7 @@
private final long[] mRejectTimes;
private final int mDuration;
private final int mProxyUid;
+ private final boolean mRunning;
private final String mProxyPackageName;
public OpEntry(int op, int mode, long time, long rejectTime, int duration,
@@ -1566,12 +1567,13 @@
mTimes[0] = time;
mRejectTimes[0] = rejectTime;
mDuration = duration;
+ mRunning = duration == -1;
mProxyUid = proxyUid;
mProxyPackageName = proxyPackage;
}
public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration,
- int proxyUid, String proxyPackage) {
+ boolean running, int proxyUid, String proxyPackage) {
mOp = op;
mMode = mode;
mTimes = new long[_NUM_UID_STATE];
@@ -1579,10 +1581,16 @@
System.arraycopy(times, 0, mTimes, 0, _NUM_UID_STATE);
System.arraycopy(rejectTimes, 0, mRejectTimes, 0, _NUM_UID_STATE);
mDuration = duration;
+ mRunning = running;
mProxyUid = proxyUid;
mProxyPackageName = proxyPackage;
}
+ public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration,
+ int proxyUid, String proxyPackage) {
+ this(op, mode, times, rejectTimes, duration, duration == -1, proxyUid, proxyPackage);
+ }
+
public int getOp() {
return mOp;
}
@@ -1632,7 +1640,7 @@
}
public boolean isRunning() {
- return mDuration == -1;
+ return mRunning;
}
public int getDuration() {
@@ -1659,6 +1667,7 @@
dest.writeLongArray(mTimes);
dest.writeLongArray(mRejectTimes);
dest.writeInt(mDuration);
+ dest.writeBoolean(mRunning);
dest.writeInt(mProxyUid);
dest.writeString(mProxyPackageName);
}
@@ -1669,6 +1678,7 @@
mTimes = source.createLongArray();
mRejectTimes = source.createLongArray();
mDuration = source.readInt();
+ mRunning = source.readBoolean();
mProxyUid = source.readInt();
mProxyPackageName = source.readString();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 15aedd7..63de8bf 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1664,7 +1664,8 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes at least one form of audio
- * output, such as speakers, audio jack or streaming over bluetooth
+ * output, as defined in the Android Compatibility Definition Document (CDD)
+ * <a href="https://source.android.com/compatibility/android-cdd#7_8_audio">section 7.8 Audio</a>.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 2d8b4d4..c861499 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -43,7 +43,7 @@
DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
DEFAULT_FLAGS.put("settings_data_usage_v2", "true");
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
- DEFAULT_FLAGS.put("settings_systemui_theme", "false");
+ DEFAULT_FLAGS.put("settings_systemui_theme", "true");
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7c814f4..ed67075 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1630,6 +1630,8 @@
contentInsets.top + outsets.top, contentInsets.right + outsets.right,
contentInsets.bottom + outsets.bottom);
}
+ contentInsets = ensureInsetsNonNegative(contentInsets, "content");
+ stableInsets = ensureInsetsNonNegative(stableInsets, "stable");
mLastWindowInsets = new WindowInsets(contentInsets,
null /* windowDecorInsets */, stableInsets,
mContext.getResources().getConfiguration().isScreenRound(),
@@ -1638,6 +1640,17 @@
return mLastWindowInsets;
}
+ private Rect ensureInsetsNonNegative(Rect insets, String kind) {
+ if (insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0) {
+ Log.wtf(mTag, "Negative " + kind + "Insets: " + insets + ", mFirst=" + mFirst);
+ return new Rect(Math.max(0, insets.left),
+ Math.max(0, insets.top),
+ Math.max(0, insets.right),
+ Math.max(0, insets.bottom));
+ }
+ return insets;
+ }
+
void dispatchApplyInsets(View host) {
WindowInsets insets = getWindowInsets(true /* forceConstruct */);
final boolean dispatchCutout = (mWindowAttributes.layoutInDisplayCutoutMode
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 2940079..9171959 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -156,9 +156,12 @@
if (activeServiceSupportsAssistGesture()) {
return getActiveServiceComponentName();
}
-
- Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(false);
+ final SearchManager searchManager =
+ (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+ if (searchManager == null) {
+ return null;
+ }
+ final Intent intent = searchManager.getAssistIntent(false);
PackageManager pm = mContext.getPackageManager();
ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_DEFAULT_ONLY,
userId);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 571878d..4f567d2 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -76,6 +76,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ResolverActivity;
import com.android.internal.app.ResolverActivity.TargetInfo;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -932,7 +933,7 @@
public static final int TARGET_SERVICE = 1;
public static final int TARGET_STANDARD = 2;
- private static final int MAX_SERVICE_TARGETS = 8;
+ private static final int MAX_SERVICE_TARGETS = 4;
private static final int MAX_TARGETS_PER_SERVICE = 4;
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
@@ -1189,123 +1190,20 @@
}
}
- static class RowScale {
- private static final int DURATION = 400;
-
- float mScale;
- ChooserRowAdapter mAdapter;
- private final ObjectAnimator mAnimator;
-
- public static final FloatProperty<RowScale> PROPERTY =
- new FloatProperty<RowScale>("scale") {
- @Override
- public void setValue(RowScale object, float value) {
- object.mScale = value;
- object.mAdapter.notifyDataSetChanged();
- }
-
- @Override
- public Float get(RowScale object) {
- return object.mScale;
- }
- };
-
- public RowScale(@NonNull ChooserRowAdapter adapter, float from, float to) {
- mAdapter = adapter;
- mScale = from;
- if (from == to) {
- mAnimator = null;
- return;
- }
-
- mAnimator = ObjectAnimator.ofFloat(this, PROPERTY, from, to)
- .setDuration(DURATION);
- mAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mAdapter.onAnimationStart();
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- mAdapter.onAnimationEnd();
- }
- });
- }
-
- public RowScale setInterpolator(Interpolator interpolator) {
- if (mAnimator != null) {
- mAnimator.setInterpolator(interpolator);
- }
- return this;
- }
-
- public float get() {
- return mScale;
- }
-
- public void startAnimation() {
- if (mAnimator != null) {
- mAnimator.start();
- }
- }
-
- public void cancelAnimation() {
- if (mAnimator != null) {
- mAnimator.cancel();
- }
- }
- }
-
class ChooserRowAdapter extends BaseAdapter {
private ChooserListAdapter mChooserListAdapter;
private final LayoutInflater mLayoutInflater;
private final int mColumnCount = 4;
- private RowScale[] mServiceTargetScale;
- private final Interpolator mInterpolator;
private int mAnimationCount = 0;
public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
mChooserListAdapter = wrappedAdapter;
mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
- mInterpolator = AnimationUtils.loadInterpolator(ChooserActivity.this,
- android.R.interpolator.decelerate_quint);
-
wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
- final int rcount = getServiceTargetRowCount();
- if (mServiceTargetScale == null
- || mServiceTargetScale.length != rcount) {
- RowScale[] old = mServiceTargetScale;
- int oldRCount = old != null ? old.length : 0;
- mServiceTargetScale = new RowScale[rcount];
- if (old != null && rcount > 0) {
- System.arraycopy(old, 0, mServiceTargetScale, 0,
- Math.min(old.length, rcount));
- }
-
- for (int i = rcount; i < oldRCount; i++) {
- old[i].cancelAnimation();
- }
-
- for (int i = oldRCount; i < rcount; i++) {
- final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
- .setInterpolator(mInterpolator);
- mServiceTargetScale[i] = rs;
- }
-
- // Start the animations in a separate loop.
- // The process of starting animations will result in
- // binding views to set up initial values, and we must
- // have ALL of the new RowScale objects created above before
- // we get started.
- for (int i = oldRCount; i < rcount; i++) {
- mServiceTargetScale[i].startAnimation();
- }
- }
-
notifyDataSetChanged();
}
@@ -1313,39 +1211,10 @@
public void onInvalidated() {
super.onInvalidated();
notifyDataSetInvalidated();
- if (mServiceTargetScale != null) {
- for (RowScale rs : mServiceTargetScale) {
- rs.cancelAnimation();
- }
- }
}
});
}
- private float getRowScale(int rowPosition) {
- final int start = getCallerTargetRowCount();
- final int end = start + getServiceTargetRowCount();
- if (rowPosition >= start && rowPosition < end) {
- return mServiceTargetScale[rowPosition - start].get();
- }
- return 1.f;
- }
-
- public void onAnimationStart() {
- final boolean lock = mAnimationCount == 0;
- mAnimationCount++;
- if (lock) {
- mResolverDrawerLayout.setDismissLocked(true);
- }
- }
-
- public void onAnimationEnd() {
- mAnimationCount--;
- if (mAnimationCount == 0) {
- mResolverDrawerLayout.setDismissLocked(false);
- }
- }
-
@Override
public int getCount() {
return (int) (
@@ -1360,9 +1229,9 @@
(float) mChooserListAdapter.getCallerTargetCount() / mColumnCount);
}
+ // There can be at most one row of service targets.
public int getServiceTargetRowCount() {
- return (int) Math.ceil(
- (float) mChooserListAdapter.getServiceTargetCount() / mColumnCount);
+ return (int) mChooserListAdapter.getServiceTargetCount() == 0 ? 0 : 1;
}
@Override
@@ -1485,8 +1354,7 @@
}
final int oldHeight = holder.row.getLayoutParams().height;
- holder.row.getLayoutParams().height = Math.max(1,
- (int) (holder.measuredRowHeight * getRowScale(rowPosition)));
+ holder.row.getLayoutParams().height = Math.max(1, holder.measuredRowHeight);
if (holder.row.getLayoutParams().height != oldHeight) {
holder.row.requestLayout();
}
@@ -1728,7 +1596,7 @@
final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;
- offset += (int) (height * mChooserRowAdapter.getRowScale(pos));
+ offset += (int) (height);
if (vt >= 0) {
mCachedViewType = vt;
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index d135040..c9a9161 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -100,7 +100,6 @@
super.onFinishInflate();
mMessageContainer = findViewById(R.id.group_message_container);
mSenderName = findViewById(R.id.message_name);
- mSenderName.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR);
mAvatarView = findViewById(R.id.message_icon);
mImageContainer = findViewById(R.id.messaging_group_icon_container);
mSendingSpinner = findViewById(R.id.messaging_group_sending_progress);
@@ -190,73 +189,66 @@
}
public void removeMessage(MessagingMessage messagingMessage) {
- ViewGroup messageParent = (ViewGroup) messagingMessage.getView().getParent();
- messageParent.removeView(messagingMessage.getView());
+ View view = messagingMessage.getView();
+ boolean wasShown = view.isShown();
+ ViewGroup messageParent = (ViewGroup) view.getParent();
+ if (messageParent == null) {
+ return;
+ }
+ messageParent.removeView(view);
Runnable recycleRunnable = () -> {
- messageParent.removeTransientView(messagingMessage.getView());
+ messageParent.removeTransientView(view);
messagingMessage.recycle();
- if (mMessageContainer.getChildCount() == 0
- && mMessageContainer.getTransientViewCount() == 0
- && mImageContainer.getChildCount() == 0) {
- ViewParent parent = getParent();
- if (parent instanceof ViewGroup) {
- ((ViewGroup) parent).removeView(MessagingGroup.this);
- }
- setAvatar(null);
- mAvatarView.setAlpha(1.0f);
- mAvatarView.setTranslationY(0.0f);
- mSenderName.setAlpha(1.0f);
- mSenderName.setTranslationY(0.0f);
- mIsolatedMessage = null;
- mMessages = null;
- sInstancePool.release(MessagingGroup.this);
- }
};
- if (isShown()) {
- messageParent.addTransientView(messagingMessage.getView(), 0);
- performRemoveAnimation(messagingMessage.getView(), recycleRunnable);
- if (mMessageContainer.getChildCount() == 0
- && mImageContainer.getChildCount() == 0) {
- removeGroupAnimated(null);
- }
+ if (wasShown && !MessagingLinearLayout.isGone(view)) {
+ messageParent.addTransientView(view, 0);
+ performRemoveAnimation(view, recycleRunnable);
} else {
recycleRunnable.run();
}
-
}
- private void removeGroupAnimated(Runnable endAction) {
- performRemoveAnimation(mAvatarView, null);
- performRemoveAnimation(mSenderName, null);
- boolean endActionTriggered = false;
- for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
- View child = mMessageContainer.getChildAt(i);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
- final ViewGroup.LayoutParams lp = child.getLayoutParams();
- if (lp instanceof MessagingLinearLayout.LayoutParams
- && ((MessagingLinearLayout.LayoutParams) lp).hide
- && !((MessagingLinearLayout.LayoutParams) lp).visibleBefore) {
- continue;
- }
- Runnable childEndAction = endActionTriggered ? null : endAction;
- performRemoveAnimation(child, childEndAction);
- endActionTriggered = true;
- }
+ public void recycle() {
if (mIsolatedMessage != null) {
- performRemoveAnimation(mIsolatedMessage, !endActionTriggered ? endAction : null);
- endActionTriggered = true;
+ mImageContainer.removeView(mIsolatedMessage);
}
- if (!endActionTriggered && endAction != null) {
- endAction.run();
+ for (int i = 0; i < mMessages.size(); i++) {
+ MessagingMessage message = mMessages.get(i);
+ mMessageContainer.removeView(message.getView());
+ message.recycle();
}
+ setAvatar(null);
+ mAvatarView.setAlpha(1.0f);
+ mAvatarView.setTranslationY(0.0f);
+ mSenderName.setAlpha(1.0f);
+ mSenderName.setTranslationY(0.0f);
+ setAlpha(1.0f);
+ mIsolatedMessage = null;
+ mMessages = null;
+ mAddedMessages.clear();
+ mFirstLayout = true;
+ MessagingPropertyAnimator.recycle(this);
+ sInstancePool.release(MessagingGroup.this);
+ }
+
+ public void removeGroupAnimated(Runnable endAction) {
+ performRemoveAnimation(this, () -> {
+ setAlpha(1.0f);
+ MessagingPropertyAnimator.setToLaidOutPosition(this);
+ if (endAction != null) {
+ endAction.run();
+ }
+ });
}
public void performRemoveAnimation(View message, Runnable endAction) {
- MessagingPropertyAnimator.fadeOut(message, endAction);
- MessagingPropertyAnimator.startLocalTranslationTo(message,
- (int) (-getHeight() * 0.5f), MessagingLayout.FAST_OUT_LINEAR_IN);
+ performRemoveAnimation(message, -message.getHeight(), endAction);
+ }
+
+ private void performRemoveAnimation(View view, int disappearTranslation, Runnable endAction) {
+ MessagingPropertyAnimator.startLocalTranslationTo(view, disappearTranslation,
+ MessagingLayout.FAST_OUT_LINEAR_IN);
+ MessagingPropertyAnimator.fadeOut(view, endAction);
}
public CharSequence getSenderName() {
@@ -341,6 +333,11 @@
}
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
public Icon getAvatarSymbolIfMatching(CharSequence avatarName, String avatarSymbol,
int layoutColor) {
if (mAvatarName.equals(avatarName) && mAvatarSymbol.equals(avatarSymbol)
@@ -458,6 +455,7 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!mAddedMessages.isEmpty()) {
+ final boolean firstLayout = mFirstLayout;
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
@@ -466,7 +464,7 @@
continue;
}
MessagingPropertyAnimator.fadeIn(message.getView());
- if (!mFirstLayout) {
+ if (!firstLayout) {
MessagingPropertyAnimator.startLocalTranslationFrom(message.getView(),
message.getView().getHeight(),
MessagingLayout.LINEAR_OUT_SLOW_IN);
diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java
index 9db74e8..607a3a9 100644
--- a/core/java/com/android/internal/widget/MessagingImageMessage.java
+++ b/core/java/com/android/internal/widget/MessagingImageMessage.java
@@ -170,8 +170,6 @@
public void recycle() {
MessagingMessage.super.recycle();
- setAlpha(1.0f);
- setTranslationY(0);
setImageBitmap(null);
mDrawable = null;
sInstancePool.release(this);
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 03a734d..0fd6109 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -180,8 +180,13 @@
List<MessagingMessage> historicMessages = createMessages(newHistoricMessages,
true /* isHistoric */);
List<MessagingMessage> messages = createMessages(newMessages, false /* isHistoric */);
+
+ ArrayList<MessagingGroup> oldGroups = new ArrayList<>(mGroups);
addMessagesToGroups(historicMessages, messages, showSpinner);
+ // Let's first check which groups were removed altogether and remove them in one animation
+ removeGroups(oldGroups);
+
// Let's remove the remaining messages
mMessages.forEach(REMOVE_MESSAGE);
mHistoricMessages.forEach(REMOVE_MESSAGE);
@@ -193,6 +198,31 @@
updateTitleAndNamesDisplay();
}
+ private void removeGroups(ArrayList<MessagingGroup> oldGroups) {
+ int size = oldGroups.size();
+ for (int i = 0; i < size; i++) {
+ MessagingGroup group = oldGroups.get(i);
+ if (!mGroups.contains(group)) {
+ List<MessagingMessage> messages = group.getMessages();
+ Runnable endRunnable = () -> {
+ mMessagingLinearLayout.removeTransientView(group);
+ group.recycle();
+ };
+
+ boolean wasShown = group.isShown();
+ mMessagingLinearLayout.removeView(group);
+ if (wasShown && !MessagingLinearLayout.isGone(group)) {
+ mMessagingLinearLayout.addTransientView(group, 0);
+ group.removeGroupAnimated(endRunnable);
+ } else {
+ endRunnable.run();
+ }
+ mMessages.removeAll(messages);
+ mHistoricMessages.removeAll(messages);
+ }
+ }
+ }
+
private void updateTitleAndNamesDisplay() {
ArrayMap<CharSequence, String> uniqueNames = new ArrayMap<>();
ArrayMap<Character, CharSequence> uniqueCharacters = new ArrayMap<>();
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 991e3e7..64b1f24 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -163,15 +163,6 @@
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
MessagingChild messagingChild = (MessagingChild) child;
- if (lp.hide) {
- if (shown && lp.visibleBefore) {
- messagingChild.hideAnimated();
- }
- lp.visibleBefore = false;
- continue;
- } else {
- lp.visibleBefore = true;
- }
final int childWidth = child.getMeasuredWidth();
final int childHeight = child.getMeasuredHeight();
@@ -182,6 +173,19 @@
} else {
childLeft = paddingLeft + lp.leftMargin;
}
+ if (lp.hide) {
+ if (shown && lp.visibleBefore) {
+ // We still want to lay out the child to have great animations
+ child.layout(childLeft, childTop, childLeft + childWidth,
+ childTop + lp.lastVisibleHeight);
+ messagingChild.hideAnimated();
+ }
+ lp.visibleBefore = false;
+ continue;
+ } else {
+ lp.visibleBefore = true;
+ lp.lastVisibleHeight = childHeight;
+ }
if (!first) {
childTop += mSpacing;
@@ -228,6 +232,18 @@
return copy;
}
+ public static boolean isGone(View view) {
+ if (view.getVisibility() == View.GONE) {
+ return true;
+ }
+ final ViewGroup.LayoutParams lp = view.getLayoutParams();
+ if (lp instanceof MessagingLinearLayout.LayoutParams
+ && ((MessagingLinearLayout.LayoutParams) lp).hide) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Sets how many lines should be displayed at most
*/
@@ -263,6 +279,7 @@
public boolean hide = false;
public boolean visibleBefore = false;
+ public int lastVisibleHeight;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index ffcb503..74d0aae 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -124,8 +124,7 @@
@Override
default void hideAnimated() {
setIsHidingAnimated(true);
- getGroup().performRemoveAnimation(getState().getHostView(),
- () -> setIsHidingAnimated(false));
+ getGroup().performRemoveAnimation(getView(), () -> setIsHidingAnimated(false));
}
default boolean hasOverlappingRendering() {
@@ -133,7 +132,7 @@
}
default void recycle() {
- getState().reset();
+ getState().recycle();
}
default View getView() {
diff --git a/core/java/com/android/internal/widget/MessagingMessageState.java b/core/java/com/android/internal/widget/MessagingMessageState.java
index ac62472..1ba2b51 100644
--- a/core/java/com/android/internal/widget/MessagingMessageState.java
+++ b/core/java/com/android/internal/widget/MessagingMessageState.java
@@ -72,7 +72,10 @@
return mHostView;
}
- public void reset() {
+ public void recycle() {
+ mHostView.setAlpha(1.0f);
+ mHostView.setTranslationY(0);
+ MessagingPropertyAnimator.recycle(mHostView);
mIsHidingAnimated = false;
mIsHistoric = false;
mGroup = null;
diff --git a/core/java/com/android/internal/widget/MessagingPropertyAnimator.java b/core/java/com/android/internal/widget/MessagingPropertyAnimator.java
index 7c3ab7f..7703cb0 100644
--- a/core/java/com/android/internal/widget/MessagingPropertyAnimator.java
+++ b/core/java/com/android/internal/widget/MessagingPropertyAnimator.java
@@ -31,111 +31,125 @@
* A listener that automatically starts animations when the layout bounds change.
*/
public class MessagingPropertyAnimator implements View.OnLayoutChangeListener {
- static final long APPEAR_ANIMATION_LENGTH = 210;
+ private static final long APPEAR_ANIMATION_LENGTH = 210;
private static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
- private static final int TAG_LOCAL_TRANSLATION_ANIMATOR = R.id.tag_local_translation_y_animator;
- private static final int TAG_LOCAL_TRANSLATION_Y = R.id.tag_local_translation_y;
+ private static final int TAG_TOP_ANIMATOR = R.id.tag_top_animator;
+ private static final int TAG_TOP = R.id.tag_top_override;
private static final int TAG_LAYOUT_TOP = R.id.tag_layout_top;
+ private static final int TAG_FIRST_LAYOUT = R.id.tag_is_first_layout;
private static final int TAG_ALPHA_ANIMATOR = R.id.tag_alpha_animator;
private static final ViewClippingUtil.ClippingParameters CLIPPING_PARAMETERS =
view -> view.getId() == com.android.internal.R.id.notification_messaging;
- private static final IntProperty<View> LOCAL_TRANSLATION_Y =
- new IntProperty<View>("localTranslationY") {
+ private static final IntProperty<View> TOP =
+ new IntProperty<View>("top") {
@Override
public void setValue(View object, int value) {
- setLocalTranslationY(object, value);
+ setTop(object, value);
}
@Override
public Integer get(View object) {
- return getLocalTranslationY(object);
+ return getTop(object);
}
};
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
- int oldHeight = oldBottom - oldTop;
- Integer layoutTop = (Integer) v.getTag(TAG_LAYOUT_TOP);
- if (layoutTop != null) {
- oldTop = layoutTop;
- }
- int topChange = oldTop - top;
- if (oldHeight == 0 || topChange == 0 || !v.isShown() || isGone(v)) {
- // First layout
+ setLayoutTop(v, top);
+ if (isFirstLayout(v)) {
+ setFirstLayout(v, false /* first */);
+ setTop(v, top);
return;
}
- if (layoutTop != null) {
- v.setTagInternal(TAG_LAYOUT_TOP, top);
- }
- int newHeight = bottom - top;
- int heightDifference = oldHeight - newHeight;
- // Only add the difference if the height changes and it's getting smaller
- heightDifference = Math.max(heightDifference, 0);
- startLocalTranslationFrom(v, topChange + heightDifference + getLocalTranslationY(v));
+ startTopAnimation(v, getTop(v), top, MessagingLayout.FAST_OUT_SLOW_IN);
}
- private boolean isGone(View view) {
- if (view.getVisibility() == View.GONE) {
- return true;
- }
- final ViewGroup.LayoutParams lp = view.getLayoutParams();
- if (lp instanceof MessagingLinearLayout.LayoutParams
- && ((MessagingLinearLayout.LayoutParams) lp).hide) {
- return true;
- }
- return false;
- }
-
- public static void startLocalTranslationFrom(View v, int startTranslation) {
- startLocalTranslationFrom(v, startTranslation, MessagingLayout.FAST_OUT_SLOW_IN);
- }
-
- public static void startLocalTranslationFrom(View v, int startTranslation,
- Interpolator interpolator) {
- startLocalTranslation(v, startTranslation, 0, interpolator);
- }
-
- public static void startLocalTranslationTo(View v, int endTranslation,
- Interpolator interpolator) {
- startLocalTranslation(v, getLocalTranslationY(v), endTranslation, interpolator);
- }
-
- public static int getLocalTranslationY(View v) {
- Integer tag = (Integer) v.getTag(TAG_LOCAL_TRANSLATION_Y);
+ private static boolean isFirstLayout(View view) {
+ Boolean tag = (Boolean) view.getTag(TAG_FIRST_LAYOUT);
if (tag == null) {
- return 0;
+ return true;
}
return tag;
}
- private static void setLocalTranslationY(View v, int value) {
- v.setTagInternal(TAG_LOCAL_TRANSLATION_Y, value);
+ public static void recycle(View view) {
+ setFirstLayout(view, true /* first */);
+ }
+
+ private static void setFirstLayout(View view, boolean first) {
+ view.setTagInternal(TAG_FIRST_LAYOUT, first);
+ }
+
+ private static void setLayoutTop(View view, int top) {
+ view.setTagInternal(TAG_LAYOUT_TOP, top);
+ }
+
+ public static int getLayoutTop(View view) {
+ Integer tag = (Integer) view.getTag(TAG_LAYOUT_TOP);
+ if (tag == null) {
+ return getTop(view);
+ }
+ return tag;
+ }
+
+ /**
+ * Start a translation animation from a start offset to the laid out location
+ * @param view The view to animate
+ * @param startTranslation The starting translation to start from.
+ * @param interpolator The interpolator to use.
+ */
+ public static void startLocalTranslationFrom(View view, int startTranslation,
+ Interpolator interpolator) {
+ startTopAnimation(view, getTop(view) + startTranslation, getLayoutTop(view), interpolator);
+ }
+
+ /**
+ * Start a translation animation from a start offset to the laid out location
+ * @param view The view to animate
+ * @param endTranslation The end translation to go to.
+ * @param interpolator The interpolator to use.
+ */
+ public static void startLocalTranslationTo(View view, int endTranslation,
+ Interpolator interpolator) {
+ int top = getTop(view);
+ startTopAnimation(view, top, top + endTranslation, interpolator);
+ }
+
+ public static int getTop(View v) {
+ Integer tag = (Integer) v.getTag(TAG_TOP);
+ if (tag == null) {
+ return v.getTop();
+ }
+ return tag;
+ }
+
+ private static void setTop(View v, int value) {
+ v.setTagInternal(TAG_TOP, value);
updateTopAndBottom(v);
}
private static void updateTopAndBottom(View v) {
- int layoutTop = (int) v.getTag(TAG_LAYOUT_TOP);
- int localTranslation = getLocalTranslationY(v);
+ int top = getTop(v);
int height = v.getHeight();
- v.setTop(layoutTop + localTranslation);
- v.setBottom(layoutTop + height + localTranslation);
+ v.setTop(top);
+ v.setBottom(height + top);
}
- private static void startLocalTranslation(final View v, int start, int end,
+ private static void startTopAnimation(final View v, int start, int end,
Interpolator interpolator) {
- ObjectAnimator existing = (ObjectAnimator) v.getTag(TAG_LOCAL_TRANSLATION_ANIMATOR);
+ ObjectAnimator existing = (ObjectAnimator) v.getTag(TAG_TOP_ANIMATOR);
if (existing != null) {
existing.cancel();
}
- ObjectAnimator animator = ObjectAnimator.ofInt(v, LOCAL_TRANSLATION_Y, start, end);
- Integer layoutTop = (Integer) v.getTag(TAG_LAYOUT_TOP);
- if (layoutTop == null) {
- layoutTop = v.getTop();
- v.setTagInternal(TAG_LAYOUT_TOP, layoutTop);
+ if (!v.isShown() || start == end
+ || (MessagingLinearLayout.isGone(v) && !isHidingAnimated(v))) {
+ setTop(v, end);
+ return;
}
- setLocalTranslationY(v, start);
+ ObjectAnimator animator = ObjectAnimator.ofInt(v, TOP, start, end);
+ setTop(v, start);
animator.setInterpolator(interpolator);
animator.setDuration(APPEAR_ANIMATION_LENGTH);
animator.addListener(new AnimatorListenerAdapter() {
@@ -143,12 +157,8 @@
@Override
public void onAnimationEnd(Animator animation) {
- v.setTagInternal(TAG_LOCAL_TRANSLATION_ANIMATOR, null);
+ v.setTagInternal(TAG_TOP_ANIMATOR, null);
setClippingDeactivated(v, false);
- if (!mCancelled) {
- setLocalTranslationY(v, 0);
- v.setTagInternal(TAG_LAYOUT_TOP, null);
- }
}
@Override
@@ -157,10 +167,17 @@
}
});
setClippingDeactivated(v, true);
- v.setTagInternal(TAG_LOCAL_TRANSLATION_ANIMATOR, animator);
+ v.setTagInternal(TAG_TOP_ANIMATOR, animator);
animator.start();
}
+ private static boolean isHidingAnimated(View v) {
+ if (v instanceof MessagingLinearLayout.MessagingChild) {
+ return ((MessagingLinearLayout.MessagingChild) v).isHidingAnimated();
+ }
+ return false;
+ }
+
public static void fadeIn(final View v) {
ObjectAnimator existing = (ObjectAnimator) v.getTag(TAG_ALPHA_ANIMATOR);
if (existing != null) {
@@ -199,6 +216,13 @@
if (existing != null) {
existing.cancel();
}
+ if (!view.isShown() || (MessagingLinearLayout.isGone(view) && !isHidingAnimated(view))) {
+ view.setAlpha(0.0f);
+ if (endAction != null) {
+ endAction.run();
+ }
+ return;
+ }
ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.ALPHA,
view.getAlpha(), 0.0f);
animator.setInterpolator(ALPHA_OUT);
@@ -224,10 +248,14 @@
}
public static boolean isAnimatingTranslation(View v) {
- return v.getTag(TAG_LOCAL_TRANSLATION_ANIMATOR) != null;
+ return v.getTag(TAG_TOP_ANIMATOR) != null;
}
public static boolean isAnimatingAlpha(View v) {
return v.getTag(TAG_ALPHA_ANIMATOR) != null;
}
+
+ public static void setToLaidOutPosition(View view) {
+ setTop(view, getLayoutTop(view));
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingTextMessage.java b/core/java/com/android/internal/widget/MessagingTextMessage.java
index 219116e..4081a86 100644
--- a/core/java/com/android/internal/widget/MessagingTextMessage.java
+++ b/core/java/com/android/internal/widget/MessagingTextMessage.java
@@ -92,8 +92,6 @@
public void recycle() {
MessagingMessage.super.recycle();
- setAlpha(1.0f);
- setTranslationY(0);
sInstancePool.release(this);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 19e5e21..dced0ad 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -850,7 +850,7 @@
<!-- Used for permissions that are associated telephony features. -->
<permission-group android:name="android.permission-group.CALL_LOG"
- android:icon="@drawable/perm_group_phone_calls"
+ android:icon="@drawable/perm_group_call_log"
android:label="@string/permgrouplab_calllog"
android:description="@string/permgroupdesc_calllog"
android:request="@string/permgrouprequest_calllog"
diff --git a/core/res/res/drawable/perm_group_call_log.xml b/core/res/res/drawable/perm_group_call_log.xml
new file mode 100644
index 0000000..0dfdbee
--- /dev/null
+++ b/core/res/res/drawable/perm_group_call_log.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#000000"
+ android:pathData="M16.01,14.48l-2.62,2.62c-2.75,-1.49 -5.01,-3.75 -6.5,-6.5l2.62,-2.62c0.24,-0.24 0.34,-0.58 0.27,-0.9L9.13,3.82c-0.09,-0.47 -0.5,-0.8 -0.98,-0.8L4,3.01c-0.56,0 -1.03,0.47 -1,1.03c0.17,2.91 1.04,5.63 2.43,8.01c1.57,2.69 3.81,4.93 6.5,6.5c2.38,1.39 5.1,2.26 8.01,2.43c0.56,0.03 1.03,-0.44 1.03,-1v-4.15c0,-0.48 -0.34,-0.89 -0.8,-0.98l-3.26,-0.65C16.58,14.14 16.24,14.24 16.01,14.48z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M12,8h10V6H12V8zM12,4h10V2H12V4zM22,10H12v2h10V10z"/>
+</vector>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 47d04ed..bf7e068 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -140,15 +140,18 @@
<!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW}. -->
<item type="id" name="accessibilityActionMoveWindow" />
- <!-- A tag used to save an animator in local y translation -->
- <item type="id" name="tag_local_translation_y_animator" />
+ <!-- A tag used to save an animator in top -->
+ <item type="id" name="tag_top_animator" />
- <!-- A tag used to save the local translation y -->
- <item type="id" name="tag_local_translation_y" />
+ <!-- A tag used to save the current top override -->
+ <item type="id" name="tag_top_override" />
<!-- A tag used to save the original top of a view -->
<item type="id" name="tag_layout_top" />
+ <!-- A tag used to save whether a view was laid out before -->
+ <item type="id" name="tag_is_first_layout" />
+
<!-- A tag used to save an animator in alpha -->
<item type="id" name="tag_alpha_animator" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f7ff377..8a045a0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3260,9 +3260,10 @@
<java-symbol type="id" name="message_name" />
<java-symbol type="id" name="message_icon" />
<java-symbol type="id" name="group_message_container" />
- <java-symbol type="id" name="tag_local_translation_y_animator" />
- <java-symbol type="id" name="tag_local_translation_y" />
+ <java-symbol type="id" name="tag_top_animator" />
+ <java-symbol type="id" name="tag_top_override" />
<java-symbol type="id" name="tag_layout_top" />
+ <java-symbol type="id" name="tag_is_first_layout" />
<java-symbol type="id" name="tag_alpha_animator" />
<java-symbol type="id" name="clip_children_set_tag" />
<java-symbol type="id" name="clip_to_padding_tag" />
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
new file mode 100644
index 0000000..c8e46fc
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.view;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ViewRootImplTest {
+
+ private Context mContext;
+ private ViewRootImplAccessor mViewRootImpl;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ mViewRootImpl = new ViewRootImplAccessor(
+ new ViewRootImpl(mContext, mContext.getDisplay()));
+ });
+ }
+
+ @Test
+ public void negativeInsets_areSetToZero() throws Exception {
+ mViewRootImpl.getAttachInfo().getContentInsets().set(-10, -20, -30 , -40);
+ mViewRootImpl.getAttachInfo().getStableInsets().set(-10, -20, -30 , -40);
+ final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
+
+ assertThat(insets.getSystemWindowInsets(), equalTo(new Rect()));
+ assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+ insets.getStableInsetRight(), insets.getStableInsetBottom()), equalTo(new Rect()));
+ }
+
+ @Test
+ public void negativeInsets_areSetToZero_positiveAreLeftAsIs() throws Exception {
+ mViewRootImpl.getAttachInfo().getContentInsets().set(-10, 20, -30 , 40);
+ mViewRootImpl.getAttachInfo().getStableInsets().set(10, -20, 30 , -40);
+ final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
+
+ assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(0, 20, 0, 40)));
+ assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+ insets.getStableInsetRight(), insets.getStableInsetBottom()),
+ equalTo(new Rect(10, 0, 30, 0)));
+ }
+
+ @Test
+ public void positiveInsets_areLeftAsIs() throws Exception {
+ mViewRootImpl.getAttachInfo().getContentInsets().set(10, 20, 30 , 40);
+ mViewRootImpl.getAttachInfo().getStableInsets().set(10, 20, 30 , 40);
+ final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
+
+ assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(10, 20, 30, 40)));
+ assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+ insets.getStableInsetRight(), insets.getStableInsetBottom()),
+ equalTo(new Rect(10, 20, 30, 40)));
+ }
+
+ private static class ViewRootImplAccessor {
+
+ private final ViewRootImpl mViewRootImpl;
+
+ ViewRootImplAccessor(ViewRootImpl viewRootImpl) {
+ mViewRootImpl = viewRootImpl;
+ }
+
+ public ViewRootImpl get() {
+ return mViewRootImpl;
+ }
+
+ AttachInfoAccessor getAttachInfo() throws Exception {
+ return new AttachInfoAccessor(
+ getField(mViewRootImpl, ViewRootImpl.class.getDeclaredField("mAttachInfo")));
+ }
+
+ WindowInsets getWindowInsets(boolean forceConstruct) throws Exception {
+ return (WindowInsets) invokeMethod(mViewRootImpl,
+ ViewRootImpl.class.getDeclaredMethod("getWindowInsets", boolean.class),
+ forceConstruct);
+ }
+
+ class AttachInfoAccessor {
+
+ private final Class<?> mClass;
+ private final Object mAttachInfo;
+
+ AttachInfoAccessor(Object attachInfo) throws Exception {
+ mAttachInfo = attachInfo;
+ mClass = ViewRootImpl.class.getClassLoader().loadClass(
+ "android.view.View$AttachInfo");
+ }
+
+ Rect getContentInsets() throws Exception {
+ return (Rect) getField(mAttachInfo, mClass.getDeclaredField("mContentInsets"));
+ }
+
+ Rect getStableInsets() throws Exception {
+ return (Rect) getField(mAttachInfo, mClass.getDeclaredField("mStableInsets"));
+ }
+ }
+
+ private static Object getField(Object o, Field field) throws Exception {
+ field.setAccessible(true);
+ return field.get(o);
+ }
+
+ private static Object invokeMethod(Object o, Method method, Object... args)
+ throws Exception {
+ method.setAccessible(true);
+ return method.invoke(o, args);
+ }
+ }
+}
diff --git a/docs/html/reference/_book.yaml b/docs/html/reference/_book.yaml
deleted file mode 100644
index b902a61..0000000
--- a/docs/html/reference/_book.yaml
+++ /dev/null
@@ -1,853 +0,0 @@
-reference:
-- title: Class Index
- path: /reference/classes.html
- status_text: no-toggle
-- title: Package Index
- path: /reference/packages.html
- status_text: no-toggle
-- title: android
- path: /reference/android/package-summary.html
- status_text: apilevel-1
-- title: android.accessibilityservice
- path: /reference/android/accessibilityservice/package-summary.html
- status_text: apilevel-4
-- title: android.accounts
- path: /reference/android/accounts/package-summary.html
- status_text: apilevel-5
-- title: android.animation
- path: /reference/android/animation/package-summary.html
- status_text: apilevel-11
-- title: android.annotation
- path: /reference/android/annotation/package-summary.html
- status_text: apilevel-16
-- title: android.app
- path: /reference/android/app/package-summary.html
- status_text: apilevel-1
-- title: android.app.admin
- path: /reference/android/app/admin/package-summary.html
- status_text: apilevel-8
-- title: android.app.assist
- path: /reference/android/app/assist/package-summary.html
- status_text: apilevel-23
-- title: android.app.backup
- path: /reference/android/app/backup/package-summary.html
- status_text: apilevel-8
-- title: android.app.job
- path: /reference/android/app/job/package-summary.html
- status_text: apilevel-21
-- title: android.app.usage
- path: /reference/android/app/usage/package-summary.html
- status_text: apilevel-21
-- title: android.appwidget
- path: /reference/android/appwidget/package-summary.html
- status_text: apilevel-3
-- title: android.bluetooth
- path: /reference/android/bluetooth/package-summary.html
- status_text: apilevel-5
-- title: android.bluetooth.le
- path: /reference/android/bluetooth/le/package-summary.html
- status_text: apilevel-21
-- title: android.companion
- path: /reference/android/companion/package-summary.html
- status_text: apilevel-O
-- title: android.content
- path: /reference/android/content/package-summary.html
- status_text: apilevel-1
-- title: android.content.pm
- path: /reference/android/content/pm/package-summary.html
- status_text: apilevel-1
-- title: android.content.res
- path: /reference/android/content/res/package-summary.html
- status_text: apilevel-1
-- title: android.database
- path: /reference/android/database/package-summary.html
- status_text: apilevel-1
-- title: android.database.sqlite
- path: /reference/android/database/sqlite/package-summary.html
- status_text: apilevel-1
-- title: android.databinding
- path: /reference/android/databinding/package-summary.html
- status_text: apilevel-
-- title: android.drm
- path: /reference/android/drm/package-summary.html
- status_text: apilevel-11
-- title: android.gesture
- path: /reference/android/gesture/package-summary.html
- status_text: apilevel-4
-- title: android.graphics
- path: /reference/android/graphics/package-summary.html
- status_text: apilevel-1
-- title: android.graphics.drawable
- path: /reference/android/graphics/drawable/package-summary.html
- status_text: apilevel-1
-- title: android.graphics.drawable.shapes
- path: /reference/android/graphics/drawable/shapes/package-summary.html
- status_text: apilevel-1
-- title: android.graphics.fonts
- path: /reference/android/graphics/fonts/package-summary.html
- status_text: apilevel-O
-- title: android.graphics.pdf
- path: /reference/android/graphics/pdf/package-summary.html
- status_text: apilevel-19
-- title: android.hardware
- path: /reference/android/hardware/package-summary.html
- status_text: apilevel-1
-- title: android.hardware.camera2
- path: /reference/android/hardware/camera2/package-summary.html
- status_text: apilevel-21
-- title: android.hardware.camera2.params
- path: /reference/android/hardware/camera2/params/package-summary.html
- status_text: apilevel-21
-- title: android.hardware.display
- path: /reference/android/hardware/display/package-summary.html
- status_text: apilevel-17
-- title: android.hardware.fingerprint
- path: /reference/android/hardware/fingerprint/package-summary.html
- status_text: apilevel-23
-- title: android.hardware.input
- path: /reference/android/hardware/input/package-summary.html
- status_text: apilevel-16
-- title: android.hardware.usb
- path: /reference/android/hardware/usb/package-summary.html
- status_text: apilevel-12
-- title: android.icu.lang
- path: /reference/android/icu/lang/package-summary.html
- status_text: apilevel-24
-- title: android.icu.math
- path: /reference/android/icu/math/package-summary.html
- status_text: apilevel-24
-- title: android.icu.text
- path: /reference/android/icu/text/package-summary.html
- status_text: apilevel-24
-- title: android.icu.util
- path: /reference/android/icu/util/package-summary.html
- status_text: apilevel-24
-- title: android.inputmethodservice
- path: /reference/android/inputmethodservice/package-summary.html
- status_text: apilevel-3
-- title: android.location
- path: /reference/android/location/package-summary.html
- status_text: apilevel-1
-- title: android.media
- path: /reference/android/media/package-summary.html
- status_text: apilevel-1
-- title: android.media.audiofx
- path: /reference/android/media/audiofx/package-summary.html
- status_text: apilevel-9
-- title: android.media.browse
- path: /reference/android/media/browse/package-summary.html
- status_text: apilevel-21
-- title: android.media.effect
- path: /reference/android/media/effect/package-summary.html
- status_text: apilevel-14
-- title: android.media.midi
- path: /reference/android/media/midi/package-summary.html
- status_text: apilevel-23
-- title: android.media.projection
- path: /reference/android/media/projection/package-summary.html
- status_text: apilevel-21
-- title: android.media.session
- path: /reference/android/media/session/package-summary.html
- status_text: apilevel-21
-- title: android.media.tv
- path: /reference/android/media/tv/package-summary.html
- status_text: apilevel-21
-- title: android.mtp
- path: /reference/android/mtp/package-summary.html
- status_text: apilevel-12
-- title: android.net
- path: /reference/android/net/package-summary.html
- status_text: apilevel-1
-- title: android.net.http
- path: /reference/android/net/http/package-summary.html
- status_text: apilevel-1
-- title: android.net.nsd
- path: /reference/android/net/nsd/package-summary.html
- status_text: apilevel-16
-- title: android.net.rtp
- path: /reference/android/net/rtp/package-summary.html
- status_text: apilevel-12
-- title: android.net.sip
- path: /reference/android/net/sip/package-summary.html
- status_text: apilevel-9
-- title: android.net.wifi
- path: /reference/android/net/wifi/package-summary.html
- status_text: apilevel-1
-- title: android.net.wifi.aware
- path: /reference/android/net/wifi/aware/package-summary.html
- status_text: apilevel-O
-- title: android.net.wifi.hotspot2
- path: /reference/android/net/wifi/hotspot2/package-summary.html
- status_text: apilevel-O
-- title: android.net.wifi.hotspot2.omadm
- path: /reference/android/net/wifi/hotspot2/omadm/package-summary.html
- status_text: apilevel-O
-- title: android.net.wifi.hotspot2.pps
- path: /reference/android/net/wifi/hotspot2/pps/package-summary.html
- status_text: apilevel-O
-- title: android.net.wifi.p2p
- path: /reference/android/net/wifi/p2p/package-summary.html
- status_text: apilevel-14
-- title: android.net.wifi.p2p.nsd
- path: /reference/android/net/wifi/p2p/nsd/package-summary.html
- status_text: apilevel-16
-- title: android.nfc
- path: /reference/android/nfc/package-summary.html
- status_text: apilevel-9
-- title: android.nfc.cardemulation
- path: /reference/android/nfc/cardemulation/package-summary.html
- status_text: apilevel-19
-- title: android.nfc.tech
- path: /reference/android/nfc/tech/package-summary.html
- status_text: apilevel-10
-- title: android.opengl
- path: /reference/android/opengl/package-summary.html
- status_text: apilevel-1
-- title: android.os
- path: /reference/android/os/package-summary.html
- status_text: apilevel-1
-- title: android.os.health
- path: /reference/android/os/health/package-summary.html
- status_text: apilevel-24
-- title: android.os.storage
- path: /reference/android/os/storage/package-summary.html
- status_text: apilevel-9
-- title: android.preference
- path: /reference/android/preference/package-summary.html
- status_text: apilevel-1
-- title: android.print
- path: /reference/android/print/package-summary.html
- status_text: apilevel-19
-- title: android.print.pdf
- path: /reference/android/print/pdf/package-summary.html
- status_text: apilevel-19
-- title: android.printservice
- path: /reference/android/printservice/package-summary.html
- status_text: apilevel-19
-- title: android.provider
- path: /reference/android/provider/package-summary.html
- status_text: apilevel-1
-- title: android.renderscript
- path: /reference/android/renderscript/package-summary.html
- status_text: apilevel-11
-- title: android.sax
- path: /reference/android/sax/package-summary.html
- status_text: apilevel-1
-- title: android.security
- path: /reference/android/security/package-summary.html
- status_text: apilevel-14
-- title: android.security.keystore
- path: /reference/android/security/keystore/package-summary.html
- status_text: apilevel-23
-- title: android.service.autofill
- path: /reference/android/service/autofill/package-summary.html
- status_text: apilevel-O
-- title: android.service.carrier
- path: /reference/android/service/carrier/package-summary.html
- status_text: apilevel-22
-- title: android.service.chooser
- path: /reference/android/service/chooser/package-summary.html
- status_text: apilevel-23
-- title: android.service.dreams
- path: /reference/android/service/dreams/package-summary.html
- status_text: apilevel-17
-- title: android.service.media
- path: /reference/android/service/media/package-summary.html
- status_text: apilevel-21
-- title: android.service.notification
- path: /reference/android/service/notification/package-summary.html
- status_text: apilevel-18
-- title: android.service.quicksettings
- path: /reference/android/service/quicksettings/package-summary.html
- status_text: apilevel-24
-- title: android.service.restrictions
- path: /reference/android/service/restrictions/package-summary.html
- status_text: apilevel-21
-- title: android.service.textservice
- path: /reference/android/service/textservice/package-summary.html
- status_text: apilevel-14
-- title: android.service.voice
- path: /reference/android/service/voice/package-summary.html
- status_text: apilevel-21
-- title: android.service.vr
- path: /reference/android/service/vr/package-summary.html
- status_text: apilevel-24
-- title: android.service.wallpaper
- path: /reference/android/service/wallpaper/package-summary.html
- status_text: apilevel-7
-- title: android.speech
- path: /reference/android/speech/package-summary.html
- status_text: apilevel-3
-- title: android.speech.tts
- path: /reference/android/speech/tts/package-summary.html
- status_text: apilevel-4
-- title: android.support.animation
- path: /reference/android/support/animation/package-summary.html
- status_text: apilevel-25.3.0
-- title: android.support.annotation
- path: /reference/android/support/annotation/package-summary.html
- status_text: apilevel-
-- title: android.support.app.recommendation
- path: /reference/android/support/app/recommendation/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.compat
- path: /reference/android/support/compat/package-summary.html
- status_text: apilevel-
-- title: android.support.coreui
- path: /reference/android/support/coreui/package-summary.html
- status_text: apilevel-
-- title: android.support.coreutils
- path: /reference/android/support/coreutils/package-summary.html
- status_text: apilevel-
-- title: android.support.customtabs
- path: /reference/android/support/customtabs/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.design
- path: /reference/android/support/design/package-summary.html
- status_text: apilevel-
-- title: android.support.design.widget
- path: /reference/android/support/design/widget/package-summary.html
- status_text: apilevel-22.2.0
-- title: android.support.dynamicanimation
- path: /reference/android/support/dynamicanimation/package-summary.html
- status_text: apilevel-
-- title: android.support.exifinterface
- path: /reference/android/support/exifinterface/package-summary.html
- status_text: apilevel-
-- title: android.support.fragment
- path: /reference/android/support/fragment/package-summary.html
- status_text: apilevel-
-- title: android.support.graphics.drawable
- path: /reference/android/support/graphics/drawable/package-summary.html
- status_text: apilevel-23.2.0
-- title: android.support.graphics.drawable.animated
- path: /reference/android/support/graphics/drawable/animated/package-summary.html
- status_text: apilevel-
-- title: android.support.media
- path: /reference/android/support/media/package-summary.html
- status_text: apilevel-25.1.0
-- title: android.support.media.instantvideo
- path: /reference/android/support/media/instantvideo/package-summary.html
- status_text: apilevel-
-- title: android.support.media.instantvideo.preload
- path: /reference/android/support/media/instantvideo/preload/package-summary.html
- status_text: apilevel-26.0.0-alpha1
-- title: android.support.media.instantvideo.widget
- path: /reference/android/support/media/instantvideo/widget/package-summary.html
- status_text: apilevel-26.0.0-alpha1
-- title: android.support.media.tv
- path: /reference/android/support/media/tv/package-summary.html
- status_text: apilevel-26.0.0-alpha1
-- title: android.support.mediacompat
- path: /reference/android/support/mediacompat/package-summary.html
- status_text: apilevel-
-- title: android.support.multidex
- path: /reference/android/support/multidex/package-summary.html
- status_text: apilevel-
-- title: android.support.percent
- path: /reference/android/support/percent/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.recommendation
- path: /reference/android/support/recommendation/package-summary.html
- status_text: apilevel-
-- title: android.support.transition
- path: /reference/android/support/transition/package-summary.html
- status_text: apilevel-24.2.0
-- title: android.support.v13
- path: /reference/android/support/v13/package-summary.html
- status_text: apilevel-
-- title: android.support.v13.app
- path: /reference/android/support/v13/app/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v13.view
- path: /reference/android/support/v13/view/package-summary.html
- status_text: apilevel-24.0.0
-- title: android.support.v13.view.inputmethod
- path: /reference/android/support/v13/view/inputmethod/package-summary.html
- status_text: apilevel-25.0.0
-- title: android.support.v14.preference
- path: /reference/android/support/v14/preference/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.v17.leanback
- path: /reference/android/support/v17/leanback/package-summary.html
- status_text: apilevel-
-- title: android.support.v17.leanback.app
- path: /reference/android/support/v17/leanback/app/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v17.leanback.database
- path: /reference/android/support/v17/leanback/database/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v17.leanback.graphics
- path: /reference/android/support/v17/leanback/graphics/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v17.leanback.media
- path: /reference/android/support/v17/leanback/media/package-summary.html
- status_text: apilevel-25.1.0
-- title: android.support.v17.leanback.system
- path: /reference/android/support/v17/leanback/system/package-summary.html
- status_text: apilevel-22.2.1
-- title: android.support.v17.leanback.widget
- path: /reference/android/support/v17/leanback/widget/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v17.leanback.widget.picker
- path: /reference/android/support/v17/leanback/widget/picker/package-summary.html
- status_text: apilevel-23.2.0
-- title: android.support.v17.preference
- path: /reference/android/support/v17/preference/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.v4
- path: /reference/android/support/v4/package-summary.html
- status_text: apilevel-
-- title: android.support.v4.accessibilityservice
- path: /reference/android/support/v4/accessibilityservice/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.app
- path: /reference/android/support/v4/app/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.content
- path: /reference/android/support/v4/content/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.content.pm
- path: /reference/android/support/v4/content/pm/package-summary.html
- status_text: apilevel-22.2.0
-- title: android.support.v4.content.res
- path: /reference/android/support/v4/content/res/package-summary.html
- status_text: apilevel-22.2.0
-- title: android.support.v4.database
- path: /reference/android/support/v4/database/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.graphics
- path: /reference/android/support/v4/graphics/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.graphics.drawable
- path: /reference/android/support/v4/graphics/drawable/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.hardware.display
- path: /reference/android/support/v4/hardware/display/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.hardware.fingerprint
- path: /reference/android/support/v4/hardware/fingerprint/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.v4.math
- path: /reference/android/support/v4/math/package-summary.html
- status_text: apilevel-26.0.0-alpha1
-- title: android.support.v4.media
- path: /reference/android/support/v4/media/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.media.session
- path: /reference/android/support/v4/media/session/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.net
- path: /reference/android/support/v4/net/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.os
- path: /reference/android/support/v4/os/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.print
- path: /reference/android/support/v4/print/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.provider
- path: /reference/android/support/v4/provider/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.text
- path: /reference/android/support/v4/text/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.text.util
- path: /reference/android/support/v4/text/util/package-summary.html
- status_text: apilevel-24.2.0
-- title: android.support.v4.util
- path: /reference/android/support/v4/util/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.view
- path: /reference/android/support/v4/view/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.view.accessibility
- path: /reference/android/support/v4/view/accessibility/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v4.view.animation
- path: /reference/android/support/v4/view/animation/package-summary.html
- status_text: apilevel-22.1.0
-- title: android.support.v4.widget
- path: /reference/android/support/v4/widget/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v7.app
- path: /reference/android/support/v7/app/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v7.appcompat
- path: /reference/android/support/v7/appcompat/package-summary.html
- status_text: apilevel-22.2.0
-- title: android.support.v7.cardview
- path: /reference/android/support/v7/cardview/package-summary.html
- status_text: apilevel-
-- title: android.support.v7.content.res
- path: /reference/android/support/v7/content/res/package-summary.html
- status_text: apilevel-24.0.0
-- title: android.support.v7.graphics
- path: /reference/android/support/v7/graphics/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v7.graphics.drawable
- path: /reference/android/support/v7/graphics/drawable/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.v7.gridlayout
- path: /reference/android/support/v7/gridlayout/package-summary.html
- status_text: apilevel-
-- title: android.support.v7.media
- path: /reference/android/support/v7/media/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v7.mediarouter
- path: /reference/android/support/v7/mediarouter/package-summary.html
- status_text: apilevel-
-- title: android.support.v7.palette
- path: /reference/android/support/v7/palette/package-summary.html
- status_text: apilevel-
-- title: android.support.v7.preference
- path: /reference/android/support/v7/preference/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.v7.recyclerview
- path: /reference/android/support/v7/recyclerview/package-summary.html
- status_text: apilevel-22.2.0
-- title: android.support.v7.util
- path: /reference/android/support/v7/util/package-summary.html
- status_text: apilevel-22.1.0
-- title: android.support.v7.view
- path: /reference/android/support/v7/view/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v7.widget
- path: /reference/android/support/v7/widget/package-summary.html
- status_text: apilevel-22.0.0
-- title: android.support.v7.widget.helper
- path: /reference/android/support/v7/widget/helper/package-summary.html
- status_text: apilevel-22.2.0
-- title: android.support.v7.widget.util
- path: /reference/android/support/v7/widget/util/package-summary.html
- status_text: apilevel-22.1.0
-- title: android.support.v8.renderscript
- path: /reference/android/support/v8/renderscript/package-summary.html
- status_text: apilevel-23.0.0
-- title: android.support.wearable
- path: /reference/android/support/wearable/package-summary.html
- status_text: apilevel-
-- title: android.support.wearable.view
- path: /reference/android/support/wearable/view/package-summary.html
- status_text: apilevel-26.0.0-alpha1
-- title: android.system
- path: /reference/android/system/package-summary.html
- status_text: apilevel-21
-- title: android.telecom
- path: /reference/android/telecom/package-summary.html
- status_text: apilevel-21
-- title: android.telephony
- path: /reference/android/telephony/package-summary.html
- status_text: apilevel-1
-- title: android.telephony.cdma
- path: /reference/android/telephony/cdma/package-summary.html
- status_text: apilevel-5
-- title: android.telephony.gsm
- path: /reference/android/telephony/gsm/package-summary.html
- status_text: apilevel-1
-- title: android.test
- path: /reference/android/test/package-summary.html
- status_text: apilevel-1
-- title: android.test.mock
- path: /reference/android/test/mock/package-summary.html
- status_text: apilevel-1
-- title: android.test.suitebuilder
- path: /reference/android/test/suitebuilder/package-summary.html
- status_text: apilevel-1
-- title: android.test.suitebuilder.annotation
- path: /reference/android/test/suitebuilder/annotation/package-summary.html
- status_text: apilevel-1
-- title: android.text
- path: /reference/android/text/package-summary.html
- status_text: apilevel-1
-- title: android.text.format
- path: /reference/android/text/format/package-summary.html
- status_text: apilevel-3
-- title: android.text.method
- path: /reference/android/text/method/package-summary.html
- status_text: apilevel-1
-- title: android.text.style
- path: /reference/android/text/style/package-summary.html
- status_text: apilevel-1
-- title: android.text.util
- path: /reference/android/text/util/package-summary.html
- status_text: apilevel-1
-- title: android.transition
- path: /reference/android/transition/package-summary.html
- status_text: apilevel-19
-- title: android.util
- path: /reference/android/util/package-summary.html
- status_text: apilevel-1
-- title: android.view
- path: /reference/android/view/package-summary.html
- status_text: apilevel-1
-- title: android.view.accessibility
- path: /reference/android/view/accessibility/package-summary.html
- status_text: apilevel-4
-- title: android.view.animation
- path: /reference/android/view/animation/package-summary.html
- status_text: apilevel-1
-- title: android.view.autofill
- path: /reference/android/view/autofill/package-summary.html
- status_text: apilevel-O
-- title: android.view.inputmethod
- path: /reference/android/view/inputmethod/package-summary.html
- status_text: apilevel-3
-- title: android.view.textclassifier
- path: /reference/android/view/textclassifier/package-summary.html
- status_text: apilevel-O
-- title: android.view.textservice
- path: /reference/android/view/textservice/package-summary.html
- status_text: apilevel-14
-- title: android.webkit
- path: /reference/android/webkit/package-summary.html
- status_text: apilevel-1
-- title: android.widget
- path: /reference/android/widget/package-summary.html
- status_text: apilevel-1
-- title: com.android.test.runner
- path: /reference/com/android/test/runner/package-summary.html
- status_text: apilevel-
-- title: dalvik.annotation
- path: /reference/dalvik/annotation/package-summary.html
- status_text: apilevel-1
-- title: dalvik.bytecode
- path: /reference/dalvik/bytecode/package-summary.html
- status_text: apilevel-1
-- title: dalvik.system
- path: /reference/dalvik/system/package-summary.html
- status_text: apilevel-1
-- title: java.awt.font
- path: /reference/java/awt/font/package-summary.html
- status_text: apilevel-1
-- title: java.beans
- path: /reference/java/beans/package-summary.html
- status_text: apilevel-3
-- title: java.io
- path: /reference/java/io/package-summary.html
- status_text: apilevel-1
-- title: java.lang
- path: /reference/java/lang/package-summary.html
- status_text: apilevel-1
-- title: java.lang.annotation
- path: /reference/java/lang/annotation/package-summary.html
- status_text: apilevel-1
-- title: java.lang.invoke
- path: /reference/java/lang/invoke/package-summary.html
- status_text: apilevel-O
-- title: java.lang.ref
- path: /reference/java/lang/ref/package-summary.html
- status_text: apilevel-1
-- title: java.lang.reflect
- path: /reference/java/lang/reflect/package-summary.html
- status_text: apilevel-1
-- title: java.math
- path: /reference/java/math/package-summary.html
- status_text: apilevel-1
-- title: java.net
- path: /reference/java/net/package-summary.html
- status_text: apilevel-1
-- title: java.nio
- path: /reference/java/nio/package-summary.html
- status_text: apilevel-1
-- title: java.nio.channels
- path: /reference/java/nio/channels/package-summary.html
- status_text: apilevel-1
-- title: java.nio.channels.spi
- path: /reference/java/nio/channels/spi/package-summary.html
- status_text: apilevel-1
-- title: java.nio.charset
- path: /reference/java/nio/charset/package-summary.html
- status_text: apilevel-1
-- title: java.nio.charset.spi
- path: /reference/java/nio/charset/spi/package-summary.html
- status_text: apilevel-1
-- title: java.nio.file
- path: /reference/java/nio/file/package-summary.html
- status_text: apilevel-O
-- title: java.nio.file.attribute
- path: /reference/java/nio/file/attribute/package-summary.html
- status_text: apilevel-O
-- title: java.nio.file.spi
- path: /reference/java/nio/file/spi/package-summary.html
- status_text: apilevel-O
-- title: java.security
- path: /reference/java/security/package-summary.html
- status_text: apilevel-1
-- title: java.security.acl
- path: /reference/java/security/acl/package-summary.html
- status_text: apilevel-1
-- title: java.security.cert
- path: /reference/java/security/cert/package-summary.html
- status_text: apilevel-1
-- title: java.security.interfaces
- path: /reference/java/security/interfaces/package-summary.html
- status_text: apilevel-1
-- title: java.security.spec
- path: /reference/java/security/spec/package-summary.html
- status_text: apilevel-1
-- title: java.sql
- path: /reference/java/sql/package-summary.html
- status_text: apilevel-1
-- title: java.text
- path: /reference/java/text/package-summary.html
- status_text: apilevel-1
-- title: java.time
- path: /reference/java/time/package-summary.html
- status_text: apilevel-O
-- title: java.time.chrono
- path: /reference/java/time/chrono/package-summary.html
- status_text: apilevel-O
-- title: java.time.format
- path: /reference/java/time/format/package-summary.html
- status_text: apilevel-O
-- title: java.time.temporal
- path: /reference/java/time/temporal/package-summary.html
- status_text: apilevel-O
-- title: java.time.zone
- path: /reference/java/time/zone/package-summary.html
- status_text: apilevel-O
-- title: java.util
- path: /reference/java/util/package-summary.html
- status_text: apilevel-1
-- title: java.util.concurrent
- path: /reference/java/util/concurrent/package-summary.html
- status_text: apilevel-1
-- title: java.util.concurrent.atomic
- path: /reference/java/util/concurrent/atomic/package-summary.html
- status_text: apilevel-1
-- title: java.util.concurrent.locks
- path: /reference/java/util/concurrent/locks/package-summary.html
- status_text: apilevel-1
-- title: java.util.function
- path: /reference/java/util/function/package-summary.html
- status_text: apilevel-24
-- title: java.util.jar
- path: /reference/java/util/jar/package-summary.html
- status_text: apilevel-1
-- title: java.util.logging
- path: /reference/java/util/logging/package-summary.html
- status_text: apilevel-1
-- title: java.util.prefs
- path: /reference/java/util/prefs/package-summary.html
- status_text: apilevel-1
-- title: java.util.regex
- path: /reference/java/util/regex/package-summary.html
- status_text: apilevel-1
-- title: java.util.stream
- path: /reference/java/util/stream/package-summary.html
- status_text: apilevel-24
-- title: java.util.zip
- path: /reference/java/util/zip/package-summary.html
- status_text: apilevel-1
-- title: javax.crypto
- path: /reference/javax/crypto/package-summary.html
- status_text: apilevel-1
-- title: javax.crypto.interfaces
- path: /reference/javax/crypto/interfaces/package-summary.html
- status_text: apilevel-1
-- title: javax.crypto.spec
- path: /reference/javax/crypto/spec/package-summary.html
- status_text: apilevel-1
-- title: javax.microedition.khronos.egl
- path: /reference/javax/microedition/khronos/egl/package-summary.html
- status_text: apilevel-1
-- title: javax.microedition.khronos.opengles
- path: /reference/javax/microedition/khronos/opengles/package-summary.html
- status_text: apilevel-1
-- title: javax.net
- path: /reference/javax/net/package-summary.html
- status_text: apilevel-1
-- title: javax.net.ssl
- path: /reference/javax/net/ssl/package-summary.html
- status_text: apilevel-1
-- title: javax.security.auth
- path: /reference/javax/security/auth/package-summary.html
- status_text: apilevel-1
-- title: javax.security.auth.callback
- path: /reference/javax/security/auth/callback/package-summary.html
- status_text: apilevel-1
-- title: javax.security.auth.login
- path: /reference/javax/security/auth/login/package-summary.html
- status_text: apilevel-1
-- title: javax.security.auth.x500
- path: /reference/javax/security/auth/x500/package-summary.html
- status_text: apilevel-1
-- title: javax.security.cert
- path: /reference/javax/security/cert/package-summary.html
- status_text: apilevel-1
-- title: javax.sql
- path: /reference/javax/sql/package-summary.html
- status_text: apilevel-1
-- title: javax.xml
- path: /reference/javax/xml/package-summary.html
- status_text: apilevel-1
-- title: javax.xml.datatype
- path: /reference/javax/xml/datatype/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.namespace
- path: /reference/javax/xml/namespace/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.parsers
- path: /reference/javax/xml/parsers/package-summary.html
- status_text: apilevel-1
-- title: javax.xml.transform
- path: /reference/javax/xml/transform/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.transform.dom
- path: /reference/javax/xml/transform/dom/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.transform.sax
- path: /reference/javax/xml/transform/sax/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.transform.stream
- path: /reference/javax/xml/transform/stream/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.validation
- path: /reference/javax/xml/validation/package-summary.html
- status_text: apilevel-8
-- title: javax.xml.xpath
- path: /reference/javax/xml/xpath/package-summary.html
- status_text: apilevel-8
-- title: junit.framework
- path: /reference/junit/framework/package-summary.html
- status_text: apilevel-1
-- title: junit.runner
- path: /reference/junit/runner/package-summary.html
- status_text: apilevel-1
-- title: org.apache.http.conn
- path: /reference/org/apache/http/conn/package-summary.html
- status_text: apilevel-1
-- title: org.apache.http.conn.scheme
- path: /reference/org/apache/http/conn/scheme/package-summary.html
- status_text: apilevel-1
-- title: org.apache.http.conn.ssl
- path: /reference/org/apache/http/conn/ssl/package-summary.html
- status_text: apilevel-1
-- title: org.apache.http.params
- path: /reference/org/apache/http/params/package-summary.html
- status_text: apilevel-1
-- title: org.json
- path: /reference/org/json/package-summary.html
- status_text: apilevel-1
-- title: org.w3c.dom
- path: /reference/org/w3c/dom/package-summary.html
- status_text: apilevel-1
-- title: org.w3c.dom.ls
- path: /reference/org/w3c/dom/ls/package-summary.html
- status_text: apilevel-8
-- title: org.xml.sax
- path: /reference/org/xml/sax/package-summary.html
- status_text: apilevel-1
-- title: org.xml.sax.ext
- path: /reference/org/xml/sax/ext/package-summary.html
- status_text: apilevel-1
-- title: org.xml.sax.helpers
- path: /reference/org/xml/sax/helpers/package-summary.html
- status_text: apilevel-1
-- title: org.xmlpull.v1
- path: /reference/org/xmlpull/v1/package-summary.html
- status_text: apilevel-1
-- title: org.xmlpull.v1.sax2
- path: /reference/org/xmlpull/v1/sax2/package-summary.html
- status_text: apilevel-1
diff --git a/docs/html/reference/_project.yaml b/docs/html/reference/_project.yaml
deleted file mode 100644
index e5c26e7..0000000
--- a/docs/html/reference/_project.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-name: "Reference"
-home_url: /reference/
-description: "API Reference packages and classes."
-content_license: cc3-apache2
-buganizer_id: 30209417
-parent_project_metadata_path: /develop/_project.yaml
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index b7699f1..7234788 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -16,15 +16,19 @@
package com.android.settingslib.fuelgauge;
+import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
+import android.telecom.DefaultDialerManager;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.telephony.SmsApplication;
import com.android.internal.util.ArrayUtils;
/**
@@ -38,19 +42,20 @@
private static PowerWhitelistBackend sInstance;
+ private final Context mAppContext;
private final IDeviceIdleController mDeviceIdleService;
private final ArraySet<String> mWhitelistedApps = new ArraySet<>();
private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();
private final ArraySet<String> mSysWhitelistedAppsExceptIdle = new ArraySet<>();
- public PowerWhitelistBackend() {
- mDeviceIdleService = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(DEVICE_IDLE_SERVICE));
- refreshList();
+ public PowerWhitelistBackend(Context context) {
+ this(context, IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(DEVICE_IDLE_SERVICE)));
}
@VisibleForTesting
- PowerWhitelistBackend(IDeviceIdleController deviceIdleService) {
+ PowerWhitelistBackend(Context context, IDeviceIdleController deviceIdleService) {
+ mAppContext = context.getApplicationContext();
mDeviceIdleService = deviceIdleService;
refreshList();
}
@@ -64,7 +69,27 @@
}
public boolean isWhitelisted(String pkg) {
- return mWhitelistedApps.contains(pkg);
+ if (mWhitelistedApps.contains(pkg)) {
+ return true;
+ }
+
+ // Additionally, check if pkg is default dialer/sms. They are considered essential apps and
+ // should be automatically whitelisted (otherwise user may be able to set restriction on
+ // them, leading to bad device behavior.)
+ if (!mAppContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return false;
+ }
+ final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
+ true /* updateIfNeeded */);
+ if (defaultSms != null && TextUtils.equals(pkg, defaultSms.getPackageName())) {
+ return true;
+ }
+
+ final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mAppContext);
+ if (TextUtils.equals(pkg, defaultDialer)) {
+ return true;
+ }
+ return false;
}
public boolean isWhitelisted(String[] pkgs) {
@@ -120,16 +145,19 @@
mSysWhitelistedApps.clear();
mSysWhitelistedAppsExceptIdle.clear();
mWhitelistedApps.clear();
+ if (mDeviceIdleService == null) {
+ return;
+ }
try {
- String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
+ final String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
for (String app : whitelistedApps) {
mWhitelistedApps.add(app);
}
- String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
+ final String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
for (String app : sysWhitelistedApps) {
mSysWhitelistedApps.add(app);
}
- String[] sysWhitelistedAppsExceptIdle =
+ final String[] sysWhitelistedAppsExceptIdle =
mDeviceIdleService.getSystemPowerWhitelistExceptIdle();
for (String app : sysWhitelistedAppsExceptIdle) {
mSysWhitelistedAppsExceptIdle.add(app);
@@ -139,9 +167,9 @@
}
}
- public static PowerWhitelistBackend getInstance() {
+ public static PowerWhitelistBackend getInstance(Context context) {
if (sInstance == null) {
- sInstance = new PowerWhitelistBackend();
+ sInstance = new PowerWhitelistBackend(context);
}
return sInstance;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 0af2c05..a23eebc 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -23,35 +23,52 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.IDeviceIdleController;
import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
+import com.android.settingslib.testutils.shadow.ShadowSmsApplication;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowPackageManager;
@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowDefaultDialerManager.class, ShadowSmsApplication.class})
public class PowerWhitelistBackendTest {
private static final String PACKAGE_ONE = "com.example.packageone";
private static final String PACKAGE_TWO = "com.example.packagetwo";
- private PowerWhitelistBackend mPowerWhitelistBackend;
@Mock
private IDeviceIdleController mDeviceIdleService;
+ private PowerWhitelistBackend mPowerWhitelistBackend;
+ private ShadowPackageManager mPackageManager;
+ private Context mContext;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist();
doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist();
doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
doNothing().when(mDeviceIdleService).addPowerSaveWhitelistApp(anyString());
doNothing().when(mDeviceIdleService).removePowerSaveWhitelistApp(anyString());
- mPowerWhitelistBackend = new PowerWhitelistBackend(mDeviceIdleService);
+ mPackageManager = Shadow.extract(mContext.getPackageManager());
+ mPackageManager.setSystemFeature(PackageManager.FEATURE_TELEPHONY, true);
+
+ mPowerWhitelistBackend = new PowerWhitelistBackend(mContext, mDeviceIdleService);
}
@Test
@@ -61,8 +78,8 @@
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
- assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_ONE})).isTrue();
- assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_TWO})).isFalse();
+ assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_ONE})).isTrue();
+ assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_TWO})).isFalse();
mPowerWhitelistBackend.addApp(PACKAGE_TWO);
@@ -70,15 +87,15 @@
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(
- new String[]{PACKAGE_ONE, PACKAGE_TWO})).isTrue();
+ new String[] {PACKAGE_ONE, PACKAGE_TWO})).isTrue();
mPowerWhitelistBackend.removeApp(PACKAGE_TWO);
verify(mDeviceIdleService, atLeastOnce()).removePowerSaveWhitelistApp(PACKAGE_TWO);
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
- assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_ONE})).isTrue();
- assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_TWO})).isFalse();
+ assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_ONE})).isTrue();
+ assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_TWO})).isFalse();
mPowerWhitelistBackend.removeApp(PACKAGE_ONE);
@@ -86,7 +103,23 @@
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(
- new String[]{PACKAGE_ONE, PACKAGE_TWO})).isFalse();
+ new String[] {PACKAGE_ONE, PACKAGE_TWO})).isFalse();
+ }
+
+ @Test
+ public void isWhitelisted_shouldWhitelistDefaultSms() {
+ final String testSms = "com.android.test.defaultsms";
+ ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
+
+ assertThat(mPowerWhitelistBackend.isWhitelisted(testSms)).isTrue();
+ }
+
+ @Test
+ public void isWhitelisted_shouldWhitelistDefaultDialer() {
+ final String testDialer = "com.android.test.defaultdialer";
+ ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
+
+ assertThat(mPowerWhitelistBackend.isWhitelisted(testDialer)).isTrue();
}
@Test
@@ -101,7 +134,7 @@
@Test
public void testIsSystemWhitelistedExceptIdle_onePackage() throws Exception {
- doReturn(new String[]{PACKAGE_TWO}).when(
+ doReturn(new String[] {PACKAGE_TWO}).when(
mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
mPowerWhitelistBackend.refreshList();
@@ -111,7 +144,7 @@
@Test
public void testIsSystemWhitelistedExceptIdle_packageArray() throws Exception {
- doReturn(new String[]{PACKAGE_TWO}).when(
+ doReturn(new String[] {PACKAGE_TWO}).when(
mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
mPowerWhitelistBackend.refreshList();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
new file mode 100644
index 0000000..f4afdb1
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
@@ -0,0 +1,44 @@
+/*
+ * 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.settingslib.testutils.shadow;
+
+import android.content.Context;
+import android.telecom.DefaultDialerManager;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(DefaultDialerManager.class)
+public class ShadowDefaultDialerManager {
+
+ private static String sDefaultDailer;
+
+ @Resetter
+ public void reset() {
+ sDefaultDailer = null;
+ }
+
+ @Implementation
+ public static String getDefaultDialerApplication(Context context) {
+ return sDefaultDailer;
+ }
+
+ public static void setDefaultDialerApplication(String dialer) {
+ sDefaultDailer = dialer;
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java
new file mode 100644
index 0000000..dd7b007
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java
@@ -0,0 +1,46 @@
+/*
+ * 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.settingslib.testutils.shadow;
+
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.internal.telephony.SmsApplication;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(SmsApplication.class)
+public class ShadowSmsApplication {
+
+ private static ComponentName sDefaultSmsApplication;
+
+ @Resetter
+ public void reset() {
+ sDefaultSmsApplication = null;
+ }
+
+ @Implementation
+ public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
+ return sDefaultSmsApplication;
+ }
+
+ public static void setDefaultSmsApplication(ComponentName cn) {
+ sDefaultSmsApplication = cn;
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 28e8db9..e1a602b 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -214,4 +214,7 @@
<!-- Default for Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS -->
<string name="def_backup_agent_timeout_parameters"></string>
+
+ <!-- Default for Settings.System.VIBRATE_WHEN_RINGING -->
+ <bool name="def_vibrate_when_ringing">false</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index fbe52d1..960d305 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2935,7 +2935,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 168;
+ private static final int SETTINGS_VERSION = 169;
private final int mUserId;
@@ -3805,6 +3805,21 @@
currentVersion = 168;
}
+ if (currentVersion == 168) {
+ // Version 168: by default, vibrate for phone calls
+ final SettingsState systemSettings = getSystemSettingsLocked(userId);
+ final Setting currentSetting = systemSettings.getSettingLocked(
+ Settings.System.VIBRATE_WHEN_RINGING);
+ if (currentSetting.isNull()) {
+ systemSettings.insertSettingLocked(
+ Settings.System.VIBRATE_WHEN_RINGING,
+ getContext().getResources().getBoolean(
+ R.bool.def_vibrate_when_ringing) ? "1" : "0",
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ currentVersion = 169;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 89f9e1f..9a3bdf2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -867,6 +867,8 @@
<!-- The size of corner radius of the arrow in the onboarding toast. -->
<dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen>
+ <!-- The start margin of quick scrub onboarding toast. -->
+ <dimen name="recents_quick_scrub_onboarding_margin_start">8dp</dimen>
<!-- The min alpha to apply to a task affiliation group color. -->
<item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 8cfba2c..ab82269 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -184,9 +184,15 @@
return;
}
boolean selected = mLastExpansion == 1f;
+
+ // Disable accessibility temporarily while we update selected state purely for the
+ // marquee. This will ensure that accessibility doesn't announce the TYPE_VIEW_SELECTED
+ // event on any of the children.
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
for (int i = 0; i < mPages.size(); i++) {
mPages.get(i).setSelected(i == getCurrentItem() ? selected : false);
}
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
}
public void setPageListener(PageListener listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 086c87b..8d8e206 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -393,7 +393,20 @@
if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- mWindowManager.addView(mLayout, getWindowLayoutParams());
+ final int gravity;
+ final int x;
+ if (stringRes == R.string.recents_swipe_up_onboarding) {
+ gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+ x = 0;
+ } else {
+ int layoutDirection =
+ mContext.getResources().getConfiguration().getLayoutDirection();
+ gravity = Gravity.BOTTOM | (layoutDirection == View.LAYOUT_DIRECTION_LTR
+ ? Gravity.LEFT : Gravity.RIGHT);
+ x = mContext.getResources().getDimensionPixelSize(
+ R.dimen.recents_quick_scrub_onboarding_margin_start);
+ }
+ mWindowManager.addView(mLayout, getWindowLayoutParams(gravity, x));
mLayout.setAlpha(0);
mLayout.animate()
.alpha(1f)
@@ -459,19 +472,19 @@
pw.println(" }");
}
- private WindowManager.LayoutParams getWindowLayoutParams() {
+ private WindowManager.LayoutParams getWindowLayoutParams(int gravity, int x) {
int flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
- 0, -mNavBarHeight / 2,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ x, -mNavBarHeight / 2,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
flags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("RecentsOnboarding");
- lp.gravity = Gravity.BOTTOM;
+ lp.gravity = gravity;
return lp;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 03791c7..91a4dda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -182,6 +182,9 @@
}
}
if (mReplyAction != null) {
+ // Let's reset the view on update, assuming the new pending intent isn't cancelled
+ // anymore. The color filter automatically resets when it's updated.
+ mReplyAction.setEnabled(true);
performOnPendingIntentCancellation(mReplyAction, () -> {
if (mReplyAction != null && mReplyAction.isEnabled()) {
mReplyAction.setEnabled(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 8ede224..879ac92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -16,11 +16,8 @@
package com.android.systemui.statusbar.notification;
-import android.util.ArraySet;
import android.util.Pools;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.ProgressBar;
@@ -411,7 +408,8 @@
mOwnPosition[1] -= (1.0f - mTransformedView.getScaleY()) * mTransformedView.getPivotY();
// Remove local translations
- mOwnPosition[1] -= MessagingPropertyAnimator.getLocalTranslationY(mTransformedView);
+ mOwnPosition[1] -= MessagingPropertyAnimator.getTop(mTransformedView)
+ - MessagingPropertyAnimator.getLayoutTop(mTransformedView);
return mOwnPosition;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 3c0b226..894ea62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -114,6 +114,10 @@
return mVisibility != null ? mVisibility : View.VISIBLE;
}
+ public boolean isVisible() {
+ return getVisibility() == View.VISIBLE;
+ }
+
public float getAlpha() {
return mAlpha != null ? mAlpha : 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6c66cab..0fd8df0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -336,13 +336,14 @@
int x = (int) event.getX();
int y = (int) event.getY();
mDownHitTarget = HIT_TARGET_NONE;
- if (mBackButtonBounds.contains(x, y)) {
+ if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_BACK;
- } else if (mHomeButtonBounds.contains(x, y)) {
+ } else if (getHomeButton().isVisible() && mHomeButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_HOME;
- } else if (mRecentsButtonBounds.contains(x, y)) {
+ } else if (getRecentsButton().isVisible() && mRecentsButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_OVERVIEW;
- } else if (mRotationButtonBounds.contains(x, y)) {
+ } else if (getRotateSuggestionButton().isVisible()
+ && mRotationButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_ROTATION;
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 5f5d12e..5001d4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -173,11 +173,13 @@
|| mStatusBar.isFullScreenUserSwitcherState()) {
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
} else if (mShowing && !mDozing) {
- mBouncer.setExpansion(expansion);
+ if (!isWakeAndUnlocking()) {
+ mBouncer.setExpansion(expansion);
+ }
if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking
&& mStatusBar.isKeyguardCurrentlySecure()
&& !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
- mBouncer.show(false /* resetSecuritySelection */, false /* animated */);
+ mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 8340ab2..85135ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -16,14 +16,12 @@
package com.android.systemui.statusbar.phone;
-import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -170,6 +168,15 @@
verify(mBouncer, never()).setExpansion(eq(0.5f));
}
+ @Test
+ public void onPanelExpansionChanged_neverTranslatesBouncerWhenWakeAndUnlock() {
+ when(mFingerprintUnlockController.getMode())
+ .thenReturn(FingerprintUnlockController.MODE_WAKE_AND_UNLOCK);
+ mStatusBarKeyguardViewManager.onPanelExpansionChanged(KeyguardBouncer.EXPANSION_VISIBLE,
+ false /* tracking */);
+ verify(mBouncer, never()).setExpansion(anyFloat());
+ }
+
private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 3beebcb..aa86ea8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -812,11 +812,12 @@
resOps = new ArrayList<>();
for (int j=0; j<pkgOps.size(); j++) {
Op curOp = pkgOps.valueAt(j);
- long duration = curOp.duration == -1
+ final boolean running = curOp.duration == -1;
+ long duration = running
? (elapsedNow - curOp.startRealtime)
: curOp.duration;
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
- curOp.rejectTime, (int) duration, curOp.proxyUid,
+ curOp.rejectTime, (int) duration, running, curOp.proxyUid,
curOp.proxyPackageName));
}
} else {
@@ -826,11 +827,12 @@
if (resOps == null) {
resOps = new ArrayList<>();
}
- long duration = curOp.duration == -1
+ final boolean running = curOp.duration == -1;
+ final long duration = running
? (elapsedNow - curOp.startRealtime)
: curOp.duration;
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
- curOp.rejectTime, (int) duration, curOp.proxyUid,
+ curOp.rejectTime, (int) duration, running, curOp.proxyUid,
curOp.proxyPackageName));
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4c2a940..ca715b5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -119,7 +119,7 @@
// How long the startForegroundService() grace period is to get around to
// calling startForeground() before we ANR + stop it.
- static final int SERVICE_START_FOREGROUND_TIMEOUT = 5*1000;
+ static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;
final ActivityManagerService mAm;
@@ -501,6 +501,18 @@
}
}
+ // At this point we've applied allowed-to-start policy based on whether this was
+ // an ordinary startService() or a startForegroundService(). Now, only require that
+ // the app follow through on the startForegroundService() -> startForeground()
+ // contract if it actually targets O+.
+ if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {
+ if (DEBUG_BACKGROUND_CHECK || DEBUG_FOREGROUND_SERVICE) {
+ Slog.i(TAG, "startForegroundService() but host targets "
+ + r.appInfo.targetSdkVersion + " - not requiring startForeground()");
+ }
+ fgRequired = false;
+ }
+
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 16f4585..d456f62 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -2413,11 +2413,16 @@
}
// Compute configuration based on max supported width and height.
- outBounds.set(0, 0, maxActivityWidth, maxActivityHeight);
- // Position the activity frame on the opposite side of the nav bar.
- final int navBarPosition = service.mWindowManager.getNavBarPosition();
- final int left = navBarPosition == NAV_BAR_LEFT ? appBounds.right - outBounds.width() : 0;
- outBounds.offsetTo(left, 0 /* top */);
+ // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
+ // away later in StackWindowController.adjustConfigurationForBounds(). Otherwise, the app
+ // bounds would end up too small.
+ outBounds.set(0, 0, maxActivityWidth + appBounds.left, maxActivityHeight + appBounds.top);
+
+ if (service.mWindowManager.getNavBarPosition() == NAV_BAR_LEFT) {
+ // Position the activity frame on the opposite side of the nav bar.
+ outBounds.left = appBounds.right - maxActivityWidth;
+ outBounds.right = appBounds.right;
+ }
}
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 4e6307d..0f8c526 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1015,26 +1015,25 @@
locationListener = mFusedLocationListener;
}
- if (!locationManager.isProviderEnabled(provider)) {
- Log.w(TAG, "Unable to request location since " + provider
- + " provider does not exist or is not enabled.");
- return;
- }
-
Log.i(TAG,
String.format(
"GNSS HAL Requesting location updates from %s provider for %d millis.",
provider, durationMillis));
- locationManager.requestLocationUpdates(provider,
- LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
- locationListener, mHandler.getLooper());
- locationListener.numLocationUpdateRequest++;
- mHandler.postDelayed(() -> {
- if (--locationListener.numLocationUpdateRequest == 0) {
- Log.i(TAG, String.format("Removing location updates from %s provider.", provider));
- locationManager.removeUpdates(locationListener);
- }
- }, durationMillis);
+ try {
+ locationManager.requestLocationUpdates(provider,
+ LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
+ locationListener, mHandler.getLooper());
+ locationListener.numLocationUpdateRequest++;
+ mHandler.postDelayed(() -> {
+ if (--locationListener.numLocationUpdateRequest == 0) {
+ Log.i(TAG,
+ String.format("Removing location updates from %s provider.", provider));
+ locationManager.removeUpdates(locationListener);
+ }
+ }, durationMillis);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Unable to request location.", e);
+ }
}
private void injectBestLocation(Location location) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e810b1a..d496ab6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17260,17 +17260,6 @@
+ "Persistent apps are not updateable.");
return;
}
- // Prevent apps from downgrading their targetSandbox.
- final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
- final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
- if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
- res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
- "Package " + pkg.packageName + " new target sandbox "
- + newTargetSandbox + " is incompatible with the previous value of"
- + oldTargetSandbox + ".");
- return;
- }
-
// Prevent installing of child packages
if (oldPackage.parentPackage != null) {
res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 91ef3d4..ed2b79e 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -392,7 +392,7 @@
mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true);
mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true);
mAodDisabled = parser.getBoolean(KEY_AOD_DISABLED, true);
- mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, true);
+ mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, false);
// Get default value from Settings.Secure
final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index b8431b1..65c8e96 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -22,7 +22,9 @@
import static com.android.server.wm.AnimationSpecProto.ALPHA;
import android.graphics.Rect;
+import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
@@ -171,14 +173,18 @@
*/
private DimState getDimState(WindowContainer container) {
if (mDimState == null) {
- final SurfaceControl ctl = makeDimLayer();
- mDimState = new DimState(ctl);
- /**
- * See documentation on {@link #dimAbove} to understand lifecycle management of Dim's
- * via state resetting for Dim's with containers.
- */
- if (container == null) {
- mDimState.mDontReset = true;
+ try {
+ final SurfaceControl ctl = makeDimLayer();
+ mDimState = new DimState(ctl);
+ /**
+ * See documentation on {@link #dimAbove} to understand lifecycle management of
+ * Dim's via state resetting for Dim's with containers.
+ */
+ if (container == null) {
+ mDimState.mDontReset = true;
+ }
+ } catch (Surface.OutOfResourcesException e) {
+ Log.w(TAG, "OutOfResourcesException creating dim surface");
}
}
@@ -189,6 +195,11 @@
private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
float alpha) {
final DimState d = getDimState(container);
+
+ if (d == null) {
+ return;
+ }
+
if (container != null) {
// The dim method is called from WindowState.prepareSurfaces(), which is always called
// in the correct Z from lowest Z to highest. This ensures that the dim layer is always
@@ -208,10 +219,11 @@
* @param t A Transaction in which to finish the dim.
*/
void stopDim(SurfaceControl.Transaction t) {
- DimState d = getDimState(null);
- t.hide(d.mDimLayer);
- d.isVisible = false;
- d.mDontReset = false;
+ if (mDimState != null) {
+ t.hide(mDimState.mDimLayer);
+ mDimState.isVisible = false;
+ mDimState.mDontReset = false;
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 7211533..2bfff26 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -206,6 +206,9 @@
}
}
});
+ a.mAnim = anim;
+ mRunningAnimations.put(a.mLeash, a);
+
anim.start();
if (a.mAnimSpec.canSkipFirstFrame()) {
// If we can skip the first frame, we start one frame later.
@@ -215,8 +218,6 @@
// Immediately start the animation by manually applying an animation frame. Otherwise, the
// start time would only be set in the next frame, leading to a delay.
anim.doAnimationFrame(mChoreographer.getFrameTime());
- a.mAnim = anim;
- mRunningAnimations.put(a.mLeash, a);
}
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index c366e4d..7b775f5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -54,7 +54,7 @@
static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
static final boolean DEBUG_STARTING_WINDOW = DEBUG_STARTING_WINDOW_VERBOSE || false;
static final boolean DEBUG_WALLPAPER = false;
- static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
+ static final boolean DEBUG_WALLPAPER_LIGHT = true || DEBUG_WALLPAPER;
static final boolean DEBUG_DRAG = false;
static final boolean DEBUG_SCREEN_ON = false;
static final boolean DEBUG_SCREENSHOT = false;
diff --git a/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
index ea0fe45..7f397d6 100644
--- a/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -36,6 +38,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+
/**
* Tests app ops version upgrades
*/
@@ -107,6 +111,46 @@
verifyNoMoreInteractions(listener);
}
+ @Test
+ public void testIsRunning() throws Exception {
+ final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ // Start the op
+ appOpsManager.startOp(AppOpsManager.OP_CAMERA);
+
+ assertTrue("Camera should be running", isCameraOn(appOpsManager));
+
+ // Finish the op
+ appOpsManager.finishOp(AppOpsManager.OP_CAMERA);
+
+ assertFalse("Camera should not be running", isCameraOn(appOpsManager));
+ }
+
+ private boolean isCameraOn(AppOpsManager appOpsManager) {
+ List<AppOpsManager.PackageOps> packages
+ = appOpsManager.getPackagesForOps(new int[] {AppOpsManager.OP_CAMERA});
+ // AppOpsManager can return null when there is no requested data.
+ if (packages != null) {
+ final int numPackages = packages.size();
+ for (int packageInd = 0; packageInd < numPackages; packageInd++) {
+ AppOpsManager.PackageOps packageOp = packages.get(packageInd);
+ List<AppOpsManager.OpEntry> opEntries = packageOp.getOps();
+ if (opEntries != null) {
+ final int numOps = opEntries.size();
+ for (int opInd = 0; opInd < numOps; opInd++) {
+ AppOpsManager.OpEntry opEntry = opEntries.get(opInd);
+ if (opEntry.getOp() == AppOpsManager.OP_CAMERA) {
+ if (opEntry.isRunning()) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
private static Context getContext() {
return InstrumentationRegistry.getContext();
}