Merge "Disable blocking helper" into qt-dev
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 12474ce..68a8816 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -156,7 +156,7 @@
KeyValuePairsAtom key_value_pairs_atom = 83 [(allow_from_any_uid) = true];
VibratorStateChanged vibrator_state_changed = 84;
DeferredJobStatsReported deferred_job_stats_reported = 85;
- ThermalThrottlingStateChanged thermal_throttling = 86;
+ ThermalThrottlingStateChanged thermal_throttling = 86 [deprecated=true];
BiometricAcquired biometric_acquired = 87;
BiometricAuthenticated biometric_authenticated = 88;
BiometricErrorOccurred biometric_error_occurred = 89;
@@ -270,7 +270,7 @@
HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
StyleUIChanged style_ui_changed = 179;
PrivacyIndicatorsInteracted privacy_indicators_interacted =
- 180 [(log_from_module) = "permissioncontroller"];
+ 180 [(log_from_module) = "permissioncontroller"];
AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
AppMovedStorageReported app_moved_storage_reported = 183;
@@ -280,6 +280,7 @@
BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
IntelligenceEventReported intelligence_event_reported =
188 [(log_from_module) = "intelligence"];
+ ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
}
// Pulled events will start at field 10000.
@@ -409,6 +410,7 @@
*/
/**
+ * This atom is deprecated starting in Q. Please use ThermalThrottlingSeverityStateChanged.
* Logs when the Thermal service HAL notifies the throttling start/stop events.
*
* Logged from:
@@ -426,14 +428,7 @@
}
optional State state = 2;
- // Temperature in deci degrees celsius
optional float temperature = 3;
-
- // Severity of throttling
- optional android.os.ThrottlingSeverityEnum severity = 4;
-
- // Thermistor name
- optional string sensor_name = 5;
}
/**
@@ -2364,6 +2359,27 @@
}
/**
+ * Logs when ThermalService receives throttling events.
+ *
+ * Logged from:
+ * frameworks/base/services/core/java/com/android/server/stats/StatsCompanionService.java
+ */
+message ThermalThrottlingSeverityStateChanged {
+ // The type of temperature being reported (CPU, GPU, SKIN, etc)
+ optional android.os.TemperatureTypeEnum sensor_type = 1;
+
+ // The name of the temperature source. Eg. CPU0
+ optional string sensor_name = 2;
+
+ // Temperature in tenths of a degree C.
+ // For BCL, it is decimillivolt, decimilliamps, and percentage * 10.
+ optional int32 temperature_deci_celsius = 3;
+
+ // Relative severity of the throttling, see enum definition.
+ optional android.os.ThrottlingSeverityEnum severity = 4;
+}
+
+/**
* Logs the duration of a davey (jank of >=700ms) when it occurs
*
* Logged from:
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
deleted file mode 100644
index 01c7587..0000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2017, 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.
- */
-
-#define DEBUG false // STOPSHIP if true
-#include "Log.h"
-
-#include <sstream>
-#include "MemoryLeakTrackUtil.h"
-
-/*
- * The code here originally resided in MediaPlayerService.cpp
- */
-
-// Figure out the abi based on defined macros.
-#if defined(__arm__)
-#define ABI_STRING "arm"
-#elif defined(__aarch64__)
-#define ABI_STRING "arm64"
-#elif defined(__mips__) && !defined(__LP64__)
-#define ABI_STRING "mips"
-#elif defined(__mips__) && defined(__LP64__)
-#define ABI_STRING "mips64"
-#elif defined(__i386__)
-#define ABI_STRING "x86"
-#elif defined(__x86_64__)
-#define ABI_STRING "x86_64"
-#else
-#error "Unsupported ABI"
-#endif
-
-extern std::string backtrace_string(const uintptr_t* frames, size_t frame_count);
-
-namespace android {
-namespace os {
-namespace statsd {
-
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, size_t* infoSize,
- size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
-std::string dumpMemInfo(size_t limit) {
- uint8_t* info;
- size_t overallSize;
- size_t infoSize;
- size_t totalMemory;
- size_t backtraceSize;
- get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
-
- size_t count;
- if (info == nullptr || overallSize == 0 || infoSize == 0 ||
- (count = overallSize / infoSize) == 0) {
- VLOG("no malloc info, libc.debug.malloc.program property should be set");
- return std::string();
- }
-
- std::ostringstream oss;
- oss << totalMemory << " bytes in " << count << " allocations\n";
- oss << " ABI: '" ABI_STRING "'"
- << "\n\n";
- if (count > limit) count = limit;
-
- // The memory is sorted based on total size which is useful for finding
- // worst memory offenders. For diffs, sometimes it is preferable to sort
- // based on the backtrace.
- for (size_t i = 0; i < count; i++) {
- struct AllocEntry {
- size_t size; // bit 31 is set if this is zygote allocated memory
- size_t allocations;
- uintptr_t backtrace[];
- };
-
- const AllocEntry* const e = (AllocEntry*)(info + i * infoSize);
-
- oss << (e->size * e->allocations) << " bytes ( " << e->size << " bytes * " << e->allocations
- << " allocations )\n";
- oss << backtrace_string(e->backtrace, backtraceSize) << "\n";
- }
- oss << "\n";
- free_malloc_leak_info(info);
- return oss.str();
-}
-
-} // namespace statsd
-} // namespace os
-} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
deleted file mode 100644
index 444ed92..0000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017, 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.
- */
-#pragma once
-
-#include <iostream>
-
-namespace android {
-namespace os {
-namespace statsd {
-/*
- * Dump the heap memory of the calling process, sorted by total size
- * (allocation size * number of allocations).
- *
- * limit is the number of unique allocations to return.
- */
-extern std::string dumpMemInfo(size_t limit);
-
-} // namespace statsd
-} // namespace os
-} // namespace android
\ No newline at end of file
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 86b10b9..0d22f3a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -773,6 +773,8 @@
private static final int LOG_AM_ON_RESTART_CALLED = 30058;
private static final int LOG_AM_ON_DESTROY_CALLED = 30060;
private static final int LOG_AM_ON_ACTIVITY_RESULT_CALLED = 30062;
+ private static final int LOG_AM_ON_TOP_RESUMED_GAINED_CALLED = 30064;
+ private static final int LOG_AM_ON_TOP_RESUMED_LOST_CALLED = 30065;
private static class ManagedDialog {
Dialog mDialog;
@@ -1840,6 +1842,13 @@
public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
}
+ final void performTopResumedActivityChanged(boolean isTopResumedActivity, String reason) {
+ onTopResumedActivityChanged(isTopResumedActivity);
+
+ writeEventLog(isTopResumedActivity
+ ? LOG_AM_ON_TOP_RESUMED_GAINED_CALLED : LOG_AM_ON_TOP_RESUMED_LOST_CALLED, reason);
+ }
+
void setVoiceInteractor(IVoiceInteractor voiceInteractor) {
if (mVoiceInteractor != null) {
for (Request activeRequest: mVoiceInteractor.getActiveRequests()) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 474f25b..13add09 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4026,7 +4026,7 @@
r.persistentState = null;
r.setState(ON_RESUME);
- reportTopResumedActivityChanged(r, r.isTopResumedActivity);
+ reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to resume activity "
@@ -4201,7 +4201,7 @@
r.isTopResumedActivity = onTop;
if (r.getLifecycleState() == ON_RESUME) {
- reportTopResumedActivityChanged(r, onTop);
+ reportTopResumedActivityChanged(r, onTop, "topStateChangedWhenResumed");
} else {
if (DEBUG_ORDER) {
Slog.d(TAG, "Won't deliver top position change in state=" + r.getLifecycleState());
@@ -4213,10 +4213,11 @@
* Call {@link Activity#onTopResumedActivityChanged(boolean)} if its top resumed state changed
* since the last report.
*/
- private void reportTopResumedActivityChanged(ActivityClientRecord r, boolean onTop) {
+ private void reportTopResumedActivityChanged(ActivityClientRecord r, boolean onTop,
+ String reason) {
if (r.lastReportedTopResumedState != onTop) {
r.lastReportedTopResumedState = onTop;
- r.activity.onTopResumedActivityChanged(onTop);
+ r.activity.performTopResumedActivityChanged(onTop, reason);
}
}
@@ -4313,7 +4314,7 @@
// Always reporting top resumed position loss when pausing an activity. If necessary, it
// will be restored in performResumeActivity().
- reportTopResumedActivityChanged(r, false /* onTop */);
+ reportTopResumedActivityChanged(r, false /* onTop */, "pausing");
try {
r.activity.mCalled = false;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 6c498c7..9215de1 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -267,6 +267,13 @@
public static final String NAMESPACE_CONTACTS_PROVIDER = "contacts_provider";
/**
+ * Namespace for settings ui related features
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
+
+ /**
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
*
* @hide
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 59e867f..8380115 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -200,7 +200,6 @@
private ChooserListAdapter mChooserListAdapter;
private ChooserRowAdapter mChooserRowAdapter;
- private Drawable mChooserRowLayer;
private int mChooserRowServiceSpacing;
/** {@link ChooserActivity#getBaseScore} */
@@ -219,6 +218,8 @@
private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED = 4;
private static final int LIST_VIEW_UPDATE_MESSAGE = 5;
+ private static final int MAX_LOG_RANK_POSITION = 12;
+
@VisibleForTesting
public static final int LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS = 250;
@@ -466,7 +467,6 @@
.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
}
- mChooserRowLayer = getResources().getDrawable(R.drawable.chooser_row_layer_list, null);
mChooserRowServiceSpacing = getResources()
.getDimensionPixelSize(R.dimen.chooser_service_spacing);
@@ -1015,6 +1015,7 @@
// Lower values mean the ranking was better.
int cat = 0;
int value = which;
+ int directTargetAlsoRanked = -1;
HashedStringCache.HashResult directTargetHashed = null;
switch (mChooserListAdapter.getPositionTargetType(which)) {
case ChooserListAdapter.TARGET_CALLER:
@@ -1034,6 +1035,7 @@
target.getComponentName().getPackageName()
+ target.getTitle().toString(),
mMaxHashSaltDays);
+ directTargetAlsoRanked = getRankedPosition((SelectableTargetInfo) targetInfo);
break;
case ChooserListAdapter.TARGET_STANDARD:
cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
@@ -1056,6 +1058,8 @@
targetLogMaker.addTaggedData(
MetricsEvent.FIELD_HASHED_TARGET_SALT_GEN,
directTargetHashed.saltGeneration);
+ targetLogMaker.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION,
+ directTargetAlsoRanked);
}
getMetricsLogger().write(targetLogMaker);
MetricsLogger.action(this, cat, value);
@@ -1074,6 +1078,21 @@
}
}
+ private int getRankedPosition(SelectableTargetInfo targetInfo) {
+ String targetPackageName =
+ targetInfo.getChooserTarget().getComponentName().getPackageName();
+ int maxRankedResults = Math.min(mChooserListAdapter.mDisplayList.size(),
+ MAX_LOG_RANK_POSITION);
+
+ for (int i = 0; i < maxRankedResults; i++) {
+ if (mChooserListAdapter.mDisplayList.get(i)
+ .getResolveInfo().activityInfo.packageName.equals(targetPackageName)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
void queryTargetServices(ChooserListAdapter adapter) {
final PackageManager pm = getPackageManager();
ShortcutManager sm = (ShortcutManager) getSystemService(ShortcutManager.class);
@@ -1931,6 +1950,7 @@
int offset = 0;
int rowsToShow = mChooserRowAdapter.getContentPreviewRowCount()
+ + mChooserRowAdapter.getProfileRowCount()
+ mChooserRowAdapter.getServiceTargetRowCount()
+ mChooserRowAdapter.getCallerAndRankedTargetRowCount();
@@ -1950,7 +1970,7 @@
}
int lastHeight = 0;
- rowsToShow = Math.max(3, rowsToShow);
+ rowsToShow = Math.min(4, rowsToShow);
for (int i = 0; i < Math.min(rowsToShow, mAdapterView.getChildCount()); i++) {
lastHeight = mAdapterView.getChildAt(i).getHeight();
offset += lastHeight;
@@ -2426,6 +2446,7 @@
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
private static final int VIEW_TYPE_CONTENT_PREVIEW = 2;
+ private static final int VIEW_TYPE_PROFILE = 3;
private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4;
private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8;
@@ -2481,9 +2502,9 @@
@Override
public int getCount() {
-
return (int) (
getContentPreviewRowCount()
+ + getProfileRowCount()
+ getServiceTargetRowCount()
+ getCallerAndRankedTargetRowCount()
+ Math.ceil(
@@ -2504,6 +2525,10 @@
return 1;
}
+ public int getProfileRowCount() {
+ return mChooserListAdapter.getOtherProfile() == null ? 0 : 1;
+ }
+
public int getCallerAndRankedTargetRowCount() {
return (int) Math.ceil(
((float) mChooserListAdapter.getCallerTargetCount()
@@ -2539,6 +2564,10 @@
return createContentPreviewView(convertView, parent);
}
+ if (viewType == VIEW_TYPE_PROFILE) {
+ return createProfileView(convertView, parent);
+ }
+
if (convertView == null) {
holder = createViewHolder(viewType, parent);
} else {
@@ -2556,6 +2585,10 @@
return VIEW_TYPE_CONTENT_PREVIEW;
}
+ if (getProfileRowCount() == 1 && position == getContentPreviewRowCount()) {
+ return VIEW_TYPE_PROFILE;
+ }
+
final int start = getFirstRowPosition(position);
final int startType = mChooserListAdapter.getPositionTargetType(start);
@@ -2568,7 +2601,7 @@
@Override
public int getViewTypeCount() {
- return 3;
+ return 4;
}
private ViewGroup createContentPreviewView(View convertView, ViewGroup parent) {
@@ -2584,6 +2617,17 @@
(ViewGroup) convertView, parent);
}
+ private View createProfileView(View convertView, ViewGroup parent) {
+ View profileRow = convertView != null ? convertView : mLayoutInflater.inflate(
+ R.layout.chooser_profile_row, parent, false);
+ profileRow.setBackground(
+ getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
+ mProfileView = profileRow.findViewById(R.id.profile_button);
+ mProfileView.setOnClickListener(ChooserActivity.this::onProfileClick);
+ bindProfileView();
+ return profileRow;
+ }
+
private RowViewHolder loadViewsIntoRow(RowViewHolder holder) {
final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int exactSpec = MeasureSpec.makeMeasureSpec(mChooserTargetWidth,
@@ -2702,8 +2746,10 @@
final ViewGroup row = holder.getViewGroup();
- if (startType != lastStartType || rowPosition == getContentPreviewRowCount()) {
- row.setBackground(mChooserRowLayer);
+ if (startType != lastStartType
+ || rowPosition == getContentPreviewRowCount() + getProfileRowCount()) {
+ row.setBackground(
+ getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
} else {
row.setBackground(null);
}
@@ -2753,7 +2799,7 @@
}
int getFirstRowPosition(int row) {
- row -= getContentPreviewRowCount();
+ row -= getContentPreviewRowCount() + getProfileRowCount();
final int serviceCount = mChooserListAdapter.getServiceTargetCount();
final int serviceRows = (int) Math.ceil((float) serviceCount
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ad1e767..2849f57 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -108,7 +108,7 @@
private Button mAlwaysButton;
private Button mOnceButton;
private Button mSettingsButton;
- private View mProfileView;
+ protected View mProfileView;
private int mIconDpi;
private int mLastSelected = AbsListView.INVALID_POSITION;
private boolean mResolvingHome = false;
@@ -142,9 +142,7 @@
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override public void onSomePackagesChanged() {
mAdapter.handlePackagesChanged();
- if (mProfileView != null) {
- bindProfileView();
- }
+ bindProfileView();
}
@Override
@@ -336,21 +334,7 @@
mProfileView = findViewById(R.id.profile_button);
if (mProfileView != null) {
- mProfileView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final DisplayResolveInfo dri = mAdapter.getOtherProfile();
- if (dri == null) {
- return;
- }
-
- // Do not show the profile switch message anymore.
- mProfileSwitchMessageId = -1;
-
- onTargetSelected(dri, false);
- finish();
- }
- });
+ mProfileView.setOnClickListener(this::onProfileClick);
bindProfileView();
}
@@ -367,6 +351,19 @@
+ (categories != null ? Arrays.toString(categories.toArray()) : ""));
}
+ protected void onProfileClick(View v) {
+ final DisplayResolveInfo dri = mAdapter.getOtherProfile();
+ if (dri == null) {
+ return;
+ }
+
+ // Do not show the profile switch message anymore.
+ mProfileSwitchMessageId = -1;
+
+ onTargetSelected(dri, false);
+ finish();
+ }
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -445,7 +442,11 @@
return R.layout.resolver_list;
}
- void bindProfileView() {
+ protected void bindProfileView() {
+ if (mProfileView == null) {
+ return;
+ }
+
final DisplayResolveInfo dri = mAdapter.getOtherProfile();
if (dri != null) {
mProfileView.setVisibility(View.VISIBLE);
@@ -709,9 +710,7 @@
mRegistered = true;
}
mAdapter.handlePackagesChanged();
- if (mProfileView != null) {
- bindProfileView();
- }
+ bindProfileView();
}
@Override
@@ -1737,9 +1736,7 @@
@Override
protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
processSortedList(sortedComponents);
- if (mProfileView != null) {
- bindProfileView();
- }
+ bindProfileView();
notifyDataSetChanged();
}
};
@@ -2148,7 +2145,7 @@
@Override
protected void onPostExecute(Drawable d) {
- if (mProfileView != null && mAdapter.getOtherProfile() == mDisplayResolveInfo) {
+ if (mAdapter.getOtherProfile() == mDisplayResolveInfo) {
bindProfileView();
} else {
mDisplayResolveInfo.setDisplayIcon(d);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 5fee2c9..8f8e4d8 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -48,8 +48,7 @@
void setIconVisibility(String slot, boolean visible);
@UnsupportedAppUsage
void removeIcon(String slot);
- // TODO(b/117478341): support back button change when IME is showing on a external display.
- void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
+ void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher);
void expandSettingsPanel(String subPanel);
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index e22f581..076e99d 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -22,6 +22,9 @@
#include <jni.h>
#include "core_jni_helpers.h"
+#include <android-base/logging.h>
+#include <bionic_malloc.h>
+
#include <utils/Log.h>
#include <utils/String8.h>
@@ -30,11 +33,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
- size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
#define DDMS_HEADER_SIGNATURE 0x812345dd
#define DDMS_VERSION 2
@@ -78,9 +76,16 @@
ReadFile("/proc/self/maps", maps);
header.mapSize = maps.size();
- uint8_t* allocBytes;
- get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
- &header.totalMemory, &header.backtraceSize);
+ android_mallopt_leak_info_t leak_info;
+ if (!android_mallopt(M_GET_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info))) {
+ PLOG(ERROR) << "*** Failed to get malloc leak info";
+ return nullptr;
+ }
+
+ header.allocSize = leak_info.overall_size;
+ header.allocInfoSize = leak_info.info_size;
+ header.totalMemory = leak_info.total_memory;
+ header.backtraceSize = leak_info.backtrace_size;
ALOGD("*** mapSize: %zu allocSize: %zu allocInfoSize: %zu totalMemory: %zu",
header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
@@ -98,10 +103,10 @@
env->SetByteArrayRegion(array, sizeof(header),
maps.size(), reinterpret_cast<const jbyte*>(maps.string()));
env->SetByteArrayRegion(array, sizeof(header) + maps.size(),
- header.allocSize, reinterpret_cast<jbyte*>(allocBytes));
+ header.allocSize, reinterpret_cast<jbyte*>(leak_info.buffer));
}
- free_malloc_leak_info(allocBytes);
+ android_mallopt(M_FREE_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info));
return array;
}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 195fe58..69a7c4d 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -33,6 +33,8 @@
#include <string>
#include <vector>
+#include <android-base/logging.h>
+#include <bionic_malloc.h>
#include <debuggerd/client.h>
#include <log/log.h>
#include <utils/misc.h>
@@ -663,9 +665,6 @@
return true;
}
-/* pulled out of bionic */
-extern "C" void write_malloc_leak_info(FILE* fp);
-
/*
* Dump the native heap, writing human-readable output to the specified
* file descriptor.
@@ -681,8 +680,11 @@
ALOGD("Native heap dump starting...\n");
// Formatting of the native heap dump is handled by malloc debug itself.
// See https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md#backtrace-heap-dump-format
- write_malloc_leak_info(fp.get());
- ALOGD("Native heap dump complete.\n");
+ if (android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp.get(), sizeof(FILE*))) {
+ ALOGD("Native heap dump complete.\n");
+ } else {
+ PLOG(ERROR) << "Failed to write native heap dump to file";
+ }
}
/*
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 68c62a6..138e24e3 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -41,21 +41,6 @@
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true" />
- <TextView android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginEnd="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:visibility="gone"
- style="?attr/borderlessButtonStyle"
- android:textAppearance="?attr/textAppearanceButton"
- android:textColor="?attr/colorAccent"
- android:gravity="center_vertical"
- android:layout_below="@id/drag"
- android:layout_alignParentRight="true"
- android:singleLine="true"/>
-
<TextView android:id="@+id/title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
@@ -67,7 +52,7 @@
android:paddingBottom="@dimen/chooser_view_spacing"
android:paddingLeft="24dp"
android:paddingRight="24dp"
- android:layout_below="@id/profile_button"
+ android:layout_below="@id/drag"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
diff --git a/core/res/res/layout/chooser_profile_row.xml b/core/res/res/layout/chooser_profile_row.xml
new file mode 100644
index 0000000..1a24a07
--- /dev/null
+++ b/core/res/res/layout/chooser_profile_row.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, 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.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center">
+ <TextView
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ style="?attr/borderlessButtonStyle"
+ android:textAppearance="?attr/textAppearanceButton"
+ android:textColor="?attr/colorAccent"
+ android:singleLine="true"/>
+</LinearLayout>
+
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a6a0c6e..2f34c94 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2794,6 +2794,7 @@
<java-symbol type="drawable" name="scroll_indicator_material" />
<java-symbol type="layout" name="chooser_row" />
+ <java-symbol type="layout" name="chooser_profile_row" />
<java-symbol type="color" name="chooser_row_divider" />
<java-symbol type="layout" name="chooser_row_direct_share" />
<java-symbol type="bool" name="config_supportDoubleTapWake" />
diff --git a/core/tests/coretests/src/android/util/HashedStringCacheTest.java b/core/tests/coretests/src/android/util/HashedStringCacheTest.java
index 333db24..2292473 100644
--- a/core/tests/coretests/src/android/util/HashedStringCacheTest.java
+++ b/core/tests/coretests/src/android/util/HashedStringCacheTest.java
@@ -80,6 +80,17 @@
assertThat(cachedResult2.hashedString, is(cachedResult.hashedString));
}
+
+ @Test
+ public void testThatMultipleInputResultInDifferentHash() {
+ HashedStringCache cache = HashedStringCache.getInstance();
+ HashedStringCache.HashResult cachedResult =
+ cache.hashString(mContext, TAG, TEST_STRING, 7);
+ HashedStringCache.HashResult cachedResult2 =
+ cache.hashString(mContext, TAG, "different_test", 7);
+ assertThat(cachedResult2.hashedString, is(not(cachedResult.hashedString)));
+ }
+
@Test
public void testThatZeroDaysResultsInNewHash() {
HashedStringCache cache = HashedStringCache.getInstance();
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index ac039dd..767ec0e 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -18,6 +18,7 @@
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
@@ -62,9 +63,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.function.Function;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -74,7 +72,10 @@
import org.mockito.Mockito;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
+import java.util.function.Function;
/**
* Chooser activity instrumentation tests
@@ -245,7 +246,7 @@
waitForIdle();
assertThat(activity.getAdapter().getCount(), is(2));
- onView(withId(R.id.profile_button)).check(matches(not(isDisplayed())));
+ onView(withId(R.id.profile_button)).check(doesNotExist());
ResolveInfo[] chosen = new ResolveInfo[1];
sOverrides.onSafelyStartCallback = targetInfo -> {
@@ -770,8 +771,6 @@
}
// This test is too long and too slow and should not be taken as an example for future tests.
- // This is necessary because it tests that multiple calls result in the same result but
- // normally a test this long should be broken into smaller tests testing individual components.
@Test
public void testDirectTargetSelectionLogging() throws InterruptedException {
Intent sendIntent = createSendTextIntent();
@@ -785,7 +784,7 @@
MetricsLogger mockLogger = sOverrides.metricsLogger;
ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
// Create direct share target
- List<ChooserTarget> serviceTargets = createDirectShareTargets(1);
+ List<ChooserTarget> serviceTargets = createDirectShareTargets(1, "");
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
// Start activity
@@ -808,7 +807,7 @@
// TODO: restructure the tests b/129870719
Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
- assertThat("Chooser should have 3 targets (2apps, 1 direct)",
+ assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
activity.getAdapter().getCount(), is(3));
assertThat("Chooser should have exactly one selectable direct target",
activity.getAdapter().getSelectableServiceTargetCount(), is(1));
@@ -832,20 +831,36 @@
.getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
assertThat("Hash is not predictable but must be obfuscated",
hashedName, is(not(name)));
+ assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
+ .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
+ }
- // Running the same again to check if the hashed name is the same as before.
+ // This test is too long and too slow and should not be taken as an example for future tests.
+ @Test
+ public void testDirectTargetLoggingWithRankedAppTarget() throws InterruptedException {
+ Intent sendIntent = createSendTextIntent();
+ // We need app targets for direct targets to get displayed
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
- Intent sendIntent2 = createSendTextIntent();
+ // Set up resources
+ MetricsLogger mockLogger = sOverrides.metricsLogger;
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ // Create direct share target
+ List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
+ resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
// Start activity
- final ChooserWrapperActivity activity2 = mActivityRule
- .launchActivity(Intent.createChooser(sendIntent2, null));
- waitForIdle();
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
// Insert the direct share target
InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> activity2.getAdapter().addServiceResults(
- activity2.createTestDisplayResolveInfo(sendIntent,
+ () -> activity.getAdapter().addServiceResults(
+ activity.createTestDisplayResolveInfo(sendIntent,
ri,
"testLabel",
"testInfo",
@@ -858,29 +873,89 @@
// TODO: restructure the tests b/129870719
Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
- assertThat("Chooser should have 3 targets (2apps, 1 direct)",
- activity2.getAdapter().getCount(), is(3));
+ assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
+ activity.getAdapter().getCount(), is(3));
assertThat("Chooser should have exactly one selectable direct target",
- activity2.getAdapter().getSelectableServiceTargetCount(), is(1));
+ activity.getAdapter().getSelectableServiceTargetCount(), is(1));
assertThat("The resolver info must match the resolver info used to create the target",
- activity2.getAdapter().getItem(0).getResolveInfo(), is(ri));
+ activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
// Click on the direct target
+ String name = serviceTargets.get(0).getTitle().toString();
onView(withText(name))
.perform(click());
waitForIdle();
- // Currently we're seeing 6 invocations (3 from above, doubled up)
- // 4. ChooserActivity.onCreate()
- // 5. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
- // 6. ChooserActivity.startSelected -- which is the one we're after
- verify(mockLogger, Mockito.times(6)).write(logMakerCaptor.capture());
- assertThat(logMakerCaptor.getAllValues().get(5).getCategory(),
+ // Currently we're seeing 3 invocations
+ // 1. ChooserActivity.onCreate()
+ // 2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
+ // 3. ChooserActivity.startSelected -- which is the one we're after
+ verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
+ assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
- String hashedName2 = (String) logMakerCaptor
- .getAllValues().get(5).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
- assertThat("Hashing the same name should result in the same hashed value",
- hashedName2, is(hashedName));
+ assertThat("The packages should match for app target and direct target", logMakerCaptor
+ .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(0));
+ }
+
+ // This test is too long and too slow and should not be taken as an example for future tests.
+ @Test
+ public void testDirectTargetLoggingWithAppTargetNotRanked() throws InterruptedException {
+ Intent sendIntent = createSendTextIntent();
+ // We need app targets for direct targets to get displayed
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ // Set up resources
+ MetricsLogger mockLogger = sOverrides.metricsLogger;
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ // Create direct share target
+ List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
+ resolvedComponentInfos.get(14).getResolveInfoAt(0).activityInfo.packageName);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0);
+
+ // Start activity
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ // Insert the direct share target
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ () -> activity.getAdapter().addServiceResults(
+ activity.createTestDisplayResolveInfo(sendIntent,
+ ri,
+ "testLabel",
+ "testInfo",
+ sendIntent),
+ serviceTargets,
+ false)
+ );
+ // Thread.sleep shouldn't be a thing in an integration test but it's
+ // necessary here because of the way the code is structured
+ // TODO: restructure the tests b/129870719
+ Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+
+ assertThat("Chooser should have 20 targets (4 apps, 1 direct, 15 A-Z)",
+ activity.getAdapter().getCount(), is(20));
+ assertThat("Chooser should have exactly one selectable direct target",
+ activity.getAdapter().getSelectableServiceTargetCount(), is(1));
+ assertThat("The resolver info must match the resolver info used to create the target",
+ activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
+
+ // Click on the direct target
+ String name = serviceTargets.get(0).getTitle().toString();
+ onView(withText(name))
+ .perform(click());
+ waitForIdle();
+
+ // Currently we're seeing 3 invocations
+ // 1. ChooserActivity.onCreate()
+ // 2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
+ // 3. ChooserActivity.startSelected -- which is the one we're after
+ verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
+ assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
+ assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
+ .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
}
private Intent createSendTextIntent() {
@@ -946,12 +1021,17 @@
return infoList;
}
- private List<ChooserTarget> createDirectShareTargets(int numberOfResults) {
+ private List<ChooserTarget> createDirectShareTargets(int numberOfResults, String packageName) {
Icon icon = Icon.createWithBitmap(createBitmap());
String testTitle = "testTitle";
List<ChooserTarget> targets = new ArrayList<>();
for (int i = 0; i < numberOfResults; i++) {
- ComponentName componentName = ResolverDataProvider.createComponentName(i);
+ ComponentName componentName;
+ if (packageName.isEmpty()) {
+ componentName = ResolverDataProvider.createComponentName(i);
+ } else {
+ componentName = new ComponentName(packageName, packageName + ".class");
+ }
ChooserTarget tempTarget = new ChooserTarget(
testTitle + i,
icon,
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index eca3926..2e9b03c 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -383,7 +383,7 @@
}
if (TextUtils.isEmpty(displayText) && !airplaneMode) {
- displayText = TextUtils.join(mSeparator, carrierNames);
+ displayText = joinNotEmpty(mSeparator, carrierNames);
}
final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
displayText,
@@ -546,6 +546,25 @@
}
}
+ /**
+ * Joins the strings in a sequence using a separator. Empty strings are discarded with no extra
+ * separator added so there are no extra separators that are not needed.
+ */
+ private static CharSequence joinNotEmpty(CharSequence separator, CharSequence[] sequences) {
+ int length = sequences.length;
+ if (length == 0) return "";
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ if (!TextUtils.isEmpty(sequences[i])) {
+ if (!TextUtils.isEmpty(sb)) {
+ sb.append(separator);
+ }
+ sb.append(sequences[i]);
+ }
+ }
+ return sb.toString();
+ }
+
private static List<CharSequence> append(List<CharSequence> list, CharSequence string) {
if (!TextUtils.isEmpty(string)) {
list.add(string);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 94bb1f3..1bd8e0d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -204,6 +204,11 @@
return false;
}
+ /** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
+ public void onInvocationProgress(int type, float progress) {
+ // intentional no-op, vendor's AssistManager implementation should override if needed.
+ }
+
public void hideAssist() {
mAssistUtils.hideCurrentSession();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 2f99cf3..d584959 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -18,7 +18,10 @@
import static android.app.StatusBarManager.DISABLE2_NONE;
import static android.app.StatusBarManager.DISABLE_NONE;
+import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
+import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
@@ -40,6 +43,7 @@
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
+import android.view.inputmethod.InputMethodSystemProperty;
import androidx.annotation.VisibleForTesting;
@@ -127,6 +131,11 @@
private Handler mHandler = new H(Looper.getMainLooper());
/** A map of display id - disable flag pair */
private SparseArray<Pair<Integer, Integer>> mDisplayDisabled = new SparseArray<>();
+ /**
+ * The last ID of the display where IME window for which we received setImeWindowStatus
+ * event.
+ */
+ private int mLastUpdatedImeDisplayId = INVALID_DISPLAY;
/**
* These methods are called back on the main thread.
@@ -785,6 +794,32 @@
}
}
+ private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition,
+ boolean showImeSwitcher) {
+ if (displayId == INVALID_DISPLAY) return;
+
+ if (!InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED
+ && mLastUpdatedImeDisplayId != displayId
+ && mLastUpdatedImeDisplayId != INVALID_DISPLAY) {
+ // Set previous NavBar's IME window status as invisible when IME
+ // window switched to another display for single-session IME case.
+ sendImeInvisibleStatusForPrevNavBar();
+ }
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setImeWindowStatus(displayId, token, vis, backDisposition,
+ showImeSwitcher);
+ }
+ mLastUpdatedImeDisplayId = displayId;
+ }
+
+ private void sendImeInvisibleStatusForPrevNavBar() {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setImeWindowStatus(mLastUpdatedImeDisplayId,
+ null /* token */, IME_INVISIBLE, BACK_DISPOSITION_DEFAULT,
+ false /* showImeSwitcher */);
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -852,10 +887,9 @@
break;
case MSG_SHOW_IME_BUTTON:
args = (SomeArgs) msg.obj;
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).setImeWindowStatus(args.argi1, (IBinder) args.arg1,
- args.argi2, args.argi3, args.argi4 != 0 /* showImeSwitcher */);
- }
+ handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
+ args.argi2 /* vis */, args.argi3 /* backDisposition */,
+ args.argi4 != 0 /* showImeSwitcher */);
break;
case MSG_SHOW_RECENT_APPS:
for (int i = 0; i < mCallbacks.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 4d2b56c..6c1a4fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -1063,4 +1063,9 @@
context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
return navigationBarView;
}
+
+ @VisibleForTesting
+ int getNavigationIconHints() {
+ return mNavigationIconHints;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index a381bbc..3f33ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3926,6 +3926,10 @@
mScrimController.setWakeLockScreenSensorActive(true);
}
+ if (reason == DozeLog.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
+ mStatusBarWindow.suppressWakeUpGesture(true);
+ }
+
boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_NOTIFICATION;
// Set the state to pulsing, so ScrimController will know what to do once we ask it to
// execute the transition. The pulse callback will then be invoked when the scrims
@@ -3945,6 +3949,9 @@
callback.onPulseFinished();
updateNotificationPanelTouchState();
mScrimController.setWakeLockScreenSensorActive(false);
+ if (mStatusBarWindow != null) {
+ mStatusBarWindow.suppressWakeUpGesture(false);
+ }
setPulsing(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 28db28c..44996ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -107,12 +107,13 @@
private boolean mTouchActive;
private boolean mExpandAnimationRunning;
private boolean mExpandAnimationPending;
+ private boolean mSuppressingWakeUpGesture;
private final GestureDetector.SimpleOnGestureListener mGestureListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
- if (mSingleTapEnabled) {
+ if (mSingleTapEnabled && !mSuppressingWakeUpGesture) {
mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this,
"SINGLE_TAP");
return true;
@@ -327,6 +328,10 @@
mTouchActive = touchActive;
}
+ void suppressWakeUpGesture(boolean suppress) {
+ mSuppressingWakeUpGesture = suppress;
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index df534d7..9f91a17 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -104,7 +104,8 @@
mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
new CharSequence[]{}, false, new int[]{});
- when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ when(mTelephonyManager.getPhoneCount()).thenReturn(3);
+
mCarrierTextController = new TestCarrierTextController(mContext, SEPARATOR, true, true,
mKeyguardUpdateMonitor);
// This should not start listening on any of the real dependencies
@@ -130,6 +131,12 @@
reset(mCarrierTextCallback);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
new ArrayList<>());
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
+ new ArrayList<>());
+
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
IccCardConstants.State.CARD_IO_ERROR);
// This should not produce an out of bounds error, even though there are no subscriptions
@@ -173,7 +180,11 @@
list.add(TEST_SUBSCRIPTION);
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -197,7 +208,11 @@
list.add(TEST_SUBSCRIPTION_ROAMING);
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -219,6 +234,12 @@
reset(mCarrierTextCallback);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
new ArrayList<>());
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
+ new ArrayList<>());
+
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -233,6 +254,121 @@
}
+ @Test
+ public void testCarrierText_twoValidSubscriptions() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCarrierText_oneDisabledSub() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY)
+ .thenReturn(IccCardConstants.State.NOT_READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCarrierText_firstDisabledSub() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.NOT_READY)
+ .thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCarrierText_threeSubsMiddleDisabled() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY)
+ .thenReturn(IccCardConstants.State.NOT_READY)
+ .thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
public static class TestCarrierTextController extends CarrierTextController {
private KeyguardUpdateMonitor mKUM;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 6a0d61d..3ae57e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -14,18 +14,38 @@
package com.android.systemui.statusbar.phone;
+import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
+import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
+import static android.inputmethodservice.InputMethodService.IME_VISIBLE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.annotation.LayoutRes;
+import android.annotation.Nullable;
import android.app.Fragment;
+import android.app.FragmentController;
+import android.app.FragmentHostCallback;
import android.content.Context;
+import android.hardware.display.DisplayManagerGlobal;
import android.os.Bundle;
+import android.os.Handler;
import android.os.Looper;
import android.testing.AndroidTestingRunner;
import android.testing.LeakCheck.Tracker;
+import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
@@ -34,6 +54,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.SysuiTestableContext;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
@@ -50,9 +71,16 @@
@RunWithLooper()
@SmallTest
public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
+ private static final int EXTERNAL_DISPLAY_ID = 2;
+ private static final int NAV_BAR_VIEW_ID = 43;
+ private Fragment mFragmentExternalDisplay;
+ private FragmentController mControllerExternalDisplay;
+
+ private SysuiTestableContext mSysuiTestableContextExternal;
private OverviewProxyService mOverviewProxyService =
mDependency.injectMockDependency(OverviewProxyService.class);
+ private CommandQueue mCommandQueue;
private AccessibilityManagerWrapper mAccessibilityWrapper =
new AccessibilityManagerWrapper(mContext) {
Tracker mTracker = mLeakCheck.getTracker("accessibility_manager");
@@ -73,15 +101,51 @@
}
protected void createRootView() {
- mView = new NavigationBarFrame(mContext);
+ mView = new NavigationBarFrame(mSysuiContext);
+ mView.setId(NAV_BAR_VIEW_ID);
}
@Before
- public void setup() {
- mSysuiContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+ public void setupFragment() throws Exception {
+ setupSysuiDependency();
+ createRootView();
+ TestableLooper.get(this).runWithLooper(() -> {
+ mHandler = new Handler();
+
+ mFragment = instantiate(mSysuiContext, NavigationBarFragment.class.getName(), null);
+ mFragments = FragmentController.createController(
+ new HostCallbacksForExternalDisplay(mSysuiContext));
+ mFragments.attachHost(null);
+ mFragments.getFragmentManager().beginTransaction()
+ .replace(NAV_BAR_VIEW_ID, mFragment)
+ .commit();
+ mControllerExternalDisplay = FragmentController.createController(
+ new HostCallbacksForExternalDisplay(mSysuiTestableContextExternal));
+ mControllerExternalDisplay.attachHost(null);
+ mFragmentExternalDisplay = instantiate(mSysuiTestableContextExternal,
+ NavigationBarFragment.class.getName(), null);
+ mControllerExternalDisplay.getFragmentManager().beginTransaction()
+ .replace(NAV_BAR_VIEW_ID, mFragmentExternalDisplay)
+ .commit();
+ });
+ }
+
+ private void setupSysuiDependency() {
+ mCommandQueue = new CommandQueue(mContext);
+ mSysuiContext.putComponent(CommandQueue.class, mCommandQueue);
mSysuiContext.putComponent(StatusBar.class, mock(StatusBar.class));
mSysuiContext.putComponent(Recents.class, mock(Recents.class));
mSysuiContext.putComponent(Divider.class, mock(Divider.class));
+
+ Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY_ID,
+ new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
+ mSysuiTestableContextExternal = (SysuiTestableContext) mSysuiContext.createDisplayContext(
+ display);
+ mSysuiTestableContextExternal.putComponent(CommandQueue.class, mCommandQueue);
+ mSysuiTestableContextExternal.putComponent(StatusBar.class, mock(StatusBar.class));
+ mSysuiTestableContextExternal.putComponent(Recents.class, mock(Recents.class));
+ mSysuiTestableContextExternal.putComponent(Divider.class, mock(Divider.class));
+
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
WindowManager windowManager = mock(WindowManager.class);
Display defaultDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
@@ -102,15 +166,111 @@
navigationBarFragment.onHomeLongClick(navigationBarFragment.getView());
}
+ @Test
+ public void testSetImeWindowStatusWhenImeSwitchOnDisplay() {
+ // Create default & external NavBar fragment.
+ NavigationBarFragment defaultNavBar = (NavigationBarFragment) mFragment;
+ NavigationBarFragment externalNavBar = (NavigationBarFragment) mFragmentExternalDisplay;
+ mFragments.dispatchCreate();
+ processAllMessages();
+ mFragments.dispatchResume();
+ processAllMessages();
+ mControllerExternalDisplay.dispatchCreate();
+ processAllMessages();
+ mControllerExternalDisplay.dispatchResume();
+ processAllMessages();
+
+ // Set IME window status for default NavBar.
+ mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+ BACK_DISPOSITION_DEFAULT, true);
+ Handler.getMain().runWithScissors(() -> { }, 500);
+
+ // Verify IME window state will be updated in default NavBar & external NavBar state reset.
+ assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN,
+ defaultNavBar.getNavigationIconHints());
+ assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+ assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+
+ // Set IME window status for external NavBar.
+ mCommandQueue.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null,
+ IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true);
+ Handler.getMain().runWithScissors(() -> { }, 500);
+
+ // Verify IME window state will be updated in external NavBar & default NavBar state reset.
+ assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN,
+ externalNavBar.getNavigationIconHints());
+ assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+ assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+ }
+
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
DeviceProvisionedController deviceProvisionedController =
mock(DeviceProvisionedController.class);
assertNotNull(mAccessibilityWrapper);
- return new NavigationBarFragment(mAccessibilityWrapper,
+ return new NavigationBarFragment(
+ context.getDisplayId() == DEFAULT_DISPLAY ? mAccessibilityWrapper
+ : mock(AccessibilityManagerWrapper.class),
deviceProvisionedController,
new MetricsLogger(),
- new AssistManager(deviceProvisionedController, mContext),
+ mock(AssistManager.class),
mOverviewProxyService);
}
+
+ private class HostCallbacksForExternalDisplay extends
+ FragmentHostCallback<NavigationBarFragmentTest> {
+ private Context mDisplayContext;
+
+ HostCallbacksForExternalDisplay(Context context) {
+ super(context, mHandler, 0);
+ mDisplayContext = context;
+ }
+
+ @Override
+ public NavigationBarFragmentTest onGetHost() {
+ return NavigationBarFragmentTest.this;
+ }
+
+ @Override
+ public Fragment instantiate(Context context, String className, Bundle arguments) {
+ return NavigationBarFragmentTest.this.instantiate(context, className, arguments);
+ }
+
+ @Override
+ public View onFindViewById(int id) {
+ return mView.findViewById(id);
+ }
+
+ @Override
+ public LayoutInflater onGetLayoutInflater() {
+ return new LayoutInflaterWrapper(mDisplayContext);
+ }
+ }
+
+ private static class LayoutInflaterWrapper extends LayoutInflater {
+ protected LayoutInflaterWrapper(Context context) {
+ super(context);
+ }
+
+ @Override
+ public LayoutInflater cloneInContext(Context newContext) {
+ return null;
+ }
+
+ @Override
+ public View inflate(@LayoutRes int resource, @Nullable ViewGroup root,
+ boolean attachToRoot) {
+ NavigationBarView view = mock(NavigationBarView.class);
+ when(view.getDisplay()).thenReturn(mContext.getDisplay());
+ when(view.getBackButton()).thenReturn(mock(ButtonDispatcher.class));
+ when(view.getHomeButton()).thenReturn(mock(ButtonDispatcher.class));
+ when(view.getRecentsButton()).thenReturn(mock(ButtonDispatcher.class));
+ when(view.getAccessibilityButton()).thenReturn(mock(ButtonDispatcher.class));
+ when(view.getRotateSuggestionButton()).thenReturn(mock(RotationContextButton.class));
+ when(view.getBarTransitions()).thenReturn(mock(BarTransitions.class));
+ when(view.getLightTransitionsController()).thenReturn(
+ mock(LightBarTransitionsController.class));
+ return view;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 43bc21b..fb16465 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -681,6 +681,25 @@
}
@Test
+ public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() {
+ // Keep track of callback to be able to stop the pulse
+ final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1];
+ doAnswer(invocation -> {
+ pulseCallback[0] = invocation.getArgument(0);
+ return null;
+ }).when(mDozeScrimController).pulse(any(), anyInt());
+
+ // Starting a pulse while docking should suppress wakeup gesture
+ mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class),
+ DozeLog.PULSE_REASON_DOCKING);
+ verify(mStatusBarWindowView).suppressWakeUpGesture(eq(true));
+
+ // Ending a pulse should restore wakeup gesture
+ pulseCallback[0].onPulseFinished();
+ verify(mStatusBarWindowView).suppressWakeUpGesture(eq(false));
+ }
+
+ @Test
public void testSetState_changesIsFullScreenUserSwitcherState() {
mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
assertFalse(mStatusBar.isFullScreenUserSwitcherState());
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 55a0621..ecea251c 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -16,7 +16,9 @@
package com.android.server.contentsuggestions;
+import static android.Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE;
import static android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -92,16 +94,11 @@
return MAX_TEMP_SERVICE_DURATION_MS;
}
- private boolean isCallerRecents(int userId) {
- if (mServiceNameResolver.isTemporary(userId)) {
- // If a temporary service is set then skip the recents check
- return true;
- }
- return mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid());
- }
-
- private void enforceCallerIsRecents(int userId, String func) {
- if (isCallerRecents(userId)) {
+ private void enforceCaller(int userId, String func) {
+ Context ctx = getContext();
+ if (ctx.checkCallingPermission(BIND_CONTENT_SUGGESTIONS_SERVICE) == PERMISSION_GRANTED
+ || mServiceNameResolver.isTemporary(userId)
+ || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
return;
}
@@ -122,7 +119,7 @@
if (imageContextRequestExtras == null) {
throw new IllegalArgumentException("Expected non-null imageContextRequestExtras");
}
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "provideContextImage");
+ enforceCaller(UserHandle.getCallingUserId(), "provideContextImage");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -141,7 +138,7 @@
int userId,
@NonNull SelectionsRequest selectionsRequest,
@NonNull ISelectionsCallback selectionsCallback) {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "suggestContentSelections");
+ enforceCaller(UserHandle.getCallingUserId(), "suggestContentSelections");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -160,7 +157,7 @@
int userId,
@NonNull ClassificationsRequest classificationsRequest,
@NonNull IClassificationsCallback callback) {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "classifyContentSelections");
+ enforceCaller(UserHandle.getCallingUserId(), "classifyContentSelections");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -177,7 +174,7 @@
@Override
public void notifyInteraction(
int userId, @NonNull String requestId, @NonNull Bundle bundle) {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "notifyInteraction");
+ enforceCaller(UserHandle.getCallingUserId(), "notifyInteraction");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -194,7 +191,7 @@
@Override
public void isEnabled(int userId, @NonNull IResultReceiver receiver)
throws RemoteException {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "isEnabled");
+ enforceCaller(UserHandle.getCallingUserId(), "isEnabled");
boolean isDisabled;
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index e65a4e5..7c2ea3f 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -139,3 +139,8 @@
# The task is being compacted
30063 am_compact (Pid|1|5),(Process Name|3),(Action|3),(BeforeRssTotal|2|2),(BeforeRssFile|2|2),(BeforeRssAnon|2|2),(BeforeRssSwap|2|2),(DeltaRssTotal|2|2),(DeltaRssFile|2|2),(DeltaRssAnon|2|2),(DeltaRssSwap|2|2),(Time|2|3),(LastAction|1|2),(LastActionTimestamp|2|3),(setAdj|1|2),(procState|1|2),(BeforeZRAMFree|2|2),(DeltaZRAMFree|2|2)
+
+# The activity's onTopResumedActivityChanged(true) has been called.
+30064 am_on_top_resumed_gained_called (User|1|5),(Component Name|3),(Reason|3)
+# The activity's onTopResumedActivityChanged(false) has been called.
+30065 am_on_top_resumed_lost_called (User|1|5),(Component Name|3),(Reason|3)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d30a9d2..2d00f29 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -508,13 +508,14 @@
// Used to play ringtones outside system_server
private volatile IRingtonePlayer mRingtonePlayer;
- // Devices for which the volume is fixed and VolumePanel slider should be disabled
+ // Devices for which the volume is fixed (volume is either max or muted)
int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_HDMI_ARC |
AudioSystem.DEVICE_OUT_SPDIF |
AudioSystem.DEVICE_OUT_AUX_LINE;
+ // Devices for which the volume is always max, no volume panel
int mFullVolumeDevices = 0;
private final boolean mMonitorRotation;
@@ -859,6 +860,11 @@
mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
}
mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
+ if (mHdmiPlaybackClient != null) {
+ // not a television: HDMI output will be always at max
+ mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+ mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ }
mHdmiCecSink = false;
mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
}
@@ -1065,7 +1071,6 @@
}
if (isPlatformTelevision()) {
- mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
checkAllFixedVolumeDevices();
synchronized (mHdmiClientLock) {
if (mHdmiManager != null && mHdmiPlaybackClient != null) {
@@ -1656,7 +1661,7 @@
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
- ((device & mFixedVolumeDevices) != 0)) {
+ ((device & mFixedVolumeDevices) != 0)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
// Always toggle between max safe volume and 0 for fixed volume devices where safe
@@ -1733,8 +1738,9 @@
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
mVolumeController.postDisplaySafeVolumeWarning(flags);
- } else if (streamState.adjustIndex(direction * step, device, caller)
- || streamState.mIsMuted) {
+ } else if (((device & mFullVolumeDevices) == 0)
+ && (streamState.adjustIndex(direction * step, device, caller)
+ || streamState.mIsMuted)) {
// Post message to set system volume (it in turn will post a
// message to persist).
if (streamState.mIsMuted) {
@@ -1785,9 +1791,10 @@
synchronized (mHdmiClientLock) {
if (mHdmiManager != null) {
// mHdmiCecSink true => mHdmiPlaybackClient != null
- if (mHdmiCecSink &&
- streamTypeAlias == AudioSystem.STREAM_MUSIC &&
- oldIndex != newIndex) {
+ if (mHdmiCecSink
+ && streamTypeAlias == AudioSystem.STREAM_MUSIC
+ // vol change on a full volume device
+ && ((device & mFullVolumeDevices) != 0)) {
int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
KeyEvent.KEYCODE_VOLUME_UP;
final long ident = Binder.clearCallingIdentity();
@@ -1814,7 +1821,7 @@
}
}
int index = mStreamStates[streamType].getIndex(device);
- sendVolumeUpdate(streamType, oldIndex, index, flags);
+ sendVolumeUpdate(streamType, oldIndex, index, flags, device);
}
// Called after a delay when volume down is pressed while muted
@@ -1824,7 +1831,7 @@
final int device = getDeviceForStream(stream);
final int index = mStreamStates[stream].getIndex(device);
- sendVolumeUpdate(stream, index, index, flags);
+ sendVolumeUpdate(stream, index, index, flags, device);
}
private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
@@ -1835,7 +1842,9 @@
|| mHdmiTvClient == null
|| oldVolume == newVolume
|| (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
- || !mHdmiSystemAudioSupported) return;
+ || !mHdmiSystemAudioSupported) {
+ return;
+ }
final long token = Binder.clearCallingIdentity();
try {
mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
@@ -2149,7 +2158,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- sendVolumeUpdate(streamType, oldIndex, index, flags);
+ sendVolumeUpdate(streamType, oldIndex, index, flags, device);
}
@@ -2303,18 +2312,22 @@
}
// UI update and Broadcast Intent
- protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
+ protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags, int device)
+ {
streamType = mStreamVolumeAlias[streamType];
if (streamType == AudioSystem.STREAM_MUSIC) {
- flags = updateFlagsForSystemAudio(flags);
+ flags = updateFlagsForTvPlatform(flags);
+ if ((device & mFullVolumeDevices) != 0) {
+ flags &= ~AudioManager.FLAG_SHOW_UI;
+ }
}
mVolumeController.postVolumeChanged(streamType, flags);
}
// If Hdmi-CEC system audio mode is on, we show volume bar only when TV
// receives volume notification from Audio Receiver.
- private int updateFlagsForSystemAudio(int flags) {
+ private int updateFlagsForTvPlatform(int flags) {
synchronized (mHdmiClientLock) {
if (mHdmiTvClient != null) {
if (mHdmiSystemAudioSupported &&
@@ -2328,7 +2341,7 @@
// UI update and Broadcast Intent
private void sendMasterMuteUpdate(boolean muted, int flags) {
- mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
+ mVolumeController.postMasterMuteChanged(updateFlagsForTvPlatform(flags));
broadcastMasterMuteStatus(muted);
}
@@ -2355,6 +2368,9 @@
int device,
boolean force,
String caller) {
+ if ((device & mFullVolumeDevices) != 0) {
+ return;
+ }
VolumeStreamState streamState = mStreamStates[streamType];
if (streamState.setIndex(index, device, caller) || force) {
@@ -5810,9 +5826,14 @@
}
//==========================================================================================
- // Hdmi Cec system audio mode.
- // If Hdmi Cec's system audio mode is on, audio service should send the volume change
- // to HdmiControlService so that the audio receiver can handle it.
+ // Hdmi CEC:
+ // - System audio mode:
+ // If Hdmi Cec's system audio mode is on, audio service should send the volume change
+ // to HdmiControlService so that the audio receiver can handle it.
+ // - CEC sink:
+ // OUT_HDMI becomes a "full volume device", i.e. output is always at maximum level
+ // and volume changes won't be taken into account on this device. Volume adjustments
+ // are transformed into key events for the HDMI playback client.
//==========================================================================================
private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
@@ -5821,8 +5842,18 @@
if (mHdmiManager != null) {
mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
// Television devices without CEC service apply software volume on HDMI output
- if (isPlatformTelevision() && !mHdmiCecSink) {
- mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+ if (mHdmiCecSink) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "CEC sink: setting HDMI as full vol device");
+ }
+ mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ } else {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
+ }
+ // Android TV devices without CEC service apply software volume on
+ // HDMI output
+ mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
}
checkAllFixedVolumeDevices();
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3c97c39..c2aade3 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -575,6 +575,12 @@
*/
int mCurTokenDisplayId = INVALID_DISPLAY;
+ /**
+ * The display ID of the input method indicates the fallback display which returned by
+ * {@link #computeImeDisplayIdForTarget}.
+ */
+ private static final int FALLBACK_DISPLAY_ID = DEFAULT_DISPLAY;
+
final ImeDisplayValidator mImeDisplayValidator;
/**
@@ -625,7 +631,8 @@
* currently invisible.
* </dd>
* </dl>
- * <em>Do not update this value outside of setImeWindowStatus.</em>
+ * <em>Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and
+ * {@link #unbindCurrentMethodLocked()}.</em>
*/
int mImeWindowVis;
@@ -2124,12 +2131,10 @@
*/
static int computeImeDisplayIdForTarget(int displayId, @NonNull ImeDisplayValidator checker) {
if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY) {
- // We always assume that the default display id suitable to show the IME window.
- return DEFAULT_DISPLAY;
+ return FALLBACK_DISPLAY_ID;
}
- // Show IME in default display when the display with IME target doesn't support system
- // decorations.
- return checker.displayCanShowIme(displayId) ? displayId : DEFAULT_DISPLAY;
+ // Show IME window on fallback display when the display is not allowed.
+ return checker.displayCanShowIme(displayId) ? displayId : FALLBACK_DISPLAY_ID;
}
@Override
@@ -2198,6 +2203,10 @@
mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
} catch (RemoteException e) {
}
+ // Set IME window status as invisible when unbind current method.
+ mImeWindowVis = 0;
+ mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
+ updateSystemUiLocked(mImeWindowVis, mBackDisposition);
mCurToken = null;
mCurTokenDisplayId = INVALID_DISPLAY;
}
@@ -2399,10 +2408,20 @@
@BinderThread
@SuppressWarnings("deprecation")
private void setImeWindowStatus(@NonNull IBinder token, int vis, int backDisposition) {
+ final int topFocusedDisplayId = mWindowManagerInternal.getTopFocusedDisplayId();
+
synchronized (mMethodMap) {
if (!calledWithValidTokenLocked(token)) {
return;
}
+ // Skip update IME status when current token display is not same as focused display.
+ // Note that we still need to update IME status when focusing external display
+ // that does not support system decoration and fallback to show IME on default
+ // display since it is intentional behavior.
+ if (mCurTokenDisplayId != topFocusedDisplayId
+ && mCurTokenDisplayId != FALLBACK_DISPLAY_ID) {
+ return;
+ }
mImeWindowVis = vis;
mBackDisposition = backDisposition;
updateSystemUiLocked(vis, backDisposition);
@@ -2447,7 +2466,8 @@
if (DEBUG) {
Slog.d(TAG, "IME window vis: " + vis
+ " active: " + (vis & InputMethodService.IME_ACTIVE)
- + " inv: " + (vis & InputMethodService.IME_INVISIBLE));
+ + " inv: " + (vis & InputMethodService.IME_INVISIBLE)
+ + " displayId: " + mCurTokenDisplayId);
}
// TODO: Move this clearing calling identity block to setImeWindowStatus after making sure
@@ -2461,7 +2481,7 @@
// mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked().
final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis);
if (mStatusBar != null) {
- mStatusBar.setImeWindowStatus(mCurToken, vis, backDisposition,
+ mStatusBar.setImeWindowStatus(mCurTokenDisplayId, mCurToken, vis, backDisposition,
needsToShowImeSwitcher);
}
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 8578bb7..a349d87 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -248,7 +248,8 @@
scheduleOpTimeOutLocked();
final Intent intent = new Intent().setComponent(job.getServiceComponent());
boolean binding = mContext.bindServiceAsUser(intent, this,
- Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_NOT_VISIBLE | Context.BIND_ADJUST_BELOW_PERCEPTIBLE,
new UserHandle(job.getUserId()));
if (!binding) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2e8e65b..e5ecd49 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2863,8 +2863,7 @@
// Reset notification preferences
if (!fromApp) {
- mPreferencesHelper.onPackagesChanged(
- true, UserHandle.getCallingUserId(), packages, uids);
+ mPreferencesHelper.clearData(packageName, uid);
}
handleSavePolicyFile();
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 642fa7f..b57063f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -1717,6 +1717,22 @@
}
}
+ public void clearData(String pkg, int uid) {
+ synchronized (mPackagePreferences) {
+ PackagePreferences p = getPackagePreferencesLocked(pkg, uid);
+ p.channels = new ArrayMap<>();
+ p.groups = new ArrayMap<>();
+ p.delegate = null;
+ p.lockedAppFields = DEFAULT_LOCKED_APP_FIELDS;
+ p.allowBubble = DEFAULT_ALLOW_BUBBLE;
+ p.importance = DEFAULT_IMPORTANCE;
+ p.priority = DEFAULT_PRIORITY;
+ p.visibility = DEFAULT_VISIBILITY;
+ p.showBadge = DEFAULT_SHOW_BADGE;
+
+ }
+ }
+
private LogMaker getChannelLog(NotificationChannel channel, String pkg) {
return new LogMaker(
com.android.internal.logging.nano.MetricsProto.MetricsEvent
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 0caeb10..1edb93a 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -2563,9 +2563,8 @@
private static final class ThermalEventListener extends IThermalEventListener.Stub {
@Override
public void notifyThrottling(Temperature temp) {
- StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
- StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__UNKNOWN,
- temp.getValue(), temp.getStatus(), temp.getName());
+ StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(),
+ temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index aaf3df3..9cbf00b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -843,10 +843,9 @@
}
}
- // TODO(b/117478341): support back button change when IME is showing on a external display.
@Override
- public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition,
- final boolean showImeSwitcher) {
+ public void setImeWindowStatus(int displayId, final IBinder token, final int vis,
+ final int backDisposition, final boolean showImeSwitcher) {
enforceStatusBar();
if (SPEW) {
@@ -857,18 +856,13 @@
// In case of IME change, we need to call up setImeWindowStatus() regardless of
// mImeWindowVis because mImeWindowVis may not have been set to false when the
// previous IME was destroyed.
- // TODO(b/117478341): support back button change when IME is showing on a external
- // display.
- getUiState(DEFAULT_DISPLAY)
- .setImeWindowState(vis, backDisposition, showImeSwitcher, token);
+ getUiState(displayId).setImeWindowState(vis, backDisposition, showImeSwitcher, token);
mHandler.post(() -> {
if (mBar == null) return;
try {
- // TODO(b/117478341): support back button change when IME is showing on a
- // external display.
mBar.setImeWindowStatus(
- DEFAULT_DISPLAY, token, vis, backDisposition, showImeSwitcher);
+ displayId, token, vis, backDisposition, showImeSwitcher);
} catch (RemoteException ex) { }
});
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 76b0351..4ed07c3 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -4089,11 +4089,14 @@
// The activity that we are finishing may be over the lock screen. In this case, we do not
// want to consider activities that cannot be shown on the lock screen as running and should
// proceed with finishing the activity if there is no valid next top running activity.
+ // Note that if this finishing activity is floating task, we don't need to wait the
+ // next activity resume and can destroy it directly.
final ActivityDisplay display = getDisplay();
final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */);
+ final boolean isFloating = r.getConfiguration().windowConfiguration.tasksAreFloating();
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
- && next != null && !next.nowVisible) {
+ && next != null && !next.nowVisible && !isFloating) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 9d80425..78c5dbd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -476,6 +476,11 @@
public abstract int getDisplayIdForWindow(IBinder windowToken);
/**
+ * @return The top focused display ID.
+ */
+ public abstract int getTopFocusedDisplayId();
+
+ /**
* Checks whether this display should support showing system decorations.
*/
public abstract boolean shouldShowSystemDecorOnDisplay(int displayId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8ed2a15..d46aa7b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7340,6 +7340,13 @@
}
@Override
+ public int getTopFocusedDisplayId() {
+ synchronized (mGlobalLock) {
+ return mRoot.getTopFocusedDisplayContent().getDisplayId();
+ }
+ }
+
+ @Override
public boolean shouldShowSystemDecorOnDisplay(int displayId) {
synchronized (mGlobalLock) {
return WindowManagerService.this.shouldShowSystemDecors(displayId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8e18683..4105487 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2861,6 +2861,13 @@
}
mDestroying = false;
destroyedSomething = true;
+
+ // Since mDestroying will affect AppWindowToken#allDrawn, we need to perform another
+ // traversal in case we are waiting on this window to start the transition.
+ if (getDisplayContent().mAppTransition.isTransitionSet()
+ && getDisplayContent().mOpeningApps.contains(mAppToken)) {
+ mWmService.mWindowPlacerLocked.requestTraversal();
+ }
}
return destroyedSomething;
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 b34bd25..1a06490 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -1644,6 +1644,38 @@
}
@Test
+ public void testClearData() {
+ ArraySet<String> pkg = new ArraySet<>();
+ pkg.add(PKG_O);
+ mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
+ mHelper.createNotificationChannelGroup(
+ PKG_O, UID_O, new NotificationChannelGroup("1", "bye"), true);
+ mHelper.lockChannelsForOEM(pkg.toArray(new String[]{}));
+ mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, pkg);
+ mHelper.setNotificationDelegate(PKG_O, UID_O, "", 1);
+ mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_NONE);
+ mHelper.setBubblesAllowed(PKG_O, UID_O, false);
+ mHelper.setShowBadge(PKG_O, UID_O, false);
+ mHelper.setAppImportanceLocked(PKG_O, UID_O);
+
+ mHelper.clearData(PKG_O, UID_O);
+
+ assertEquals(IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_O, UID_O));
+ assertTrue(mHelper.areBubblesAllowed(PKG_O, UID_O));
+ assertTrue(mHelper.canShowBadge(PKG_O, UID_O));
+ assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+ assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O));
+ assertEquals(0, mHelper.getNotificationChannels(PKG_O, UID_O, true).getList().size());
+ assertEquals(0, mHelper.getNotificationChannelGroups(PKG_O, UID_O).size());
+
+ NotificationChannel channel = getChannel();
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false);
+
+ assertTrue(channel.isImportanceLockedByCriticalDeviceFunction());
+ assertTrue(channel.isImportanceLockedByOEM());
+ }
+
+ @Test
public void testRecordDefaults() throws Exception {
assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1,
UID_N_MR1));
diff --git a/tests/testables/src/android/testing/BaseFragmentTest.java b/tests/testables/src/android/testing/BaseFragmentTest.java
index 9f60cce..6cd88b5 100644
--- a/tests/testables/src/android/testing/BaseFragmentTest.java
+++ b/tests/testables/src/android/testing/BaseFragmentTest.java
@@ -52,7 +52,7 @@
private static final int VIEW_ID = 42;
private final Class<? extends Fragment> mCls;
- private Handler mHandler;
+ protected Handler mHandler;
protected FrameLayout mView;
protected FragmentController mFragments;
protected Fragment mFragment;