summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/camera2/extension/CameraOutputConfig.aidl4
-rw-r--r--core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java94
-rw-r--r--core/java/android/hardware/display/DisplayManager.java14
-rw-r--r--core/java/android/view/autofill/AutofillManager.java8
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java17
-rw-r--r--core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java6
-rw-r--r--core/java/com/android/internal/app/ChooserRecyclerViewAccessibilityDelegate.java92
-rw-r--r--core/java/com/android/internal/app/SuggestedLocaleAdapter.java97
-rw-r--r--core/java/com/android/internal/view/inline/InlineTooltipUi.java154
-rw-r--r--core/java/com/android/internal/widget/MessagingImageMessage.java7
-rw-r--r--core/res/res/layout/chooser_grid.xml2
-rw-r--r--core/res/res/layout/language_picker_section_header.xml1
-rw-r--r--core/res/res/layout/resolver_list.xml2
-rw-r--r--core/res/res/layout/resolver_profile_tab_button.xml2
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/dimens.xml1
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHost.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt85
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt86
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java15
-rw-r--r--packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java66
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java34
-rw-r--r--services/companion/java/com/android/server/companion/CompanionApplicationController.java6
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java15
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java94
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java26
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerShellCommand.java17
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java18
-rw-r--r--services/core/java/com/android/server/display/RampAnimator.java35
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecNetwork.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java21
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java19
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java9
-rw-r--r--services/core/xsd/display-device-config/display-device-config.xsd10
-rw-r--r--services/core/xsd/display-device-config/schema/current.txt4
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java29
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java127
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java5
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java47
-rw-r--r--telephony/java/android/telephony/data/DataProfile.java7
53 files changed, 1085 insertions, 449 deletions
diff --git a/core/java/android/hardware/camera2/extension/CameraOutputConfig.aidl b/core/java/android/hardware/camera2/extension/CameraOutputConfig.aidl
index a61bb3304c12..34d016adbc06 100644
--- a/core/java/android/hardware/camera2/extension/CameraOutputConfig.aidl
+++ b/core/java/android/hardware/camera2/extension/CameraOutputConfig.aidl
@@ -15,8 +15,8 @@
*/
package android.hardware.camera2.extension;
-import android.hardware.camera2.extension.Size;
import android.hardware.camera2.extension.OutputConfigId;
+import android.hardware.camera2.extension.Size;
import android.view.Surface;
/** @hide */
@@ -35,5 +35,5 @@ parcelable CameraOutputConfig
OutputConfigId outputId;
int surfaceGroupId;
String physicalCameraId;
- List<OutputConfigId> surfaceSharingOutputConfigs;
+ List<CameraOutputConfig> sharedSurfaceConfigs;
}
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index 5503e2834d98..c8dc2d0b0b91 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -217,60 +217,30 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
CameraSessionConfig sessionConfig = mSessionProcessor.initSession(mCameraDevice.getId(),
previewSurface, captureSurface);
List<CameraOutputConfig> outputConfigs = sessionConfig.outputConfigs;
- // map camera output ids to output configurations
- HashMap<Integer, OutputConfiguration> cameraOutputs = new HashMap<>();
- for (CameraOutputConfig output : outputConfigs) {
- OutputConfiguration cameraOutput = null;
- switch(output.type) {
- case CameraOutputConfig.TYPE_SURFACE:
- if (output.surface == null) {
- Log.w(TAG, "Unsupported client output id: " + output.outputId.id +
- ", skipping!");
- continue;
- }
- cameraOutput = new OutputConfiguration(output.surfaceGroupId,
- output.surface);
- break;
- case CameraOutputConfig.TYPE_IMAGEREADER:
- if ((output.imageFormat == ImageFormat.UNKNOWN) || (output.size.width <= 0) ||
- (output.size.height <= 0)) {
- Log.w(TAG, "Unsupported client output id: " + output.outputId.id +
- ", skipping!");
- continue;
- }
- ImageReader reader = ImageReader.newInstance(output.size.width,
- output.size.height, output.imageFormat, output.capacity);
- mReaderMap.put(output.outputId.id, reader);
- cameraOutput = new OutputConfiguration(output.surfaceGroupId,
- reader.getSurface());
- break;
- case CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER:
- // Support for multi-resolution outputs to be added in future releases
- default:
- throw new IllegalArgumentException("Unsupported output config type: " +
- output.type);
- }
- cameraOutput.setPhysicalCameraId(output.physicalCameraId);
- cameraOutputs.put(output.outputId.id, cameraOutput);
- }
-
ArrayList<OutputConfiguration> outputList = new ArrayList<>();
for (CameraOutputConfig output : outputConfigs) {
- if (!cameraOutputs.containsKey(output.outputId.id)) {
- // Shared surface already removed by a previous iteration
+ Surface outputSurface = initializeSurfrace(output);
+ if (outputSurface == null) {
continue;
}
- OutputConfiguration outConfig = cameraOutputs.get(output.outputId.id);
- if ((output.surfaceSharingOutputConfigs != null) &&
- !output.surfaceSharingOutputConfigs.isEmpty()) {
- outConfig.enableSurfaceSharing();
- for (OutputConfigId outputId : output.surfaceSharingOutputConfigs) {
- outConfig.addSurface(cameraOutputs.get(outputId.id).getSurface());
- cameraOutputs.remove(outputId.id);
+ OutputConfiguration cameraOutput = new OutputConfiguration(output.surfaceGroupId,
+ outputSurface);
+
+ if ((output.sharedSurfaceConfigs != null) && !output.sharedSurfaceConfigs.isEmpty()) {
+ cameraOutput.enableSurfaceSharing();
+ for (CameraOutputConfig sharedOutputConfig : output.sharedSurfaceConfigs) {
+ Surface sharedSurface = initializeSurfrace(sharedOutputConfig);
+ if (sharedSurface == null) {
+ continue;
+ }
+ cameraOutput.addSurface(sharedSurface);
+ mCameraConfigMap.put(sharedSurface, sharedOutputConfig);
}
}
- outputList.add(outConfig);
- mCameraConfigMap.put(outConfig.getSurface(), output);
+
+ cameraOutput.setPhysicalCameraId(output.physicalCameraId);
+ outputList.add(cameraOutput);
+ mCameraConfigMap.put(cameraOutput.getSurface(), output);
}
SessionConfiguration sessionConfiguration = new SessionConfiguration(
@@ -995,4 +965,32 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
CameraMetadataNative.update(ret.getNativeMetadata(), request.parameters);
return ret;
}
+
+ private Surface initializeSurfrace(CameraOutputConfig output) {
+ switch(output.type) {
+ case CameraOutputConfig.TYPE_SURFACE:
+ if (output.surface == null) {
+ Log.w(TAG, "Unsupported client output id: " + output.outputId.id +
+ ", skipping!");
+ return null;
+ }
+ return output.surface;
+ case CameraOutputConfig.TYPE_IMAGEREADER:
+ if ((output.imageFormat == ImageFormat.UNKNOWN) || (output.size.width <= 0) ||
+ (output.size.height <= 0)) {
+ Log.w(TAG, "Unsupported client output id: " + output.outputId.id +
+ ", skipping!");
+ return null;
+ }
+ ImageReader reader = ImageReader.newInstance(output.size.width,
+ output.size.height, output.imageFormat, output.capacity);
+ mReaderMap.put(output.outputId.id, reader);
+ return reader.getSurface();
+ case CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER:
+ // Support for multi-resolution outputs to be added in future releases
+ default:
+ throw new IllegalArgumentException("Unsupported output config type: " +
+ output.type);
+ }
+ }
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 731ea9207283..eadcac91dcd7 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -108,6 +108,17 @@ public final class DisplayManager {
public static final String DISPLAY_CATEGORY_PRESENTATION =
"android.hardware.display.category.PRESENTATION";
+ /**
+ * Display category: All displays, including disabled displays.
+ * <p>
+ * This returns all displays, including currently disabled and inaccessible displays.
+ *
+ * @see #getDisplays(String)
+ * @hide
+ */
+ public static final String DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED =
+ "android.hardware.display.category.ALL_INCLUDING_DISABLED";
+
/** @hide **/
@IntDef(prefix = "VIRTUAL_DISPLAY_FLAG_", flag = true, value = {
VIRTUAL_DISPLAY_FLAG_PUBLIC,
@@ -552,7 +563,8 @@ public final class DisplayManager {
final int[] displayIds = mGlobal.getDisplayIds();
synchronized (mLock) {
try {
- if (category == null) {
+ if (category == null
+ || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
addAllDisplaysLocked(mTempDisplays, displayIds);
} else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index dcedb3083f76..7353bbccf77c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -506,6 +506,14 @@ public final class AutofillManager {
public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS =
"autofill_dialog_hints";
+ /**
+ * Sets a value of delay time to show up the inline tooltip view.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY =
+ "autofill_inline_tooltip_first_show_delay";
+
private static final String DIALOG_HINTS_DELIMITER = ":";
/** @hide */
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 468293862cd3..61c844ac8170 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1002,6 +1002,7 @@ public class ChooserActivity extends ResolverActivity implements
mMaxTargetsPerRow = getResources().getInteger(R.integer.config_chooser_max_targets_per_row);
adjustPreviewWidth(newConfig.orientation, null);
updateStickyContentPreview();
+ updateTabPadding();
}
private boolean shouldDisplayLandscape(int orientation) {
@@ -1024,6 +1025,20 @@ public class ChooserActivity extends ResolverActivity implements
updateLayoutWidth(R.id.content_preview_file_layout, width, parent);
}
+ private void updateTabPadding() {
+ if (shouldShowTabs()) {
+ View tabs = findViewById(R.id.tabs);
+ float iconSize = getResources().getDimension(R.dimen.chooser_icon_size);
+ // The entire width consists of icons or padding. Divide the item padding in half to get
+ // paddingHorizontal.
+ float padding = (tabs.getWidth() - mMaxTargetsPerRow * iconSize)
+ / mMaxTargetsPerRow / 2;
+ // Subtract the margin the buttons already have.
+ padding -= getResources().getDimension(R.dimen.resolver_profile_tab_margin);
+ tabs.setPadding((int) padding, 0, (int) padding, 0);
+ }
+ }
+
private void updateLayoutWidth(int layoutResourceId, int width, View parent) {
View view = parent.findViewById(layoutResourceId);
if (view != null && view.getLayoutParams() != null) {
@@ -2480,6 +2495,8 @@ public class ChooserActivity extends ResolverActivity implements
recyclerView.setAdapter(gridAdapter);
((GridLayoutManager) recyclerView.getLayoutManager()).setSpanCount(
mMaxTargetsPerRow);
+
+ updateTabPadding();
}
UserHandle currentUserHandle = mChooserMultiProfilePagerAdapter.getCurrentUserHandle();
diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
index d35d5ca6fca7..e6cc62472f5c 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -86,7 +86,11 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
final LayoutInflater inflater = LayoutInflater.from(getContext());
final ViewGroup rootView =
(ViewGroup) inflater.inflate(R.layout.chooser_list_per_profile, null, false);
- return new ChooserProfileDescriptor(rootView, adapter);
+ ChooserProfileDescriptor profileDescriptor =
+ new ChooserProfileDescriptor(rootView, adapter);
+ profileDescriptor.recyclerView.setAccessibilityDelegateCompat(
+ new ChooserRecyclerViewAccessibilityDelegate(profileDescriptor.recyclerView));
+ return profileDescriptor;
}
RecyclerView getListViewForIndex(int index) {
diff --git a/core/java/com/android/internal/app/ChooserRecyclerViewAccessibilityDelegate.java b/core/java/com/android/internal/app/ChooserRecyclerViewAccessibilityDelegate.java
new file mode 100644
index 000000000000..66c9838bf71b
--- /dev/null
+++ b/core/java/com/android/internal/app/ChooserRecyclerViewAccessibilityDelegate.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+
+import com.android.internal.widget.RecyclerView;
+import com.android.internal.widget.RecyclerViewAccessibilityDelegate;
+
+class ChooserRecyclerViewAccessibilityDelegate extends RecyclerViewAccessibilityDelegate {
+ private final Rect mTempRect = new Rect();
+ private final int[] mConsumed = new int[2];
+
+ ChooserRecyclerViewAccessibilityDelegate(RecyclerView recyclerView) {
+ super(recyclerView);
+ }
+
+ @Override
+ public boolean onRequestSendAccessibilityEvent(
+ @NonNull ViewGroup host,
+ @NonNull View view,
+ @NonNull AccessibilityEvent event) {
+ boolean result = super.onRequestSendAccessibilityEvent(host, view, event);
+ if (result && event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
+ ensureViewOnScreenVisibility((RecyclerView) host, view);
+ }
+ return result;
+ }
+
+ /**
+ * Bring the view that received accessibility focus on the screen.
+ * The method's logic is based on a model where RecyclerView is a child of another scrollable
+ * component (ResolverDrawerLayout) and can be partially scrolled off the screen. In that case,
+ * RecyclerView's children that are positioned fully within RecyclerView bounds but scrolled
+ * out of the screen by the outer component, when selected by the accessibility navigation will
+ * remain off the screen (as neither components detect such specific case).
+ * If the view that receiving accessibility focus is scrolled of the screen, perform the nested
+ * scrolling to make in visible.
+ */
+ private void ensureViewOnScreenVisibility(RecyclerView recyclerView, View view) {
+ View child = recyclerView.findContainingItemView(view);
+ if (child == null) {
+ return;
+ }
+ recyclerView.getBoundsOnScreen(mTempRect, true);
+ int recyclerOnScreenTop = mTempRect.top;
+ int recyclerOnScreenBottom = mTempRect.bottom;
+ child.getBoundsOnScreen(mTempRect);
+ int dy = 0;
+ // if needed, do the page-length scroll instead of just a row-length scroll as
+ // ResolverDrawerLayout snaps to the compact view and the row-length scroll can be snapped
+ // back right away.
+ if (mTempRect.top < recyclerOnScreenTop) {
+ // snap to the bottom
+ dy = mTempRect.bottom - recyclerOnScreenBottom;
+ } else if (mTempRect.bottom > recyclerOnScreenBottom) {
+ // snap to the top
+ dy = mTempRect.top - recyclerOnScreenTop;
+ }
+ nestedVerticalScrollBy(recyclerView, dy);
+ }
+
+ private void nestedVerticalScrollBy(RecyclerView recyclerView, int dy) {
+ if (dy == 0) {
+ return;
+ }
+ recyclerView.startNestedScroll(View.SCROLL_AXIS_VERTICAL);
+ if (recyclerView.dispatchNestedPreScroll(0, dy, mConsumed, null)) {
+ dy -= mConsumed[1];
+ }
+ recyclerView.scrollBy(0, dy);
+ recyclerView.stopNestedScroll();
+ }
+}
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index 5fe111148c91..ff188dc6f2b9 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -27,6 +27,7 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.R;
@@ -104,6 +105,13 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
@Override
public int getItemViewType(int position) {
if (!showHeaders()) {
+ LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
+ if (item.isSystemLocale()) {
+ return TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER;
+ }
+ if (item.isAppCurrentLocale()) {
+ return TYPE_CURRENT_LOCALE;
+ }
return TYPE_LOCALE;
} else {
if (position == 0) {
@@ -193,15 +201,11 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
}
int itemType = getItemViewType(position);
+ View itemView = getNewViewIfNeeded(convertView, parent, itemType, position);
switch (itemType) {
case TYPE_HEADER_SUGGESTED: // intentional fallthrough
case TYPE_HEADER_ALL_OTHERS:
- // Covers both null, and "reusing" a wrong kind of view
- if (!(convertView instanceof TextView)) {
- convertView = mInflater.inflate(R.layout.language_picker_section_header,
- parent, false);
- }
- TextView textView = (TextView) convertView;
+ TextView textView = (TextView) itemView;
if (itemType == TYPE_HEADER_SUGGESTED) {
setTextTo(textView, R.string.language_picker_section_suggested);
} else {
@@ -215,38 +219,77 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
mDisplayLocale != null ? mDisplayLocale : Locale.getDefault());
break;
case TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER:
- if (!(convertView instanceof ViewGroup)) {
- TextView title;
- if (((LocaleStore.LocaleInfo)getItem(position)).isAppCurrentLocale()) {
- convertView = mInflater.inflate(
- R.layout.app_language_picker_current_locale_item, parent, false);
- title = convertView.findViewById(R.id.language_picker_item);
- addStateDescriptionIntoCurrentLocaleItem(convertView);
- } else {
- convertView = mInflater.inflate(
+ TextView title;
+ if (((LocaleStore.LocaleInfo)getItem(position)).isAppCurrentLocale()) {
+ title = itemView.findViewById(R.id.language_picker_item);
+ } else {
+ title = itemView.findViewById(R.id.locale);
+ }
+ title.setText(R.string.system_locale_title);
+ break;
+ case TYPE_CURRENT_LOCALE:
+ updateTextView(itemView,
+ itemView.findViewById(R.id.language_picker_item), position);
+ break;
+ default:
+ updateTextView(itemView, itemView.findViewById(R.id.locale), position);
+ break;
+ }
+ return itemView;
+ }
+
+ /** Check if the old view can be reused, otherwise create a new one. */
+ private View getNewViewIfNeeded(
+ View convertView, ViewGroup parent, int itemType, int position) {
+ View updatedView = convertView;
+ boolean shouldReuseView;
+ switch (itemType) {
+ case TYPE_HEADER_SUGGESTED: // intentional fallthrough
+ case TYPE_HEADER_ALL_OTHERS:
+ shouldReuseView = convertView instanceof TextView
+ && convertView.findViewById(R.id.language_picker_header) != null;
+ if (!shouldReuseView) {
+ updatedView = mInflater.inflate(
+ R.layout.language_picker_section_header, parent, false);
+ }
+ break;
+ case TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER:
+ if (((LocaleStore.LocaleInfo) getItem(position)).isAppCurrentLocale()) {
+ shouldReuseView = convertView instanceof LinearLayout
+ && convertView.findViewById(R.id.language_picker_item) != null;
+ if (!shouldReuseView) {
+ updatedView = mInflater.inflate(
+ R.layout.app_language_picker_current_locale_item,
+ parent, false);
+ addStateDescriptionIntoCurrentLocaleItem(updatedView);
+ }
+ } else {
+ shouldReuseView = convertView instanceof TextView
+ && convertView.findViewById(R.id.locale) != null;
+ if (!shouldReuseView) {
+ updatedView = mInflater.inflate(
R.layout.language_picker_item, parent, false);
- title = convertView.findViewById(R.id.locale);
}
- title.setText(R.string.system_locale_title);
}
break;
case TYPE_CURRENT_LOCALE:
- if (!(convertView instanceof ViewGroup)) {
- convertView = mInflater.inflate(
+ shouldReuseView = convertView instanceof LinearLayout
+ && convertView.findViewById(R.id.language_picker_item) != null;
+ if (!shouldReuseView) {
+ updatedView = mInflater.inflate(
R.layout.app_language_picker_current_locale_item, parent, false);
- addStateDescriptionIntoCurrentLocaleItem(convertView);
+ addStateDescriptionIntoCurrentLocaleItem(updatedView);
}
- updateTextView(
- convertView, convertView.findViewById(R.id.language_picker_item), position);
break;
default:
- // Covers both null, and "reusing" a wrong kind of view
- if (!(convertView instanceof ViewGroup)) {
- convertView = mInflater.inflate(R.layout.language_picker_item, parent, false);
+ shouldReuseView = convertView instanceof TextView
+ && convertView.findViewById(R.id.locale) != null;
+ if (!shouldReuseView) {
+ updatedView = mInflater.inflate(R.layout.language_picker_item, parent, false);
}
- updateTextView(convertView, convertView.findViewById(R.id.locale), position);
+ break;
}
- return convertView;
+ return updatedView;
}
private boolean showHeaders() {
diff --git a/core/java/com/android/internal/view/inline/InlineTooltipUi.java b/core/java/com/android/internal/view/inline/InlineTooltipUi.java
index 25fa678d0507..3eae89e350a0 100644
--- a/core/java/com/android/internal/view/inline/InlineTooltipUi.java
+++ b/core/java/com/android/internal/view/inline/InlineTooltipUi.java
@@ -15,24 +15,30 @@
*/
package com.android.internal.view.inline;
+import static android.view.autofill.AutofillManager.DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY;
import static android.view.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.ContextWrapper;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.transition.Transition;
import android.util.Slog;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.inline.InlineContentView;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
/**
* UI container for the inline suggestion tooltip.
@@ -40,6 +46,8 @@ import java.io.PrintWriter;
public final class InlineTooltipUi extends PopupWindow implements AutoCloseable {
private static final String TAG = "InlineTooltipUi";
+ private static final int FIRST_TIME_SHOW_DEFAULT_DELAY_MS = 250;
+
private final WindowManager mWm;
private final ViewGroup mContentContainer;
@@ -47,6 +55,16 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
private WindowManager.LayoutParams mWindowLayoutParams;
+ private DelayShowRunnable mDelayShowTooltip;
+
+ private boolean mHasEverDetached;
+
+ private boolean mDelayShowAtStart = true;
+ private boolean mDelaying = false;
+ private int mShowDelayConfigMs;
+
+ private final Rect mTmpRect = new Rect();
+
private final View.OnAttachStateChangeListener mAnchorOnAttachStateChangeListener =
new View.OnAttachStateChangeListener() {
@Override
@@ -56,6 +74,7 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
@Override
public void onViewDetachedFromWindow(View v) {
+ mHasEverDetached = true;
dismiss();
}
};
@@ -66,6 +85,13 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ if (mHasEverDetached) {
+ // If the tooltip is ever detached, skip adjusting the position,
+ // because it only accepts to attach once and does not show again
+ // after detaching.
+ return;
+ }
+
if (mHeight != bottom - top) {
mHeight = bottom - top;
adjustPosition();
@@ -77,6 +103,13 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
mContentContainer = new LinearLayout(new ContextWrapper(context));
mWm = context.getSystemService(WindowManager.class);
+ // That's a default delay time, and it will scale via the value of
+ // Settings.Global.ANIMATOR_DURATION_SCALE
+ mShowDelayConfigMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY,
+ FIRST_TIME_SHOW_DEFAULT_DELAY_MS);
+
setTouchModal(false);
setOutsideTouchable(true);
setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
@@ -95,7 +128,7 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
@Override
public void close() {
- hide();
+ dismiss();
}
@Override
@@ -117,14 +150,57 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
* The effective {@code update} method that should be called by its clients.
*/
public void update(View anchor) {
+ if (anchor == null) {
+ final View oldAnchor = getAnchor();
+ if (oldAnchor != null) {
+ removeDelayShowTooltip(oldAnchor);
+ }
+ return;
+ }
+
+ if (mDelayShowAtStart) {
+ // To avoid showing when the anchor is doing the fade in animation. That will
+ // cause the tooltip to show in the wrong position and jump at the start.
+ mDelayShowAtStart = false;
+ mDelaying = true;
+
+ if (mDelayShowTooltip == null) {
+ mDelayShowTooltip = new DelayShowRunnable(anchor);
+ }
+
+ int delayTimeMs = mShowDelayConfigMs;
+ try {
+ final float scale = Settings.Global.getFloat(
+ anchor.getContext().getContentResolver(),
+ Settings.Global.ANIMATOR_DURATION_SCALE);
+ delayTimeMs *= scale;
+ } catch (Settings.SettingNotFoundException e) {
+ // do nothing
+ }
+ anchor.postDelayed(mDelayShowTooltip, delayTimeMs);
+ } else if (!mDelaying) {
+ // Note: If we are going to reuse the tooltip, we need to take care the delay in
+ // the case that update for the new anchor.
+ updateInner(anchor);
+ }
+ }
+
+ private void removeDelayShowTooltip(View anchor) {
+ if (mDelayShowTooltip != null) {
+ anchor.removeCallbacks(mDelayShowTooltip);
+ mDelayShowTooltip = null;
+ }
+ }
+
+ private void updateInner(View anchor) {
+ if (mHasEverDetached) {
+ return;
+ }
// set to the application type with the highest z-order
setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
- // The first time to show up, the height of tooltip is zero,
- // so set the offset Y to 2 * anchor height.
- final int achoredHeight = mContentContainer.getHeight();
- final int offsetY = (achoredHeight == 0)
- ? -anchor.getHeight() << 1 : -anchor.getHeight() - achoredHeight;
+ final int offsetY = -anchor.getHeight() - getPreferHeight(anchor);
+
if (!isShowing()) {
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
@@ -135,6 +211,34 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
}
}
+ private int getPreferHeight(View anchor) {
+ // The first time to show up, the height of tooltip is zero, so make its height
+ // the same as anchor.
+ final int achoredHeight = mContentContainer.getHeight();
+ return (achoredHeight == 0) ? anchor.getHeight() : achoredHeight;
+ }
+
+ @Override
+ protected boolean findDropDownPosition(View anchor, WindowManager.LayoutParams outParams,
+ int xOffset, int yOffset, int width, int height, int gravity, boolean allowScroll) {
+ boolean isAbove = super.findDropDownPosition(anchor, outParams, xOffset, yOffset, width,
+ height, gravity, allowScroll);
+ // Make the tooltips y fo position is above or under the parent of the anchor,
+ // otherwise suggestions doesn't clickable.
+ ViewParent parent = anchor.getParent();
+ if (parent instanceof View) {
+ final Rect r = mTmpRect;
+ ((View) parent).getGlobalVisibleRect(r);
+ if (isAbove) {
+ outParams.y = r.top - getPreferHeight(anchor);
+ } else {
+ outParams.y = r.bottom + 1;
+ }
+ }
+
+ return isAbove;
+ }
+
@Override
protected void update(View anchor, WindowManager.LayoutParams params) {
// update content view for the anchor is scrolling
@@ -175,7 +279,9 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
final View anchor = getAnchor();
if (anchor != null) {
anchor.removeOnAttachStateChangeListener(mAnchorOnAttachStateChangeListener);
+ removeDelayShowTooltip(anchor);
}
+ mHasEverDetached = true;
super.detachFromAnchor();
}
@@ -185,7 +291,6 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
return;
}
- setShowing(false);
setTransitioningToDismiss(true);
hide();
@@ -193,6 +298,7 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
if (getOnDismissListener() != null) {
getOnDismissListener().onDismiss();
}
+ super.dismiss();
}
private void adjustPosition() {
@@ -202,15 +308,15 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
}
private void show(WindowManager.LayoutParams params) {
- if (sVerbose) {
- Slog.v(TAG, "show()");
- }
mWindowLayoutParams = params;
try {
params.packageName = "android";
params.setTitle("Autofill Inline Tooltip"); // Title is set for debugging purposes
if (!mShowing) {
+ if (sVerbose) {
+ Slog.v(TAG, "show()");
+ }
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.privateFlags |=
@@ -232,11 +338,11 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
}
private void hide() {
- if (sVerbose) {
- Slog.v(TAG, "hide()");
- }
try {
if (mShowing) {
+ if (sVerbose) {
+ Slog.v(TAG, "hide()");
+ }
mContentContainer.removeOnLayoutChangeListener(mAnchoredOnLayoutChangeListener);
mWm.removeView(mContentContainer);
mShowing = false;
@@ -336,4 +442,26 @@ public final class InlineTooltipUi extends PopupWindow implements AutoCloseable
}
}
}
+
+ private class DelayShowRunnable implements Runnable {
+ WeakReference<View> mAnchor;
+
+ DelayShowRunnable(View anchor) {
+ mAnchor = new WeakReference<>(anchor);
+ }
+
+ @Override
+ public void run() {
+ mDelaying = false;
+ final View anchor = mAnchor.get();
+ if (anchor != null) {
+ updateInner(anchor);
+ }
+ }
+
+ public void setAnchor(View anchor) {
+ mAnchor.clear();
+ mAnchor = new WeakReference<>(anchor);
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java
index f7955c3f72da..8e7fe18b222b 100644
--- a/core/java/com/android/internal/widget/MessagingImageMessage.java
+++ b/core/java/com/android/internal/widget/MessagingImageMessage.java
@@ -226,6 +226,13 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ if (mDrawable == null) {
+ Log.e(TAG, "onMeasure() after recycle()!");
+ setMeasuredDimension(0, 0);
+ return;
+ }
+
if (mIsIsolated) {
// When isolated we have a fixed size, let's use that sizing.
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 6e3a11af27a7..b102b4bb2124 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -41,7 +41,7 @@
android:src="@drawable/ic_drag_handle"
android:layout_marginTop="@dimen/chooser_edge_margin_thin"
android:layout_marginBottom="@dimen/chooser_edge_margin_thin"
- android:tint="@color/lighter_gray"
+ android:tint="?attr/colorSurfaceVariant"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true" />
diff --git a/core/res/res/layout/language_picker_section_header.xml b/core/res/res/layout/language_picker_section_header.xml
index 4fa4d9b043c6..58042f9a42f8 100644
--- a/core/res/res/layout/language_picker_section_header.xml
+++ b/core/res/res/layout/language_picker_section_header.xml
@@ -24,4 +24,5 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:textColor="?android:attr/colorAccent"
android:textStyle="bold"
+ android:id="@+id/language_picker_header"
tools:text="@string/language_picker_section_all"/>
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 8480ec37a79e..6a200d05c2d7 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -90,11 +90,13 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
+ <!-- horizontal padding = 8dp content padding - 4dp margin that tab buttons have. -->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tabStripEnabled="false"
+ android:paddingHorizontal="4dp"
android:visibility="gone" />
<FrameLayout
android:id="@android:id/tabcontent"
diff --git a/core/res/res/layout/resolver_profile_tab_button.xml b/core/res/res/layout/resolver_profile_tab_button.xml
index 936c8e23b87a..fd168e6414f1 100644
--- a/core/res/res/layout/resolver_profile_tab_button.xml
+++ b/core/res/res/layout/resolver_profile_tab_button.xml
@@ -21,7 +21,7 @@
android:layout_height="36dp"
android:layout_weight="1"
android:layout_marginVertical="6dp"
- android:layout_marginHorizontal="4dp"
+ android:layout_marginHorizontal="@dimen/resolver_profile_tab_margin"
android:background="@drawable/resolver_profile_tab_bg"
android:textColor="@color/resolver_profile_tab_text"
android:textSize="@dimen/resolver_tab_text_size"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 16f14c9de606..0844dfd1112a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3000,6 +3000,10 @@
</string-array>
+ <!-- Whether to show a notification informing users about notification permission settings
+ upon upgrade to T from a pre-T version -->
+ <bool name="config_notificationReviewPermissions">false</bool>
+
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 43ca4f098ce7..bb36ededc581 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -962,6 +962,7 @@
<dimen name="resolver_title_padding_bottom">0dp</dimen>
<dimen name="resolver_empty_state_container_padding_top">48dp</dimen>
<dimen name="resolver_empty_state_container_padding_bottom">8dp</dimen>
+ <dimen name="resolver_profile_tab_margin">4dp</dimen>
<dimen name="chooser_action_button_icon_size">18dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e111ee184be1..96e8de0d2d64 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2266,6 +2266,7 @@
<java-symbol type="integer" name="config_screenshotChordKeyTimeout" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
<java-symbol type="array" name="config_notificationSignalExtractors" />
+ <java-symbol type="bool" name="config_notificationReviewPermissions" />
<java-symbol type="layout" name="notification_material_action" />
<java-symbol type="layout" name="notification_material_action_list" />
@@ -4315,6 +4316,7 @@
<java-symbol type="dimen" name="resolver_title_padding_bottom" />
<java-symbol type="dimen" name="resolver_empty_state_container_padding_top" />
<java-symbol type="dimen" name="resolver_empty_state_container_padding_bottom" />
+ <java-symbol type="dimen" name="resolver_profile_tab_margin" />
<java-symbol type="string" name="config_deviceSpecificDisplayAreaPolicyProvider" />
@@ -4789,6 +4791,7 @@
<java-symbol type="layout" name="app_language_picker_current_locale_item" />
<java-symbol type="id" name="system_locale_subtitle" />
<java-symbol type="id" name="language_picker_item" />
+ <java-symbol type="id" name="language_picker_header" />
<java-symbol type="dimen" name="status_bar_height_default" />
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index de30dbbe7e46..484294ab295b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -160,6 +160,15 @@ public class SplitDecorManager extends WindowlessWindowManager {
mBounds.set(newBounds);
}
+ final boolean show =
+ newBounds.width() > mBounds.width() || newBounds.height() > mBounds.height();
+ final boolean animate = show != mShown;
+ if (animate && mFadeAnimator != null && mFadeAnimator.isRunning()) {
+ // If we need to animate and animator still running, cancel it before we ensure both
+ // background and icon surfaces are non null for next animation.
+ mFadeAnimator.cancel();
+ }
+
if (mBackgroundLeash == null) {
mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
@@ -183,11 +192,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
newBounds.width() / 2 - mIconSize / 2,
newBounds.height() / 2 - mIconSize / 2);
- boolean show = newBounds.width() > mBounds.width() || newBounds.height() > mBounds.height();
- if (show != mShown) {
- if (mFadeAnimator != null && mFadeAnimator.isRunning()) {
- mFadeAnimator.cancel();
- }
+ if (animate) {
startFadeAnimation(show, false /* isResized */);
mShown = show;
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 345f8a3c15d6..3714c15af173 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -635,12 +635,13 @@ public class ClipboardOverlayController {
}
private Intent getRemoteCopyIntent(ClipData clipData) {
+ Intent nearbyIntent = new Intent(REMOTE_COPY_ACTION);
+
String remoteCopyPackage = mContext.getString(R.string.config_remoteCopyPackage);
- if (TextUtils.isEmpty(remoteCopyPackage)) {
- return null;
+ if (!TextUtils.isEmpty(remoteCopyPackage)) {
+ nearbyIntent.setComponent(ComponentName.unflattenFromString(remoteCopyPackage));
}
- Intent nearbyIntent = new Intent(REMOTE_COPY_ACTION);
- nearbyIntent.setComponent(ComponentName.unflattenFromString(remoteCopyPackage));
+
nearbyIntent.setClipData(clipData);
nearbyIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
index de2b5c9a4739..8bfb8aae5c91 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -199,14 +199,6 @@ class MediaHost constructor(
}
}
- override var squishFraction: Float = 1.0f
- set(value) {
- if (!value.equals(field)) {
- field = value
- changedListener?.invoke()
- }
- }
-
override var showsOnlyActiveMedia: Boolean = false
set(value) {
if (!value.equals(field)) {
@@ -257,7 +249,6 @@ class MediaHost constructor(
override fun copy(): MediaHostState {
val mediaHostState = MediaHostStateHolder()
mediaHostState.expansion = expansion
- mediaHostState.squishFraction = squishFraction
mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
mediaHostState.measurementInput = measurementInput?.copy()
mediaHostState.visible = visible
@@ -276,9 +267,6 @@ class MediaHost constructor(
if (expansion != other.expansion) {
return false
}
- if (squishFraction != other.squishFraction) {
- return false
- }
if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) {
return false
}
@@ -297,7 +285,6 @@ class MediaHost constructor(
override fun hashCode(): Int {
var result = measurementInput?.hashCode() ?: 0
result = 31 * result + expansion.hashCode()
- result = 31 * result + squishFraction.hashCode()
result = 31 * result + falsingProtectionNeeded.hashCode()
result = 31 * result + showsOnlyActiveMedia.hashCode()
result = 31 * result + if (visible) 1 else 2
@@ -338,11 +325,6 @@ interface MediaHostState {
var expansion: Float
/**
- * Fraction of the height animation.
- */
- var squishFraction: Float
-
- /**
* Is this host only showing active media or is it showing all of them including resumption?
*/
var showsOnlyActiveMedia: Boolean
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
index ae62355e6768..deb5cbafccc4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
@@ -18,7 +18,6 @@ package com.android.systemui.media
import android.content.Context
import android.content.res.Configuration
-import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.R
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -277,79 +276,53 @@ class MediaViewController @Inject constructor(
}
/**
- * Apply squishFraction to a copy of viewState such that the cached version is untouched.
- */
- @VisibleForTesting
- internal fun squishViewState(
- viewState: TransitionViewState,
- squishFraction: Float
- ): TransitionViewState {
- val squishedViewState = viewState.copy()
- squishedViewState.height = (squishedViewState.height * squishFraction).toInt()
- val albumArtViewState = squishedViewState.widgetStates.get(R.id.album_art)
- if (albumArtViewState != null) {
- albumArtViewState.height = squishedViewState.height
- }
- return squishedViewState
- }
-
- /**
* Obtain a new viewState for a given media state. This usually returns a cached state, but if
* it's not available, it will recreate one by measuring, which may be expensive.
*/
- @VisibleForTesting
- public fun obtainViewState(state: MediaHostState?): TransitionViewState? {
+ private fun obtainViewState(state: MediaHostState?): TransitionViewState? {
if (state == null || state.measurementInput == null) {
return null
}
// Only a subset of the state is relevant to get a valid viewState. Let's get the cachekey
var cacheKey = getKey(state, isGutsVisible, tmpKey)
val viewState = viewStates[cacheKey]
-
if (viewState != null) {
// we already have cached this measurement, let's continue
- if (state.squishFraction < 1f) {
- return squishViewState(viewState, state.squishFraction)
- }
return viewState
}
// Copy the key since this might call recursively into it and we're using tmpKey
cacheKey = cacheKey.copy()
val result: TransitionViewState?
- if (transitionLayout == null) {
- return null
- }
- // Not cached. Let's create a new measurement
- if (state.expansion == 0.0f || state.expansion == 1.0f) {
- result = transitionLayout!!.calculateViewState(
- state.measurementInput!!,
- constraintSetForExpansion(state.expansion),
- TransitionViewState())
- // We don't want to cache interpolated or null states as this could quickly fill up
- // our cache. We only cache the start and the end states since the interpolation
- // is cheap
- setGutsViewState(result)
- viewStates[cacheKey] = result
- logger.logMediaSize("measured new viewState", result.width, result.height)
+ if (transitionLayout != null) {
+ // Let's create a new measurement
+ if (state.expansion == 0.0f || state.expansion == 1.0f) {
+ result = transitionLayout!!.calculateViewState(
+ state.measurementInput!!,
+ constraintSetForExpansion(state.expansion),
+ TransitionViewState())
+
+ setGutsViewState(result)
+ // We don't want to cache interpolated or null states as this could quickly fill up
+ // our cache. We only cache the start and the end states since the interpolation
+ // is cheap
+ viewStates[cacheKey] = result
+ } else {
+ // This is an interpolated state
+ val startState = state.copy().also { it.expansion = 0.0f }
+
+ // Given that we have a measurement and a view, let's get (guaranteed) viewstates
+ // from the start and end state and interpolate them
+ val startViewState = obtainViewState(startState) as TransitionViewState
+ val endState = state.copy().also { it.expansion = 1.0f }
+ val endViewState = obtainViewState(endState) as TransitionViewState
+ result = layoutController.getInterpolatedState(
+ startViewState,
+ endViewState,
+ state.expansion)
+ }
} else {
- // This is an interpolated state
- val startState = state.copy().also { it.expansion = 0.0f }
-
- // Given that we have a measurement and a view, let's get (guaranteed) viewstates
- // from the start and end state and interpolate them
- val startViewState = obtainViewState(startState) as TransitionViewState
- val endState = state.copy().also { it.expansion = 1.0f }
-
- val endViewState = obtainViewState(endState) as TransitionViewState
- result = layoutController.getInterpolatedState(
- startViewState,
- endViewState,
- state.expansion)
- logger.logMediaSize("interpolated viewState", result.width, result.height)
- }
- if (state.squishFraction < 1f) {
- return squishViewState(result, state.squishFraction)
+ result = null
}
return result
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 6b579e8bb118..d03a2e55d628 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -624,7 +624,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
if (mQSAnimator != null) {
mQSAnimator.setPosition(expansion);
}
- mQqsMediaHost.setSquishFraction(mSquishinessFraction);
updateMediaPositions();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 4d325e154a4f..ba57d57d0fd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -191,7 +191,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private final boolean mDebugRemoveAnimation;
private int mContentHeight;
- private int mIntrinsicContentHeight;
+ private float mIntrinsicContentHeight;
private int mCollapsedSize;
private int mPaddingBetweenElements;
private int mMaxTopPadding;
@@ -802,7 +802,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
drawDebugInfo(canvas, y, Color.MAGENTA,
/* label= */ "mAmbientState.getStackY() + mContentHeight = " + y);
- y = (int) mAmbientState.getStackY() + mIntrinsicContentHeight;
+ y = (int) (mAmbientState.getStackY() + mIntrinsicContentHeight);
drawDebugInfo(canvas, y, Color.YELLOW,
/* label= */ "mAmbientState.getStackY() + mIntrinsicContentHeight = " + y);
@@ -1371,7 +1371,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public void setExpandedHeight(float height) {
+ final float shadeBottom = getHeight() - getEmptyBottomMargin();
final boolean skipHeightUpdate = shouldSkipHeightUpdate();
+ if (!skipHeightUpdate) {
+ final float expansionFraction = MathUtils.saturate(height / shadeBottom);
+ mAmbientState.setExpansionFraction(expansionFraction);
+ }
updateStackPosition();
if (!skipHeightUpdate) {
@@ -1473,7 +1478,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public int getIntrinsicContentHeight() {
- return mIntrinsicContentHeight;
+ return (int) mIntrinsicContentHeight;
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -2287,7 +2292,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private void updateContentHeight() {
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
final int shelfIntrinsicHeight = mShelf != null ? mShelf.getIntrinsicHeight() : 0;
- final int height =
+ final float height =
(int) scrimTopPadding + (int) mNotificationStackSizeCalculator.computeHeight(
/* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications,
shelfIntrinsicHeight);
@@ -2295,7 +2300,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
// The topPadding can be bigger than the regular padding when qs is expanded, in that
// state the maxPanelHeight and the contentHeight should be bigger
- mContentHeight = height + Math.max(mIntrinsicPadding, mTopPadding) + mBottomPadding;
+ mContentHeight = (int) (height + Math.max(mIntrinsicPadding, mTopPadding) + mBottomPadding);
updateScrollability();
clampScrollPosition();
updateStackPosition();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
index d05c3385e982..6287857e7be9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -37,6 +37,7 @@ import kotlin.properties.Delegates.notNull
private const val TAG = "NotifStackSizeCalc"
private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG)
+private val SPEW = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE)
/** Calculates number of notifications to display and the height of the notification stack. */
@SysUISingleton
@@ -87,9 +88,10 @@ constructor(
// Could be < 0 if the space available is less than the shelf size. Returns 0 in this case.
maxNotifications = max(0, maxNotifications)
log {
+ val sequence = if (SPEW) " stackHeightSequence=${stackHeightSequence.toList()}" else ""
"computeMaxKeyguardNotifications(" +
"availableSpace=$totalAvailableSpace" +
- " shelfHeight=$shelfIntrinsicHeight) -> $maxNotifications"
+ " shelfHeight=$shelfIntrinsicHeight) -> $maxNotifications$sequence"
}
return maxNotifications
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 799fee5e865d..4013254c6592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -53,9 +53,9 @@ public class StackScrollAlgorithm {
private static final Boolean DEBUG = false;
private final ViewGroup mHostView;
- private int mPaddingBetweenElements;
- private int mGapHeight;
- private int mGapHeightOnLockscreen;
+ private float mPaddingBetweenElements;
+ private float mGapHeight;
+ private float mGapHeightOnLockscreen;
private int mCollapsedSize;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
@@ -127,13 +127,13 @@ public class StackScrollAlgorithm {
return getExpansionFractionWithoutShelf(mTempAlgorithmState, ambientState);
}
- private void log(String s) {
+ public static void log(String s) {
if (DEBUG) {
android.util.Log.i(TAG, s);
}
}
- public void logView(View view, String s) {
+ public static void logView(View view, String s) {
String viewString = "";
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = ((ExpandableNotificationRow) view);
@@ -535,30 +535,23 @@ public class StackScrollAlgorithm {
// more notifications than we should during this special transitional states.
boolean bypassPulseNotExpanding = ambientState.isBypassEnabled()
&& ambientState.isOnKeyguard() && !ambientState.isPulseExpanding();
- final int stackBottom =
- !ambientState.isShadeExpanded() || ambientState.isDozing()
- || bypassPulseNotExpanding
+ final float stackBottom = !ambientState.isShadeExpanded()
+ || ambientState.getDozeAmount() == 1f
+ || bypassPulseNotExpanding
? ambientState.getInnerHeight()
- : (int) ambientState.getStackHeight();
- final int shelfStart = stackBottom
+ : ambientState.getStackHeight();
+ final float shelfStart = stackBottom
- ambientState.getShelf().getIntrinsicHeight()
- mPaddingBetweenElements;
- viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
- if (viewState.yTranslation >= shelfStart) {
- viewState.hidden = !view.isExpandAnimationRunning()
- && !view.hasExpandingChild();
- viewState.inShelf = true;
- // Notifications in the shelf cannot be visible HUNs.
- viewState.headsUpIsVisible = false;
- }
+ updateViewWithShelf(view, viewState, shelfStart);
}
}
// Clip height of view right before shelf.
viewState.height = (int) (getMaxAllowedChildHeight(view) * expansionFraction);
}
- algorithmState.mCurrentYPosition += viewState.height
- + expansionFraction * mPaddingBetweenElements;
+ algorithmState.mCurrentYPosition +=
+ expansionFraction * (getMaxAllowedChildHeight(view) + mPaddingBetweenElements);
algorithmState.mCurrentExpandedYPosition += view.getIntrinsicHeight()
+ mPaddingBetweenElements;
@@ -566,6 +559,18 @@ public class StackScrollAlgorithm {
viewState.yTranslation += ambientState.getStackY();
}
+ @VisibleForTesting
+ void updateViewWithShelf(ExpandableView view, ExpandableViewState viewState, float shelfStart) {
+ viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
+ if (viewState.yTranslation >= shelfStart) {
+ viewState.hidden = !view.isExpandAnimationRunning()
+ && !view.hasExpandingChild();
+ viewState.inShelf = true;
+ // Notifications in the shelf cannot be visible HUNs.
+ viewState.headsUpIsVisible = false;
+ }
+ }
+
/**
* Get the gap height needed for before a view
*
@@ -849,13 +854,13 @@ public class StackScrollAlgorithm {
* Y position of the current view during updating children
* with expansion factor applied.
*/
- private int mCurrentYPosition;
+ private float mCurrentYPosition;
/**
* Y position of the current view during updating children
* without applying the expansion factor.
*/
- private int mCurrentExpandedYPosition;
+ private float mCurrentExpandedYPosition;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 5c12671726f4..8203987cd7d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -107,7 +107,6 @@ import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.widget.DateTimeView;
-import android.window.SplashScreen;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
@@ -3508,11 +3507,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
@Override
public void onTrackingStopped(boolean expand) {
- if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
- if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
- mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */);
- }
- }
}
// TODO: Figure out way to remove these.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 4a912572b7ed..9afdfd651130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -192,6 +192,7 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.Compile;
import com.android.systemui.util.LargeScreenUtils;
import com.android.systemui.util.ListenerSet;
import com.android.systemui.util.Utils;
@@ -216,7 +217,9 @@ import javax.inject.Provider;
@CentralSurfacesComponent.CentralSurfacesScope
public class NotificationPanelViewController extends PanelViewController {
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG_LOGCAT = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean SPEW_LOGCAT = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
+ private static final boolean DEBUG_DRAWABLE = false;
/**
* The parallax amount of the quick settings translation when dragging down the panel
@@ -816,7 +819,7 @@ public class NotificationPanelViewController extends PanelViewController {
mSettingsChangeObserver = new SettingsChangeObserver(handler);
mSplitShadeEnabled =
LargeScreenUtils.shouldUseSplitNotificationShade(mResources);
- mView.setWillNotDraw(!DEBUG);
+ mView.setWillNotDraw(!DEBUG_DRAWABLE);
mLargeScreenShadeHeaderController = largeScreenShadeHeaderController;
mLayoutInflater = layoutInflater;
mFeatureFlags = featureFlags;
@@ -890,7 +893,7 @@ public class NotificationPanelViewController extends PanelViewController {
mView.setOnApplyWindowInsetsListener(new OnApplyWindowInsetsListener());
- if (DEBUG) {
+ if (DEBUG_DRAWABLE) {
mView.getOverlay().add(new DebugDrawable());
}
@@ -1189,7 +1192,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
private void reInflateViews() {
- if (DEBUG) Log.d(TAG, "reInflateViews");
+ if (DEBUG_LOGCAT) Log.d(TAG, "reInflateViews");
// Re-inflate the status view group.
KeyguardStatusView keyguardStatusView =
mNotificationContainerParent.findViewById(R.id.keyguard_status_view);
@@ -1293,6 +1296,8 @@ public class NotificationPanelViewController extends PanelViewController {
private void updateMaxDisplayedNotifications(boolean recompute) {
if (recompute) {
mMaxAllowedKeyguardNotifications = Math.max(computeMaxKeyguardNotifications(), 1);
+ } else {
+ if (SPEW_LOGCAT) Log.d(TAG, "Skipping computeMaxKeyguardNotifications() by request");
}
if (mKeyguardShowing && !mKeyguardBypassController.getBypassEnabled()) {
@@ -1545,6 +1550,19 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationStackScrollLayoutController.getHeight()
- staticTopPadding
- bottomPadding;
+
+ if (SPEW_LOGCAT) {
+ Log.d(TAG, "getSpaceForLockscreenNotifications()"
+ + " availableSpace=" + availableSpace
+ + " NSSL.height=" + mNotificationStackScrollLayoutController.getHeight()
+ + " NSSL.top=" + mNotificationStackScrollLayoutController.getTop()
+ + " staticTopPadding=" + staticTopPadding
+ + " bottomPadding=" + bottomPadding
+ + " lockIconPadding=" + lockIconPadding
+ + " mIndicationBottomPadding=" + mIndicationBottomPadding
+ + " mAmbientIndicationBottomPadding=" + mAmbientIndicationBottomPadding
+ );
+ }
return availableSpace;
}
@@ -1553,7 +1571,12 @@ public class NotificationPanelViewController extends PanelViewController {
*/
@VisibleForTesting
int computeMaxKeyguardNotifications() {
- if (mAmbientState.getFractionToShade() > 0 || mAmbientState.getDozeAmount() > 0) {
+ if (mAmbientState.getFractionToShade() > 0) {
+ if (SPEW_LOGCAT) {
+ Log.v(TAG, "Internally skipping computeMaxKeyguardNotifications()"
+ + " fractionToShade=" + mAmbientState.getFractionToShade()
+ );
+ }
return mMaxAllowedKeyguardNotifications;
}
@@ -1743,7 +1766,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
private boolean onQsIntercept(MotionEvent event) {
- if (DEBUG) Log.d(TAG, "onQsIntercept");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onQsIntercept");
int pointerIndex = event.findPointerIndex(mTrackingPointer);
if (pointerIndex < 0) {
pointerIndex = 0;
@@ -1798,7 +1821,7 @@ public class NotificationPanelViewController extends PanelViewController {
if ((h > getTouchSlop(event) || (h < -getTouchSlop(event) && mQsExpanded))
&& Math.abs(h) > Math.abs(x - mInitialTouchX)
&& shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, h)) {
- if (DEBUG) Log.d(TAG, "onQsIntercept - start tracking expansion");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onQsIntercept - start tracking expansion");
mView.getParent().requestDisallowInterceptTouchEvent(true);
mQsTracking = true;
traceQsJank(true /* startTracing */, false /* wasCancelled */);
@@ -2075,7 +2098,7 @@ public class NotificationPanelViewController extends PanelViewController {
private void handleQsDown(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && shouldQuickSettingsIntercept(
event.getX(), event.getY(), -1)) {
- if (DEBUG) Log.d(TAG, "handleQsDown");
+ if (DEBUG_LOGCAT) Log.d(TAG, "handleQsDown");
mFalsingCollector.onQsDown();
mQsTracking = true;
onQsExpansionStarted();
@@ -2189,7 +2212,7 @@ public class NotificationPanelViewController extends PanelViewController {
break;
case MotionEvent.ACTION_MOVE:
- if (DEBUG) Log.d(TAG, "onQSTouch move");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onQSTouch move");
setQsExpansion(h + mInitialHeightOnTouch);
if (h >= getFalsingThreshold()) {
mQsTouchAboveFalsingThreshold = true;
@@ -2341,7 +2364,7 @@ public class NotificationPanelViewController extends PanelViewController {
mCentralSurfaces.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
}
- if (DEBUG) {
+ if (DEBUG_DRAWABLE) {
mView.invalidate();
}
}
@@ -2998,7 +3021,7 @@ public class NotificationPanelViewController extends PanelViewController {
// This is a circular dependency and should be avoided, otherwise we'll have
// a stack overflow.
if (mStackScrollerMeasuringPass > 2) {
- if (DEBUG) Log.d(TAG, "Unstable notification panel height. Aborting.");
+ if (DEBUG_LOGCAT) Log.d(TAG, "Unstable notification panel height. Aborting.");
} else {
positionClockAndNotifications();
}
@@ -3032,7 +3055,7 @@ public class NotificationPanelViewController extends PanelViewController {
updateNotificationTranslucency();
updatePanelExpanded();
updateGestureExclusionRect();
- if (DEBUG) {
+ if (DEBUG_DRAWABLE) {
mView.invalidate();
}
}
@@ -3057,7 +3080,9 @@ public class NotificationPanelViewController extends PanelViewController {
}
private int calculatePanelHeightShade() {
- final int maxHeight = mNotificationStackScrollLayoutController.getHeight();
+ int emptyBottomMargin = mNotificationStackScrollLayoutController.getEmptyBottomMargin();
+ int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin;
+
if (mBarState == KEYGUARD) {
int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight()
+ mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
@@ -3675,7 +3700,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void onQsPanelScrollChanged(int scrollY) {
mLargeScreenShadeHeaderController.setQsScrollY(scrollY);
if (scrollY > 0 && !mQsFullyExpanded) {
- if (DEBUG) Log.d(TAG, "Scrolling while not expanded. Forcing expand");
+ if (DEBUG_LOGCAT) Log.d(TAG, "Scrolling while not expanded. Forcing expand");
// If we are scrolling QS, we should be fully expanded.
expandWithQs();
}
@@ -4070,7 +4095,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
public void setHeaderDebugInfo(String text) {
- if (DEBUG) mHeaderDebugInfo = text;
+ if (DEBUG_DRAWABLE) mHeaderDebugInfo = text;
}
public void onThemeChanged() {
@@ -4112,7 +4137,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
if (!isFullyCollapsed() && onQsIntercept(event)) {
- if (DEBUG) Log.d(TAG, "onQsIntercept true");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onQsIntercept true");
return true;
}
return super.onInterceptTouchEvent(event);
@@ -4183,7 +4208,7 @@ public class NotificationPanelViewController extends PanelViewController {
handled |= mHeadsUpTouchHelper.onTouchEvent(event);
if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
- if (DEBUG) Log.d(TAG, "handleQsTouch true");
+ if (DEBUG_LOGCAT) Log.d(TAG, "handleQsTouch true");
return true;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
@@ -4623,7 +4648,7 @@ public class NotificationPanelViewController extends PanelViewController {
private class ConfigurationListener implements ConfigurationController.ConfigurationListener {
@Override
public void onThemeChanged() {
- if (DEBUG) Log.d(TAG, "onThemeChanged");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onThemeChanged");
mThemeResId = mView.getContext().getThemeResId();
reInflateViews();
}
@@ -4631,7 +4656,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onSmallestScreenWidthChanged() {
Trace.beginSection("onSmallestScreenWidthChanged");
- if (DEBUG) Log.d(TAG, "onSmallestScreenWidthChanged");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onSmallestScreenWidthChanged");
// Can affect multi-user switcher visibility as it depends on screen size by default:
// it is enabled only for devices with large screens (see config_keyguardUserSwitcher)
@@ -4648,7 +4673,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onDensityOrFontScaleChanged() {
- if (DEBUG) Log.d(TAG, "onDensityOrFontScaleChanged");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onDensityOrFontScaleChanged");
reInflateViews();
}
}
@@ -4661,7 +4686,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onChange(boolean selfChange) {
- if (DEBUG) Log.d(TAG, "onSettingsChanged");
+ if (DEBUG_LOGCAT) Log.d(TAG, "onSettingsChanged");
// Can affect multi-user switcher visibility
reInflateViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 7ab944dc013e..82ca842d48c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -806,7 +806,6 @@ public abstract class PanelViewController {
mExpansionDragDownAmountPx = h;
mExpandedFraction = Math.min(1f,
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
- mAmbientState.setExpansionFraction(mExpandedFraction);
onHeightUpdated(mExpandedHeight);
updatePanelExpansionAndVisibility();
});
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 124647b81d4a..61e123a8e42a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -480,12 +480,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
if (mBouncer == null) {
return;
}
+ mBouncer.hide(destroyView);
if (mShowing) {
// If we were showing the bouncer and then aborting, we need to also clear out any
// potential actions unless we actually unlocked.
cancelPostAuthActions();
}
- mBouncer.hide(destroyView);
cancelPendingWakeupAction();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt
deleted file mode 100644
index 18178097d5e3..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.android.systemui.media
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.View
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.util.animation.MeasurementInput
-import com.android.systemui.util.animation.TransitionLayout
-import com.android.systemui.util.animation.TransitionViewState
-import com.android.systemui.util.animation.WidgetState
-import junit.framework.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
-import org.mockito.Mockito.`when` as whenever
-
-/**
- * Tests for {@link MediaViewController}.
- */
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
-class MediaViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var logger: MediaViewLogger
-
- private val configurationController =
- com.android.systemui.statusbar.phone.ConfigurationControllerImpl(context)
- private val mediaHostStatesManager = MediaHostStatesManager()
- private lateinit var mediaViewController: MediaViewController
- private val mediaHostStateHolder = MediaHost.MediaHostStateHolder()
- private var transitionLayout = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0)
- @Mock private lateinit var mockViewState: TransitionViewState
- @Mock private lateinit var mockCopiedState: TransitionViewState
- @Mock private lateinit var mockWidgetState: WidgetState
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- mediaViewController = MediaViewController(
- context,
- configurationController,
- mediaHostStatesManager,
- logger
- )
- mediaViewController.attach(transitionLayout, MediaViewController.TYPE.PLAYER)
- }
-
- @Test
- fun testObtainViewState_applySquishFraction_toTransitionViewState_height() {
- transitionLayout.measureState = TransitionViewState().apply {
- this.height = 100
- }
- mediaHostStateHolder.expansion = 1f
- val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
- val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
- mediaHostStateHolder.measurementInput =
- MeasurementInput(widthMeasureSpec, heightMeasureSpec)
-
- // Test no squish
- mediaHostStateHolder.squishFraction = 1f
- assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100)
-
- // Test half squish
- mediaHostStateHolder.squishFraction = 0.5f
- assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
- }
-
- @Test
- fun testSquish_DoesNotMutateViewState() {
- whenever(mockViewState.copy()).thenReturn(mockCopiedState)
- whenever(mockCopiedState.widgetStates)
- .thenReturn(mutableMapOf(R.id.album_art to mockWidgetState))
-
- mediaViewController.squishViewState(mockViewState, 0.5f)
- verify(mockViewState, times(1)).copy()
- verifyNoMoreInteractions(mockViewState)
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 87ca1aa5eeb7..668f7526891a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -7,10 +7,13 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.EmptyShadeView
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
@@ -110,4 +113,52 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
/* fractionToShade= */ 0f, /* onKeyguard= */ false)
assertThat(gap).isEqualTo(bigGap)
}
+
+ @Test
+ fun updateViewWithShelf_viewAboveShelf_viewShown() {
+ val viewStart = 0f
+ val shelfStart = 1f
+
+ val expandableView = mock(ExpandableView::class.java)
+ whenever(expandableView.isExpandAnimationRunning).thenReturn(false)
+ whenever(expandableView.hasExpandingChild()).thenReturn(false)
+
+ val expandableViewState = ExpandableViewState()
+ expandableViewState.yTranslation = viewStart
+
+ stackScrollAlgorithm.updateViewWithShelf(expandableView, expandableViewState, shelfStart);
+ assertFalse(expandableViewState.hidden)
+ }
+
+ @Test
+ fun updateViewWithShelf_viewBelowShelf_viewHidden() {
+ val shelfStart = 0f
+ val viewStart = 1f
+
+ val expandableView = mock(ExpandableView::class.java)
+ whenever(expandableView.isExpandAnimationRunning).thenReturn(false)
+ whenever(expandableView.hasExpandingChild()).thenReturn(false)
+
+ val expandableViewState = ExpandableViewState()
+ expandableViewState.yTranslation = viewStart
+
+ stackScrollAlgorithm.updateViewWithShelf(expandableView, expandableViewState, shelfStart);
+ assertTrue(expandableViewState.hidden)
+ }
+
+ @Test
+ fun updateViewWithShelf_viewBelowShelfButIsExpanding_viewShown() {
+ val shelfStart = 0f
+ val viewStart = 1f
+
+ val expandableView = mock(ExpandableView::class.java)
+ whenever(expandableView.isExpandAnimationRunning).thenReturn(true)
+ whenever(expandableView.hasExpandingChild()).thenReturn(true)
+
+ val expandableViewState = ExpandableViewState()
+ expandableViewState.yTranslation = viewStart
+
+ stackScrollAlgorithm.updateViewWithShelf(expandableView, expandableViewState, shelfStart);
+ assertFalse(expandableViewState.hidden)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index fa9161a19cb1..f599e3b12c57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -578,19 +578,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void computeMaxKeyguardNotifications_dozeAmountNotZero_returnsExistingMax() {
- when(mAmbientState.getDozeAmount()).thenReturn(0.5f);
- mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
-
- // computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
- assertThat(mNotificationPanelViewController.computeMaxKeyguardNotifications())
- .isEqualTo(-1);
- }
-
- @Test
public void computeMaxKeyguardNotifications_noTransition_updatesMax() {
when(mAmbientState.getFractionToShade()).thenReturn(0f);
- when(mAmbientState.getDozeAmount()).thenReturn(0f);
mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
// computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
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 38e018b42985..4f2abf263a9b 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
@@ -312,6 +312,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mStatusBarKeyguardViewManager.dismissWithAction(
action, cancelAction, true /* afterKeyguardGone */);
+ when(mBouncer.isShowing()).thenReturn(false);
mStatusBarKeyguardViewManager.hideBouncer(true);
mStatusBarKeyguardViewManager.hide(0, 30);
verify(action, never()).onDismiss();
@@ -319,6 +320,20 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
+ public void testHidingBouncer_cancelsGoneRunnable() {
+ OnDismissAction action = mock(OnDismissAction.class);
+ Runnable cancelAction = mock(Runnable.class);
+ mStatusBarKeyguardViewManager.dismissWithAction(
+ action, cancelAction, true /* afterKeyguardGone */);
+
+ when(mBouncer.isShowing()).thenReturn(false);
+ mStatusBarKeyguardViewManager.hideBouncer(true);
+
+ verify(action, never()).onDismiss();
+ verify(cancelAction).run();
+ }
+
+ @Test
public void testHiding_doesntCancelWhenShowing() {
OnDismissAction action = mock(OnDismissAction.class);
Runnable cancelAction = mock(Runnable.class);
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index e27b7a659ae6..09a05bb6b40e 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -1135,41 +1135,13 @@ public class CameraExtensionsProxyService extends Service {
CameraSessionConfig ret = new CameraSessionConfig();
ret.outputConfigs = new ArrayList<>();
for (Camera2OutputConfigImpl output : outputConfigs) {
- CameraOutputConfig entry = new CameraOutputConfig();
- entry.outputId = new OutputConfigId();
- entry.outputId.id = output.getId();
- entry.physicalCameraId = output.getPhysicalCameraId();
- entry.surfaceGroupId = output.getSurfaceGroupId();
- if (output instanceof SurfaceOutputConfigImpl) {
- SurfaceOutputConfigImpl surfaceConfig = (SurfaceOutputConfigImpl) output;
- entry.type = CameraOutputConfig.TYPE_SURFACE;
- entry.surface = surfaceConfig.getSurface();
- } else if (output instanceof ImageReaderOutputConfigImpl) {
- ImageReaderOutputConfigImpl imageReaderOutputConfig =
- (ImageReaderOutputConfigImpl) output;
- entry.type = CameraOutputConfig.TYPE_IMAGEREADER;
- entry.size = new android.hardware.camera2.extension.Size();
- entry.size.width = imageReaderOutputConfig.getSize().getWidth();
- entry.size.height = imageReaderOutputConfig.getSize().getHeight();
- entry.imageFormat = imageReaderOutputConfig.getImageFormat();
- entry.capacity = imageReaderOutputConfig.getMaxImages();
- } else if (output instanceof MultiResolutionImageReaderOutputConfigImpl) {
- MultiResolutionImageReaderOutputConfigImpl multiResReaderConfig =
- (MultiResolutionImageReaderOutputConfigImpl) output;
- entry.type = CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER;
- entry.imageFormat = multiResReaderConfig.getImageFormat();
- entry.capacity = multiResReaderConfig.getMaxImages();
- } else {
- throw new IllegalStateException("Unknown output config type!");
- }
+ CameraOutputConfig entry = getCameraOutputConfig(output);
List<Camera2OutputConfigImpl> sharedOutputs =
output.getSurfaceSharingOutputConfigs();
if ((sharedOutputs != null) && (!sharedOutputs.isEmpty())) {
- entry.surfaceSharingOutputConfigs = new ArrayList<>();
+ entry.sharedSurfaceConfigs = new ArrayList<>();
for (Camera2OutputConfigImpl sharedOutput : sharedOutputs) {
- OutputConfigId outputId = new OutputConfigId();
- outputId.id = sharedOutput.getId();
- entry.surfaceSharingOutputConfigs.add(outputId);
+ entry.sharedSurfaceConfigs.add(getCameraOutputConfig(sharedOutput));
}
}
ret.outputConfigs.add(entry);
@@ -1854,4 +1826,36 @@ public class CameraExtensionsProxyService extends Service {
}
}
}
+
+ private static CameraOutputConfig getCameraOutputConfig(Camera2OutputConfigImpl output) {
+ CameraOutputConfig ret = new CameraOutputConfig();
+ ret.outputId = new OutputConfigId();
+ ret.outputId.id = output.getId();
+ ret.physicalCameraId = output.getPhysicalCameraId();
+ ret.surfaceGroupId = output.getSurfaceGroupId();
+ if (output instanceof SurfaceOutputConfigImpl) {
+ SurfaceOutputConfigImpl surfaceConfig = (SurfaceOutputConfigImpl) output;
+ ret.type = CameraOutputConfig.TYPE_SURFACE;
+ ret.surface = surfaceConfig.getSurface();
+ } else if (output instanceof ImageReaderOutputConfigImpl) {
+ ImageReaderOutputConfigImpl imageReaderOutputConfig =
+ (ImageReaderOutputConfigImpl) output;
+ ret.type = CameraOutputConfig.TYPE_IMAGEREADER;
+ ret.size = new android.hardware.camera2.extension.Size();
+ ret.size.width = imageReaderOutputConfig.getSize().getWidth();
+ ret.size.height = imageReaderOutputConfig.getSize().getHeight();
+ ret.imageFormat = imageReaderOutputConfig.getImageFormat();
+ ret.capacity = imageReaderOutputConfig.getMaxImages();
+ } else if (output instanceof MultiResolutionImageReaderOutputConfigImpl) {
+ MultiResolutionImageReaderOutputConfigImpl multiResReaderConfig =
+ (MultiResolutionImageReaderOutputConfigImpl) output;
+ ret.type = CameraOutputConfig.TYPE_MULTIRES_IMAGEREADER;
+ ret.imageFormat = multiResReaderConfig.getImageFormat();
+ ret.capacity = multiResReaderConfig.getMaxImages();
+ } else {
+ throw new IllegalStateException("Unknown output config type!");
+ }
+
+ return ret;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
index 9e8b2228195e..26a295ef9253 100644
--- a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
+++ b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
@@ -56,39 +56,41 @@ public class CustomScrollView extends ScrollView {
private int mWidth = -1;
private int mHeight = -1;
- private int mMaxPortraitBodyHeightPercent = 20;
- private int mMaxLandscapeBodyHeightPercent = 20;
+ private int mMaxPortraitBodyHeightPercent;
+ private int mMaxLandscapeBodyHeightPercent;
+ private int mAttrBasedMaxHeightPercent;
public CustomScrollView(Context context) {
super(context);
- setMaxBodyHeightPercent();
+ setMaxBodyHeightPercent(context);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
- setMaxBodyHeightPercent();
+ setMaxBodyHeightPercent(context);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- setMaxBodyHeightPercent();
+ setMaxBodyHeightPercent(context);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- setMaxBodyHeightPercent();
+ setMaxBodyHeightPercent(context);
}
- private void setMaxBodyHeightPercent() {
+ private void setMaxBodyHeightPercent(Context context) {
+ mAttrBasedMaxHeightPercent = getAttrBasedMaxHeightPercent(context);
mMaxPortraitBodyHeightPercent = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_AUTOFILL,
DEVICE_CONFIG_SAVE_DIALOG_PORTRAIT_BODY_HEIGHT_MAX_PERCENT,
- mMaxPortraitBodyHeightPercent);
+ mAttrBasedMaxHeightPercent);
mMaxLandscapeBodyHeightPercent = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_AUTOFILL,
DEVICE_CONFIG_SAVE_DIALOG_LANDSCAPE_BODY_HEIGHT_MAX_PERCENT,
- mMaxLandscapeBodyHeightPercent);
+ mAttrBasedMaxHeightPercent);
}
@Override
@@ -117,29 +119,27 @@ public class CustomScrollView extends ScrollView {
final int contentHeight = content.getMeasuredHeight();
int displayHeight = point.y;
- int configBasedMaxHeight = (getResources().getConfiguration().orientation
+ int maxHeight = (getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE)
? (int) (mMaxLandscapeBodyHeightPercent * displayHeight / 100)
: (int) (mMaxPortraitBodyHeightPercent * displayHeight / 100);
- mHeight = configBasedMaxHeight > 0
- ? Math.min(contentHeight, configBasedMaxHeight)
- : Math.min(contentHeight, getAttrBasedMaxHeight(context, displayHeight));
+ mHeight = Math.min(contentHeight, maxHeight);
if (sDebug) {
Slog.d(TAG, "calculateDimensions():"
+ " mMaxPortraitBodyHeightPercent=" + mMaxPortraitBodyHeightPercent
+ ", mMaxLandscapeBodyHeightPercent=" + mMaxLandscapeBodyHeightPercent
- + ", configBasedMaxHeight=" + configBasedMaxHeight
- + ", attrBasedMaxHeight=" + getAttrBasedMaxHeight(context, displayHeight)
+ + ", mAttrBasedMaxHeightPercent=" + mAttrBasedMaxHeightPercent
+ + ", maxHeight=" + maxHeight
+ ", contentHeight=" + contentHeight
+ ", w=" + mWidth + ", h=" + mHeight);
}
}
- private int getAttrBasedMaxHeight(Context context, int displayHeight) {
+ private int getAttrBasedMaxHeightPercent(Context context) {
final TypedValue maxHeightAttrTypedValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.autofillSaveCustomSubtitleMaxHeight,
maxHeightAttrTypedValue, true);
- return (int) maxHeightAttrTypedValue.getFraction(displayHeight, displayHeight);
+ return (int) maxHeightAttrTypedValue.getFraction(100, 100);
}
}
diff --git a/services/companion/java/com/android/server/companion/CompanionApplicationController.java b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
index 2a83a3c431ec..6eb8e2619cb5 100644
--- a/services/companion/java/com/android/server/companion/CompanionApplicationController.java
+++ b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
@@ -104,10 +104,10 @@ class CompanionApplicationController {
}
void bindCompanionApplication(@UserIdInt int userId, @NonNull String packageName,
- boolean bindImportant) {
+ boolean isSelfManaged) {
if (DEBUG) {
Log.i(TAG, "bind() u" + userId + "/" + packageName
- + " important=" + bindImportant);
+ + " isSelfManaged=" + isSelfManaged);
}
final List<ComponentName> companionServices =
@@ -130,7 +130,7 @@ class CompanionApplicationController {
serviceConnectors = CollectionUtils.map(companionServices, componentName ->
CompanionDeviceServiceConnector.newInstance(mContext, userId,
- componentName, bindImportant));
+ componentName, isSelfManaged));
mBoundCompanionApplications.setValueForPackage(userId, packageName, serviceConnectors);
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java
index a6bd48056e12..9bb1fb9ac9f5 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java
@@ -17,7 +17,7 @@
package com.android.server.companion;
import static android.content.Context.BIND_ALMOST_PERCEPTIBLE;
-import static android.content.Context.BIND_IMPORTANT;
+import static android.content.Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE;
import static android.os.Process.THREAD_PRIORITY_DEFAULT;
import android.annotation.NonNull;
@@ -61,21 +61,22 @@ class CompanionDeviceServiceConnector extends ServiceConnector.Impl<ICompanionDe
/**
* Create a CompanionDeviceServiceConnector instance.
*
- * When bindImportant is false, the binding flag will be BIND_ALMOST_PERCEPTIBLE
+ * For self-managed apps, the binding flag will be BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE
+ * (oom_score_adj = VISIBLE_APP_ADJ = 100).
+ *
+ * For non self-managed apps, the binding flag will be BIND_ALMOST_PERCEPTIBLE
* (oom_score_adj = PERCEPTIBLE_MEDIUM_APP = 225). The target service will be treated
* as important as a perceptible app (IMPORTANCE_VISIBLE = 200), and will be unbound when
* the app is removed from task manager.
- * When bindImportant is true, the binding flag will be BIND_IMPORTANT
- * (oom_score_adj = PERCEPTIBLE_MEDIUM_APP = -700). The target service will
- * have the highest priority to avoid being killed (IMPORTANCE_FOREGROUND = 100).
*
* One time permission's importance level to keep session alive is
* IMPORTANCE_FOREGROUND_SERVICE = 125. In order to kill the one time permission session, the
* service importance level should be higher than 125.
*/
static CompanionDeviceServiceConnector newInstance(@NonNull Context context,
- @UserIdInt int userId, @NonNull ComponentName componentName, boolean bindImportant) {
- final int bindingFlags = bindImportant ? BIND_IMPORTANT : BIND_ALMOST_PERCEPTIBLE;
+ @UserIdInt int userId, @NonNull ComponentName componentName, boolean isSelfManaged) {
+ final int bindingFlags = isSelfManaged ? BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE
+ : BIND_ALMOST_PERCEPTIBLE;
return new CompanionDeviceServiceConnector(context, userId, componentName, bindingFlags);
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 089a92402de5..254a3226e6de 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -125,6 +125,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.NetworkStackConstants;
import com.android.server.DeviceIdleInternal;
@@ -213,7 +214,9 @@ public class Vpn {
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
private final NetworkInfo mNetworkInfo;
+ @GuardedBy("this")
private int mLegacyState;
+ @GuardedBy("this")
@VisibleForTesting protected String mPackage;
private int mOwnerUID;
private boolean mIsPackageTargetingAtLeastQ;
@@ -251,6 +254,7 @@ public class Vpn {
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
* only applies to {@link VpnService} connections.
*/
+ @GuardedBy("this")
@VisibleForTesting protected boolean mAlwaysOn = false;
/**
@@ -258,6 +262,7 @@ public class Vpn {
* apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is
* not set. Applies to all types of VPNs.
*/
+ @GuardedBy("this")
@VisibleForTesting protected boolean mLockdown = false;
/**
@@ -610,7 +615,7 @@ public class Vpn {
}
/** Returns the package name that is currently prepared. */
- public String getPackage() {
+ public synchronized String getPackage() {
return mPackage;
}
@@ -691,6 +696,36 @@ public class Vpn {
return true;
}
+ private boolean sendEventToVpnManagerApp(@NonNull String category, int errorClass,
+ int errorCode, @NonNull final String packageName, @Nullable final String sessionKey,
+ @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork,
+ @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) {
+ final Intent intent = new Intent(VpnManager.ACTION_VPN_MANAGER_EVENT);
+ intent.setPackage(packageName);
+ intent.addCategory(category);
+ intent.putExtra(VpnManager.EXTRA_VPN_PROFILE_STATE, profileState);
+ intent.putExtra(VpnManager.EXTRA_SESSION_KEY, sessionKey);
+ intent.putExtra(VpnManager.EXTRA_UNDERLYING_NETWORK, underlyingNetwork);
+ intent.putExtra(VpnManager.EXTRA_UNDERLYING_NETWORK_CAPABILITIES, nc);
+ intent.putExtra(VpnManager.EXTRA_UNDERLYING_LINK_PROPERTIES, lp);
+ intent.putExtra(VpnManager.EXTRA_TIMESTAMP_MILLIS, System.currentTimeMillis());
+ if (!VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER.equals(category)
+ || !VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED.equals(category)) {
+ intent.putExtra(VpnManager.EXTRA_ERROR_CLASS, errorClass);
+ intent.putExtra(VpnManager.EXTRA_ERROR_CODE, errorCode);
+ }
+ try {
+ return mUserIdContext.startService(intent) != null;
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e);
+ return false;
+ }
+ }
+
+ private boolean isVpnApp(String packageName) {
+ return packageName != null && !VpnConfig.LEGACY_VPN.equals(packageName);
+ }
+
/**
* Configures an always-on VPN connection through a specific application. This connection is
* automatically granted and persisted after a reboot.
@@ -713,9 +748,40 @@ public class Vpn {
boolean lockdown,
@Nullable List<String> lockdownAllowlist) {
enforceControlPermissionOrInternalCaller();
+ // Store mPackage since it might be reset or might be replaced with the other VPN app.
+ final String oldPackage = mPackage;
+ final boolean isPackageChanged = !Objects.equals(packageName, oldPackage);
+ // TODO: Remove "SdkLevel.isAtLeastT()" check once VpnManagerService is decoupled from
+ // ConnectivityServiceTest.
+ // Only notify VPN apps that were already always-on, and only if the always-on provider
+ // changed, or the lockdown mode changed.
+ final boolean shouldNotifyOldPkg = isVpnApp(oldPackage) && mAlwaysOn
+ && (lockdown != mLockdown || isPackageChanged);
+ // Also notify the new package if there was a provider change.
+ final boolean shouldNotifyNewPkg = isVpnApp(packageName) && isPackageChanged;
if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) {
saveAlwaysOnPackage();
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (shouldNotifyOldPkg && SdkLevel.isAtLeastT()) {
+ // If both of shouldNotifyOldPkg & isPackageChanged are true, which means the
+ // always-on of old package is disabled or the old package is replaced with the new
+ // package. In this case, VpnProfileState should be disconnected.
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
+ -1 /* errorClass */, -1 /* errorCode*/, oldPackage,
+ null /* sessionKey */, isPackageChanged ? makeDisconnectedVpnProfileState()
+ : makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (shouldNotifyNewPkg && SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
+ -1 /* errorClass */, -1 /* errorCode*/, packageName,
+ getSessionKeyLocked(), makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
return true;
}
return false;
@@ -1012,6 +1078,7 @@ public class Vpn {
return true;
}
+ @GuardedBy("this")
private boolean isCurrentPreparedPackage(String packageName) {
// We can't just check that packageName matches mPackage, because if the app was uninstalled
// and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the
@@ -1049,6 +1116,17 @@ public class Vpn {
if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
mAppOpsManager.finishOp(
AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null);
+ // The underlying network, NetworkCapabilities and LinkProperties are not
+ // necessary to send to VPN app since the purpose of this event is to notify
+ // VPN app that VPN is deactivated by the user.
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
+ -1 /* errorClass */, -1 /* errorCode*/, mPackage,
+ getSessionKeyLocked(), makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
}
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
@@ -1305,6 +1383,7 @@ public class Vpn {
return true;
}
+ @GuardedBy("this")
private void agentConnect() {
LinkProperties lp = makeLinkProperties();
@@ -2005,6 +2084,7 @@ public class Vpn {
return isIkev2VpnRunner() ? VpnManager.TYPE_VPN_PLATFORM : VpnManager.TYPE_VPN_LEGACY;
}
+ @GuardedBy("this")
private void updateAlwaysOnNotification(DetailedState networkState) {
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
@@ -3593,11 +3673,19 @@ public class Vpn {
}
}
- private VpnProfileState makeVpnProfileState() {
+ @GuardedBy("this")
+ @NonNull
+ private VpnProfileState makeVpnProfileStateLocked() {
return new VpnProfileState(getStateFromLegacyState(mLegacyState),
isIkev2VpnRunner() ? getSessionKeyLocked() : null, mAlwaysOn, mLockdown);
}
+ @NonNull
+ private VpnProfileState makeDisconnectedVpnProfileState() {
+ return new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, null /* sessionKey */,
+ false /* alwaysOn */, false /* lockdown */);
+ }
+
/**
* Retrieve the VpnProfileState for the profile provisioned by the given package.
*
@@ -3609,7 +3697,7 @@ public class Vpn {
@NonNull String packageName) {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
- return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileState() : null;
+ return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileStateLocked() : null;
}
/**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index aa30c0897d60..a25ac210f9c8 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -152,6 +152,9 @@ import javax.xml.datatype.DatatypeConfigurationException;
* <screenBrightnessRampSlowDecrease>0.03</screenBrightnessRampSlowDecrease>
* <screenBrightnessRampSlowIncrease>0.04</screenBrightnessRampSlowIncrease>
*
+ * <screenBrightnessRampIncreaseMaxMillis>2000</screenBrightnessRampIncreaseMaxMillis>
+ * <screenBrightnessRampDecreaseMaxMillis>3000</screenBrightnessRampDecreaseMaxMillis>
+ *
* <lightSensor>
* <type>android.sensor.light</type>
* <name>1234 Ambient Light Sensor</name>
@@ -259,6 +262,8 @@ public class DisplayDeviceConfig {
private float mBrightnessRampFastIncrease = Float.NaN;
private float mBrightnessRampSlowDecrease = Float.NaN;
private float mBrightnessRampSlowIncrease = Float.NaN;
+ private long mBrightnessRampDecreaseMaxMillis = 0;
+ private long mBrightnessRampIncreaseMaxMillis = 0;
private int mAmbientHorizonLong = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
private int mAmbientHorizonShort = AMBIENT_LIGHT_SHORT_HORIZON_MILLIS;
private float mScreenBrighteningMinThreshold = 0.0f; // Retain behaviour as though there is
@@ -534,6 +539,14 @@ public class DisplayDeviceConfig {
return mBrightnessRampSlowIncrease;
}
+ public long getBrightnessRampDecreaseMaxMillis() {
+ return mBrightnessRampDecreaseMaxMillis;
+ }
+
+ public long getBrightnessRampIncreaseMaxMillis() {
+ return mBrightnessRampIncreaseMaxMillis;
+ }
+
public int getAmbientHorizonLong() {
return mAmbientHorizonLong;
}
@@ -628,6 +641,8 @@ public class DisplayDeviceConfig {
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
+ ", mBrightnessRampSlowIncrease=" + mBrightnessRampSlowIncrease
+ + ", mBrightnessRampDecreaseMaxMillis=" + mBrightnessRampDecreaseMaxMillis
+ + ", mBrightnessRampIncreaseMaxMillis=" + mBrightnessRampIncreaseMaxMillis
+ ", mAmbientHorizonLong=" + mAmbientHorizonLong
+ ", mAmbientHorizonShort=" + mAmbientHorizonShort
+ ", mScreenDarkeningMinThreshold=" + mScreenDarkeningMinThreshold
@@ -725,6 +740,8 @@ public class DisplayDeviceConfig {
mBrightnessRampFastIncrease = PowerManager.BRIGHTNESS_MAX;
mBrightnessRampSlowDecrease = PowerManager.BRIGHTNESS_MAX;
mBrightnessRampSlowIncrease = PowerManager.BRIGHTNESS_MAX;
+ mBrightnessRampDecreaseMaxMillis = 0;
+ mBrightnessRampIncreaseMaxMillis = 0;
setSimpleMappingStrategyValues();
loadAmbientLightSensorFromConfigXml();
setProxSensorUnspecified();
@@ -1115,6 +1132,15 @@ public class DisplayDeviceConfig {
}
loadBrightnessRampsFromConfigXml();
}
+
+ final BigInteger increaseMax = config.getScreenBrightnessRampIncreaseMaxMillis();
+ if (increaseMax != null) {
+ mBrightnessRampIncreaseMaxMillis = increaseMax.intValue();
+ }
+ final BigInteger decreaseMax = config.getScreenBrightnessRampDecreaseMaxMillis();
+ if (decreaseMax != null) {
+ mBrightnessRampDecreaseMaxMillis = decreaseMax.intValue();
+ }
}
private void loadBrightnessRampsFromConfigXml() {
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index 7dce2380407e..a4f49549c7eb 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -76,6 +76,8 @@ class DisplayManagerShellCommand extends ShellCommand {
return setUserDisabledHdrTypes();
case "get-user-disabled-hdr-types":
return getUserDisabledHdrTypes();
+ case "get-displays":
+ return getDisplays();
case "dock":
return setDockedAndIdle();
case "undock":
@@ -133,6 +135,9 @@ class DisplayManagerShellCommand extends ShellCommand {
pw.println(" Sets the user disabled HDR types as TYPES");
pw.println(" get-user-disabled-hdr-types");
pw.println(" Returns the user disabled HDR types");
+ pw.println(" get-displays [CATEGORY]");
+ pw.println(" Returns the current displays. Can specify string category among");
+ pw.println(" DisplayManager.DISPLAY_CATEGORY_*; must use the actual string value.");
pw.println(" dock");
pw.println(" Sets brightness to docked + idle screen brightness mode");
pw.println(" undock");
@@ -141,6 +146,18 @@ class DisplayManagerShellCommand extends ShellCommand {
Intent.printIntentArgsHelp(pw , "");
}
+ private int getDisplays() {
+ String category = getNextArg();
+ DisplayManager dm = mService.getContext().getSystemService(DisplayManager.class);
+ Display[] displays = dm.getDisplays(category);
+ PrintWriter out = getOutPrintWriter();
+ out.println("Displays:");
+ for (int i = 0; i < displays.length; i++) {
+ out.println(" " + displays[i]);
+ }
+ return 0;
+ }
+
private int setBrightness() {
String brightnessText = getNextArg();
if (brightnessText == null) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 80ff8349a153..d13a9a3ec27e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -255,6 +255,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// to reach the final state.
private final boolean mBrightnessBucketsInDozeConfig;
+ // Maximum time a ramp animation can take.
+ private long mBrightnessRampIncreaseMaxTimeMillis;
+ private long mBrightnessRampDecreaseMaxTimeMillis;
+
// The pending power request.
// Initially null until the first call to requestPowerState.
@GuardedBy("mLock")
@@ -507,7 +511,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final Resources resources = context.getResources();
-
// DOZE AND DIM SETTINGS
mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
@@ -641,7 +644,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
-
// If rbc is turned on, off or there is a change in strength, we want to reset the short
// term model. Since the nits range at which brightness now operates has changed due to
// RBC/strength change, any short term model based on the previous range should be
@@ -837,6 +839,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
loadNitsRange(mContext.getResources());
setUpAutoBrightness(mContext.getResources(), mHandler);
reloadReduceBrightColours();
+ if (mScreenBrightnessRampAnimator != null) {
+ mScreenBrightnessRampAnimator.setAnimationTimeLimits(
+ mBrightnessRampIncreaseMaxTimeMillis,
+ mBrightnessRampDecreaseMaxTimeMillis);
+ }
mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
mDisplayDeviceConfig.getHighBrightnessModeData(),
new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
@@ -883,6 +890,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mScreenBrightnessRampAnimator = new DualRampAnimator<>(mPowerState,
DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT,
DisplayPowerState.SCREEN_SDR_BRIGHTNESS_FLOAT);
+ mScreenBrightnessRampAnimator.setAnimationTimeLimits(
+ mBrightnessRampIncreaseMaxTimeMillis,
+ mBrightnessRampDecreaseMaxTimeMillis);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
noteScreenState(mPowerState.getScreenState());
@@ -1007,6 +1017,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
+ mBrightnessRampDecreaseMaxTimeMillis =
+ mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis();
+ mBrightnessRampIncreaseMaxTimeMillis =
+ mDisplayDeviceConfig.getBrightnessRampIncreaseMaxMillis();
}
private void loadNitsRange(Resources resources) {
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index 2567e4306293..690ec3fb5aaf 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -34,6 +34,8 @@ class RampAnimator<T> {
private float mCurrentValue;
private float mTargetValue;
private float mRate;
+ private float mAnimationIncreaseMaxTimeSecs;
+ private float mAnimationDecreaseMaxTimeSecs;
private boolean mAnimating;
private float mAnimatedValue; // higher precision copy of mCurrentValue
@@ -43,13 +45,24 @@ class RampAnimator<T> {
private Listener mListener;
- public RampAnimator(T object, FloatProperty<T> property) {
+ RampAnimator(T object, FloatProperty<T> property) {
mObject = object;
mProperty = property;
mChoreographer = Choreographer.getInstance();
}
/**
+ * Sets the maximum time that a brightness animation can take.
+ */
+ public void setAnimationTimeLimits(long animationRampIncreaseMaxTimeMillis,
+ long animationRampDecreaseMaxTimeMillis) {
+ mAnimationIncreaseMaxTimeSecs = (animationRampIncreaseMaxTimeMillis > 0)
+ ? (animationRampIncreaseMaxTimeMillis / 1000.0f) : 0.0f;
+ mAnimationDecreaseMaxTimeSecs = (animationRampDecreaseMaxTimeMillis > 0)
+ ? (animationRampDecreaseMaxTimeMillis / 1000.0f) : 0.0f;
+ }
+
+ /**
* Starts animating towards the specified value.
*
* If this is the first time the property is being set or if the rate is 0,
@@ -83,6 +96,15 @@ class RampAnimator<T> {
return false;
}
+ // Adjust the rate so that we do not exceed our maximum animation time.
+ if (target > mCurrentValue && mAnimationIncreaseMaxTimeSecs > 0.0f
+ && ((target - mCurrentValue) / rate) > mAnimationIncreaseMaxTimeSecs) {
+ rate = (target - mCurrentValue) / mAnimationIncreaseMaxTimeSecs;
+ } else if (target < mCurrentValue && mAnimationDecreaseMaxTimeSecs > 0.0f
+ && ((mCurrentValue - target) / rate) > mAnimationDecreaseMaxTimeSecs) {
+ rate = (mCurrentValue - target) / mAnimationDecreaseMaxTimeSecs;
+ }
+
// Adjust the rate based on the closest target.
// If a faster rate is specified, then use the new rate so that we converge
// more rapidly based on the new request.
@@ -209,6 +231,17 @@ class RampAnimator<T> {
}
/**
+ * Sets the maximum time that a brightness animation can take.
+ */
+ public void setAnimationTimeLimits(long animationRampIncreaseMaxTimeMillis,
+ long animationRampDecreaseMaxTimeMillis) {
+ mFirst.setAnimationTimeLimits(animationRampIncreaseMaxTimeMillis,
+ animationRampDecreaseMaxTimeMillis);
+ mSecond.setAnimationTimeLimits(animationRampIncreaseMaxTimeMillis,
+ animationRampDecreaseMaxTimeMillis);
+ }
+
+ /**
* Starts animating towards the specified values.
*
* If this is the first time the property is being set or if the rate is 0,
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
index caaf80073de1..f7089417a580 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
@@ -413,7 +413,7 @@ public class HdmiCecNetwork {
*/
boolean isConnectedToArcPort(int physicalAddress) {
int portId = physicalAddressToPortId(physicalAddress);
- if (portId != Constants.INVALID_PORT_ID) {
+ if (portId != Constants.INVALID_PORT_ID && portId != Constants.CEC_SWITCH_HOME) {
return mPortInfoMap.get(portId).isArcSupported();
}
return false;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 9e5da450c8a5..d536a463f7b4 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -40,6 +40,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioSystem;
@@ -85,6 +86,7 @@ import android.view.ViewConfiguration;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalManagerRegistry;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.Watchdog.Monitor;
@@ -540,14 +542,19 @@ public class MediaSessionService extends SystemService implements Monitor {
if (TextUtils.isEmpty(packageName)) {
throw new IllegalArgumentException("packageName may not be empty");
}
- String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
- final int packageCount = packages.length;
- for (int i = 0; i < packageCount; i++) {
- if (packageName.equals(packages[i])) {
- return;
- }
+ if (uid == Process.ROOT_UID || uid == Process.SHELL_UID) {
+ // If the caller is shell, then trust the packageName given and allow it
+ // to proceed.
+ return;
+ }
+ final PackageManagerInternal packageManagerInternal =
+ LocalServices.getService(PackageManagerInternal.class);
+ final int actualUid = packageManagerInternal.getPackageUid(
+ packageName, 0 /* flags */, UserHandle.getUserId(uid));
+ if (!UserHandle.isSameApp(uid, actualUid)) {
+ throw new IllegalArgumentException("packageName does not belong to the calling uid; "
+ + "pkg=" + packageName + ", uid=" + uid);
}
- throw new IllegalArgumentException("packageName is not owned by the calling process");
}
void tempAllowlistTargetPkgIfPossible(int targetUid, String targetPackage,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6dc1f372b602..3856633df28f 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -657,6 +657,9 @@ public class NotificationManagerService extends SystemService {
private int mWarnRemoteViewsSizeBytes;
private int mStripRemoteViewsSizeBytes;
+ @VisibleForTesting
+ protected boolean mShowReviewPermissionsNotification;
+
private MetricsLogger mMetricsLogger;
private NotificationChannelLogger mNotificationChannelLogger;
private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
@@ -2280,7 +2283,8 @@ public class NotificationManagerService extends SystemService {
mPermissionHelper,
mNotificationChannelLogger,
mAppOps,
- new SysUiStatsEvent.BuilderFactory());
+ new SysUiStatsEvent.BuilderFactory(),
+ mShowReviewPermissionsNotification);
mPreferencesHelper.updateFixedImportance(mUm.getUsers());
mRankingHelper = new RankingHelper(getContext(),
mRankingHandler,
@@ -2469,6 +2473,9 @@ public class NotificationManagerService extends SystemService {
WorkerHandler handler = new WorkerHandler(Looper.myLooper());
+ mShowReviewPermissionsNotification = getContext().getResources().getBoolean(
+ R.bool.config_notificationReviewPermissions);
+
init(handler, new RankingHandlerWorker(mRankingThread.getLooper()),
AppGlobals.getPackageManager(), getContext().getPackageManager(),
getLocalService(LightsManager.class),
@@ -6320,6 +6327,11 @@ public class NotificationManagerService extends SystemService {
@Override
public void sendReviewPermissionsNotification() {
+ if (!mShowReviewPermissionsNotification) {
+ // don't show if this notification is turned off
+ return;
+ }
+
// This method is meant to be called from the JobService upon running the job for this
// notification having been rescheduled; so without checking any other state, it will
// send the notification.
@@ -11648,6 +11660,11 @@ public class NotificationManagerService extends SystemService {
}
protected void maybeShowInitialReviewPermissionsNotification() {
+ if (!mShowReviewPermissionsNotification) {
+ // if this notification is disabled by settings do not ever show it
+ return;
+ }
+
int currentState = Settings.Global.getInt(getContext().getContentResolver(),
Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
REVIEW_NOTIF_STATE_UNKNOWN);
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 97133a56779d..477b8da61e0f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -86,7 +86,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -191,6 +190,7 @@ public class PreferencesHelper implements RankingConfig {
private boolean mIsMediaNotificationFilteringEnabled = DEFAULT_MEDIA_NOTIFICATION_FILTERING;
private boolean mAreChannelsBypassingDnd;
private boolean mHideSilentStatusBarIcons = DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS;
+ private boolean mShowReviewPermissionsNotification;
private boolean mAllowInvalidShortcuts = false;
@@ -198,7 +198,8 @@ public class PreferencesHelper implements RankingConfig {
ZenModeHelper zenHelper, PermissionHelper permHelper,
NotificationChannelLogger notificationChannelLogger,
AppOpsManager appOpsManager,
- SysUiStatsEvent.BuilderFactory statsEventBuilderFactory) {
+ SysUiStatsEvent.BuilderFactory statsEventBuilderFactory,
+ boolean showReviewPermissionsNotification) {
mContext = context;
mZenModeHelper = zenHelper;
mRankingHandler = rankingHandler;
@@ -207,6 +208,7 @@ public class PreferencesHelper implements RankingConfig {
mNotificationChannelLogger = notificationChannelLogger;
mAppOps = appOpsManager;
mStatsEventBuilderFactory = statsEventBuilderFactory;
+ mShowReviewPermissionsNotification = showReviewPermissionsNotification;
XML_VERSION = 4;
@@ -226,7 +228,8 @@ public class PreferencesHelper implements RankingConfig {
final int xmlVersion = parser.getAttributeInt(null, ATT_VERSION, -1);
boolean upgradeForBubbles = xmlVersion == XML_VERSION_BUBBLES_UPGRADE;
boolean migrateToPermission = (xmlVersion < XML_VERSION_NOTIF_PERMISSION);
- if (xmlVersion < XML_VERSION_REVIEW_PERMISSIONS_NOTIFICATION) {
+ if (mShowReviewPermissionsNotification
+ && (xmlVersion < XML_VERSION_REVIEW_PERMISSIONS_NOTIFICATION)) {
// make a note that we should show the notification at some point.
// it shouldn't be possible for the user to already have seen it, as the XML version
// would be newer then.
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 0e9a04f1fdde..09044e72f60b 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -57,6 +57,16 @@
<xs:element type="nonNegativeDecimal" name="screenBrightnessRampSlowIncrease">
<xs:annotation name="final"/>
</xs:element>
+ <!-- Maximum time in milliseconds that a brightness increase animation
+ can take. -->
+ <xs:element type="xs:nonNegativeInteger" name="screenBrightnessRampIncreaseMaxMillis">
+ <xs:annotation name="final"/>
+ </xs:element>
+ <!-- Maximum time in milliseconds that a brightness decrease animation
+ can take. -->
+ <xs:element type="xs:nonNegativeInteger" name="screenBrightnessRampDecreaseMaxMillis">
+ <xs:annotation name="final"/>
+ </xs:element>
<xs:element type="sensorDetails" name="lightSensor">
<xs:annotation name="final"/>
</xs:element>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 075edd77af1d..e8b13ca6356e 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -48,8 +48,10 @@ package com.android.server.display.config {
method public com.android.server.display.config.DisplayQuirks getQuirks();
method @NonNull public final java.math.BigDecimal getScreenBrightnessDefault();
method @NonNull public final com.android.server.display.config.NitsMap getScreenBrightnessMap();
+ method public final java.math.BigInteger getScreenBrightnessRampDecreaseMaxMillis();
method public final java.math.BigDecimal getScreenBrightnessRampFastDecrease();
method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
+ method public final java.math.BigInteger getScreenBrightnessRampIncreaseMaxMillis();
method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
@@ -64,8 +66,10 @@ package com.android.server.display.config {
method public void setQuirks(com.android.server.display.config.DisplayQuirks);
method public final void setScreenBrightnessDefault(@NonNull java.math.BigDecimal);
method public final void setScreenBrightnessMap(@NonNull com.android.server.display.config.NitsMap);
+ method public final void setScreenBrightnessRampDecreaseMaxMillis(java.math.BigInteger);
method public final void setScreenBrightnessRampFastDecrease(java.math.BigDecimal);
method public final void setScreenBrightnessRampFastIncrease(java.math.BigDecimal);
+ method public final void setScreenBrightnessRampIncreaseMaxMillis(java.math.BigInteger);
method public final void setScreenBrightnessRampSlowDecrease(java.math.BigDecimal);
method public final void setScreenBrightnessRampSlowIncrease(java.math.BigDecimal);
method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index a7dc8518daea..779673e98c6f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -19,7 +19,6 @@ package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.Notification.FLAG_AUTO_CANCEL;
import static android.app.Notification.FLAG_BUBBLE;
import static android.app.Notification.FLAG_CAN_COLORIZE;
@@ -9572,7 +9571,21 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testMaybeShowReviewPermissionsNotification_flagOff() {
+ mService.setShowReviewPermissionsNotification(false);
+ reset(mMockNm);
+
+ // If state is SHOULD_SHOW, it would show, but not if the flag is off!
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
+ NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
+ mService.maybeShowInitialReviewPermissionsNotification();
+ verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
+ }
+
+ @Test
public void testMaybeShowReviewPermissionsNotification_unknown() {
+ mService.setShowReviewPermissionsNotification(true);
reset(mMockNm);
// Set up various possible states of the settings int and confirm whether or not the
@@ -9588,6 +9601,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testMaybeShowReviewPermissionsNotification_shouldShow() {
+ mService.setShowReviewPermissionsNotification(true);
reset(mMockNm);
// If state is SHOULD_SHOW, it ... should show
@@ -9602,6 +9616,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testMaybeShowReviewPermissionsNotification_alreadyShown() {
+ mService.setShowReviewPermissionsNotification(true);
reset(mMockNm);
// If state is either USER_INTERACTED or DISMISSED, we should not show this on boot
@@ -9620,6 +9635,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testMaybeShowReviewPermissionsNotification_reshown() {
+ mService.setShowReviewPermissionsNotification(true);
reset(mMockNm);
// If we have re-shown the notification and the user did not subsequently interacted with
@@ -9635,6 +9651,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRescheduledReviewPermissionsNotification() {
+ mService.setShowReviewPermissionsNotification(true);
reset(mMockNm);
// when rescheduled, the notification goes through the NotificationManagerInternal service
@@ -9653,4 +9670,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN));
}
+
+ @Test
+ public void testRescheduledReviewPermissionsNotification_flagOff() {
+ mService.setShowReviewPermissionsNotification(false);
+ reset(mMockNm);
+
+ // no notification should be sent if the flag is off
+ mInternalService.sendReviewPermissionsNotification();
+ verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 8d50ceaf74e9..598a22bbde39 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -292,7 +292,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory();
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
resetZenModeHelper();
mAudioAttributes = new AudioAttributes.Builder()
@@ -621,7 +621,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testReadXml_oldXml_migrates() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
String xml = "<ranking version=\"2\">\n"
+ "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1
@@ -691,7 +691,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testReadXml_oldXml_backup_migratesWhenPkgInstalled() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
when(mPm.getPackageUidAsUser("pkg1", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
when(mPm.getPackageUidAsUser("pkg2", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
@@ -769,7 +769,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
String xml = "<ranking version=\"3\">\n"
+ "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -824,9 +824,66 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testReadXml_newXml_permissionNotificationOff() throws Exception {
+ mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+
+ String xml = "<ranking version=\"3\">\n"
+ + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
+ + "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n"
+ + "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n"
+ + "</package>\n"
+ + "<package name=\"" + PKG_O + "\" >\n"
+ + "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n"
+ + "</package>\n"
+ + "<package name=\"" + PKG_P + "\" >\n"
+ + "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n"
+ + "</package>\n"
+ + "</ranking>\n";
+ NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW);
+ idn.setSound(null, new AudioAttributes.Builder()
+ .setUsage(USAGE_NOTIFICATION)
+ .setContentType(CONTENT_TYPE_SONIFICATION)
+ .setFlags(0)
+ .build());
+ idn.setShowBadge(false);
+ NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW);
+ ido.setShowBadge(true);
+ ido.setSound(null, new AudioAttributes.Builder()
+ .setUsage(USAGE_NOTIFICATION)
+ .setContentType(CONTENT_TYPE_SONIFICATION)
+ .setFlags(0)
+ .build());
+ NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH);
+ idp.lockFields(2);
+ idp.setSound(null, new AudioAttributes.Builder()
+ .setUsage(USAGE_NOTIFICATION)
+ .setContentType(CONTENT_TYPE_SONIFICATION)
+ .setFlags(0)
+ .build());
+
+ loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM);
+
+ assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+
+ assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false));
+ compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false));
+ compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false));
+
+ verify(mPermissionHelper, never()).setNotificationPermission(any());
+
+ // while this is the same case as above, if the permission helper is set to not show the
+ // review permissions notification it should not write anything to the settings int
+ assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN,
+ Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
+ NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN));
+ }
+
+ @Test
public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
String xml = "<ranking version=\"4\">\n"
+ "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -882,7 +939,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testReadXml_oldXml_migration_NoUid() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
String xml = "<ranking version=\"2\">\n"
@@ -915,7 +972,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testReadXml_newXml_noMigration_NoUid() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
String xml = "<ranking version=\"3\">\n"
@@ -947,7 +1004,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testChannelXmlForNonBackup_postMigration() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
appPermissions.put(new Pair(1, "first"), new Pair(true, false));
@@ -1027,7 +1084,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testChannelXmlForBackup_postMigration() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
appPermissions.put(new Pair(1, "first"), new Pair(true, false));
@@ -1113,7 +1170,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testChannelXmlForBackup_postMigration_noExternal() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));
@@ -1192,7 +1249,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testChannelXmlForBackup_postMigration_noLocalSettings() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
- mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
appPermissions.put(new Pair(1, "first"), new Pair(true, false));
@@ -2117,7 +2174,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
// create notification channel that can bypass dnd, but app is blocked
@@ -2145,7 +2202,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
// create notification channel that can bypass dnd, but app is blocked
// expected result: areChannelsBypassingDnd = false
@@ -2168,7 +2225,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
// create notification channel that can bypass dnd, but app is blocked
// expected result: areChannelsBypassingDnd = false
@@ -2220,7 +2277,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
assertFalse(mHelper.areChannelsBypassingDnd());
verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
resetZenModeHelper();
@@ -2233,7 +2290,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
assertFalse(mHelper.areChannelsBypassingDnd());
verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
resetZenModeHelper();
@@ -3229,7 +3286,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
+ "</ranking>\n";
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadByteArrayXml(preQXml.getBytes(), true, USER_SYSTEM);
assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
@@ -3243,7 +3300,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
@@ -3341,7 +3398,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
@@ -3354,7 +3411,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
@@ -3368,7 +3425,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
@@ -3382,7 +3439,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
// appears disabled
@@ -3402,7 +3459,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
// appears disabled
@@ -3422,7 +3479,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O));
@@ -3478,7 +3535,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O));
@@ -3516,7 +3573,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
loadStreamXml(baos, false, UserHandle.USER_ALL);
assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE);
@@ -4150,7 +4207,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testPlaceholderConversationId_shortcutRequired() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
final String xml = "<ranking version=\"1\">\n"
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4170,7 +4227,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testNormalConversationId_shortcutRequired() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
final String xml = "<ranking version=\"1\">\n"
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4190,7 +4247,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testNoConversationId_shortcutRequired() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
final String xml = "<ranking version=\"1\">\n"
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4210,7 +4267,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testDeleted_noTime() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
final String xml = "<ranking version=\"1\">\n"
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4230,7 +4287,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testDeleted_twice() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
mHelper.createNotificationChannel(
PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false);
@@ -4242,7 +4299,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testDeleted_recentTime() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
mHelper.createNotificationChannel(
PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false);
@@ -4260,7 +4317,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
parser.nextTag();
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
mHelper.readXml(parser, true, USER_SYSTEM);
NotificationChannel nc = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true);
@@ -4272,7 +4329,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testUnDelete_time() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
mHelper.createNotificationChannel(
PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false);
@@ -4292,7 +4349,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testDeleted_longTime() throws Exception {
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
mPermissionHelper, mLogger,
- mAppOpsManager, mStatsEventBuilderFactory);
+ mAppOpsManager, mStatsEventBuilderFactory, false);
long time = System.currentTimeMillis() - (DateUtils.DAY_IN_MILLIS * 30);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
index 4ed7d35a097f..b49e5cbfa9dc 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
@@ -114,6 +114,11 @@ public class TestableNotificationManagerService extends NotificationManagerServi
mChannelToastsSent.add(uid);
}
+ // Helper method for testing behavior when turning on/off the review permissions notification.
+ protected void setShowReviewPermissionsNotification(boolean setting) {
+ mShowReviewPermissionsNotification = setting;
+ }
+
public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
private int mGetStrongAuthForUserReturnValue = 0;
StrongAuthTrackerFake(Context context) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 43fcc8feaec2..73b2510e6cf1 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -35,6 +35,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ShortcutServiceInternal;
@@ -104,6 +105,7 @@ import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.soundtrigger.SoundTriggerInternal;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal.ActivityTokens;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -126,6 +128,7 @@ public class VoiceInteractionManagerService extends SystemService {
final ActivityManagerInternal mAmInternal;
final ActivityTaskManagerInternal mAtmInternal;
final UserManagerInternal mUserManagerInternal;
+ final PackageManagerInternal mPackageManagerInternal;
final ArrayMap<Integer, VoiceInteractionManagerServiceStub.SoundTriggerSession>
mLoadedKeyphraseIds = new ArrayMap<>();
ShortcutServiceInternal mShortcutServiceInternal;
@@ -146,6 +149,8 @@ public class VoiceInteractionManagerService extends SystemService {
LocalServices.getService(ActivityTaskManagerInternal.class));
mUserManagerInternal = Objects.requireNonNull(
LocalServices.getService(UserManagerInternal.class));
+ mPackageManagerInternal = Objects.requireNonNull(
+ LocalServices.getService(PackageManagerInternal.class));
LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService(
LegacyPermissionManagerInternal.class);
@@ -369,6 +374,21 @@ public class VoiceInteractionManagerService extends SystemService {
return new SoundTriggerSessionBinderProxy(session);
}
+ @GuardedBy("this")
+ private void grantImplicitAccessLocked(int grantRecipientUid, @Nullable Intent intent) {
+ if (mImpl == null) {
+ Slog.w(TAG, "Cannot grant implicit access because mImpl is null.");
+ return;
+ }
+
+ final int grantRecipientAppId = UserHandle.getAppId(grantRecipientUid);
+ final int grantRecipientUserId = UserHandle.getUserId(grantRecipientUid);
+ final int voiceInteractionUid = mImpl.mInfo.getServiceInfo().applicationInfo.uid;
+ mPackageManagerInternal.grantImplicitAccess(
+ grantRecipientUserId, intent, grantRecipientAppId, voiceInteractionUid,
+ /* direct= */ true);
+ }
+
private IVoiceInteractionSoundTriggerSession createSoundTriggerSessionForSelfIdentity(
IBinder client) {
Identity identity = new Identity();
@@ -386,6 +406,7 @@ public class VoiceInteractionManagerService extends SystemService {
void startLocalVoiceInteraction(final IBinder token, Bundle options) {
if (mImpl == null) return;
+ final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
mImpl.showSessionLocked(options,
@@ -397,6 +418,11 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public void onShown() {
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ VoiceInteractionManagerServiceStub.this
+ .grantImplicitAccessLocked(callingUid,
+ /* intent= */ null);
+ }
mAtmInternal.onLocalVoiceInteractionStarted(token,
mImpl.mActiveSession.mSession,
mImpl.mActiveSession.mInteractor);
@@ -965,8 +991,16 @@ public class VoiceInteractionManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- return mImpl.startVoiceActivityLocked(callingFeatureId, callingPid, callingUid,
- token, intent, resolvedType);
+ final ActivityInfo activityInfo = intent.resolveActivityInfo(
+ mContext.getPackageManager(), PackageManager.MATCH_ALL);
+ if (activityInfo != null) {
+ final int activityUid = activityInfo.applicationInfo.uid;
+ grantImplicitAccessLocked(activityUid, intent);
+ } else {
+ Slog.w(TAG, "Cannot find ActivityInfo in startVoiceActivity.");
+ }
+ return mImpl.startVoiceActivityLocked(
+ callingFeatureId, callingPid, callingUid, token, intent, resolvedType);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -1005,6 +1039,15 @@ public class VoiceInteractionManagerService extends SystemService {
}
final long caller = Binder.clearCallingIdentity();
try {
+ // Getting the UID corresponding to the taskId, and grant the visibility to it.
+ final ActivityTokens tokens = mAtmInternal
+ .getAttachedNonFinishingActivityForTask(taskId, /* token= */ null);
+ final ComponentName componentName = mAtmInternal.getActivityName(
+ tokens.getActivityToken());
+ grantImplicitAccessLocked(mPackageManagerInternal.getPackageUid(
+ componentName.getPackageName(), PackageManager.MATCH_ALL,
+ UserHandle.myUserId()), /* intent= */ null);
+
mImpl.requestDirectActionsLocked(token, taskId, assistToken,
cancellationCallback, resultCallback);
} finally {
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index fa1bae41f433..5e111639b100 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -232,13 +232,14 @@ public final class DataProfile implements Parcelable {
}
/**
- * @return True if the profile is enabled.
+ * @return {@code true} if the profile is enabled. If the profile only has a
+ * {@link TrafficDescriptor}, but no {@link ApnSetting}, then this profile is always enabled.
*/
public boolean isEnabled() {
if (mApnSetting != null) {
return mApnSetting.isEnabled();
}
- return false;
+ return true;
}
/**
@@ -534,7 +535,7 @@ public final class DataProfile implements Parcelable {
@Type
private int mType = -1;
- private boolean mEnabled;
+ private boolean mEnabled = true;
@ApnType
private int mSupportedApnTypesBitmask;