Merge "Use rethrowFromSystemServer instead of RuntimeException"
diff --git a/Android.bp b/Android.bp
index 7bdedc7..9602941 100644
--- a/Android.bp
+++ b/Android.bp
@@ -602,6 +602,7 @@
"telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
+ "telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl",
"telephony/java/com/android/internal/telephony/ISms.aidl",
"telephony/java/com/android/internal/telephony/ISub.aidl",
"telephony/java/com/android/internal/telephony/IOns.aidl",
@@ -741,7 +742,6 @@
static_libs: [
"apex_aidl_interface-java",
- "networkstack-aidl-interfaces-java",
"framework-protos",
"game-driver-protos",
"mediaplayer2-protos",
@@ -804,6 +804,7 @@
srcs: [
"core/java/android/os/IStatsCompanionService.aidl",
"core/java/android/os/IStatsManager.aidl",
+ "core/java/android/os/IStatsPullerCallback.aidl",
],
}
@@ -1187,52 +1188,6 @@
"org/apache/http/params",
]
-// The since flag (-since N.xml API_LEVEL) is used to add API Level information
-// to the reference documentation. Must be in order of oldest to newest.
-//
-// Conscrypt (com.android.org.conscrypt) is an implementation detail and should
-// not be referenced in the documentation.
-framework_docs_args = "-android -manifest $(location core/res/AndroidManifest.xml) " +
- "-hidePackage com.android.internal " +
- "-hidePackage com.android.internal.util " +
- "-hidePackage com.android.okhttp " +
- "-hidePackage com.android.org.conscrypt " +
- "-hidePackage com.android.server " +
- "-since $(location 1/public/api/android.xml) 1 " +
- "-since $(location 2/public/api/android.xml) 2 " +
- "-since $(location 3/public/api/android.xml) 3 " +
- "-since $(location 4/public/api/android.xml) 4 " +
- "-since $(location 5/public/api/android.xml) 5 " +
- "-since $(location 6/public/api/android.xml) 6 " +
- "-since $(location 7/public/api/android.xml) 7 " +
- "-since $(location 8/public/api/android.xml) 8 " +
- "-since $(location 9/public/api/android.xml) 9 " +
- "-since $(location 10/public/api/android.xml) 10 " +
- "-since $(location 11/public/api/android.xml) 11 " +
- "-since $(location 12/public/api/android.xml) 12 " +
- "-since $(location 13/public/api/android.xml) 13 " +
- "-since $(location 14/public/api/android.txt) 14 " +
- "-since $(location 15/public/api/android.txt) 15 " +
- "-since $(location 16/public/api/android.txt) 16 " +
- "-since $(location 17/public/api/android.txt) 17 " +
- "-since $(location 18/public/api/android.txt) 18 " +
- "-since $(location 19/public/api/android.txt) 19 " +
- "-since $(location 20/public/api/android.txt) 20 " +
- "-since $(location 21/public/api/android.txt) 21 " +
- "-since $(location 22/public/api/android.txt) 22 " +
- "-since $(location 23/public/api/android.txt) 23 " +
- "-since $(location 24/public/api/android.txt) 24 " +
- "-since $(location 25/public/api/android.txt) 25 " +
- "-since $(location 26/public/api/android.txt) 26 " +
- "-since $(location 27/public/api/android.txt) 27 " +
- "-since $(location 28/public/api/android.txt) 28 " +
- "-since $(location api/current.txt) Q " +
- "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
- "-overview $(location core/java/overview.html) " +
- // Federate Support Library references against local API file.
- "-federate SupportLib https://developer.android.com " +
- "-federationapi SupportLib $(location current/support-api.txt) "
-
framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
"-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
"-overview $(location core/java/overview.html) " +
diff --git a/Android.mk b/Android.mk
index 9c65948..9a91dd1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -72,6 +72,9 @@
$(hide) mkdir -p $(OUT_DOCS)/offline-sdk
( unzip -qo $< -d $(OUT_DOCS)/offline-sdk && touch -f $@ ) || exit 1
+.PHONY: docs offline-sdk-docs
+docs offline-sdk-docs: $(OUT_DOCS)/offline-sdk-timestamp
+
# Run this for checkbuild
checkbuild: doc-comment-check-docs
# Check comment when you are updating the API
diff --git a/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java b/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java
index ec46a75..c506aec 100644
--- a/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java
+++ b/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java
@@ -64,7 +64,7 @@
Context context = InstrumentationRegistry.getTargetContext();
TextClassificationManager textClassificationManager =
context.getSystemService(TextClassificationManager.class);
- mTextClassifier = textClassificationManager.getTextClassifier();
+ mTextClassifier = textClassificationManager.getLocalTextClassifier();
}
@Test
diff --git a/api/current.txt b/api/current.txt
index c5cd573..6f2751d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -80,7 +80,6 @@
field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
field public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
- field public static final String GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY = "android.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY";
field public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field @Deprecated public static final String GET_TASKS = "android.permission.GET_TASKS";
field public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
@@ -131,6 +130,7 @@
field public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
+ field public static final String REQUEST_SCREEN_LOCK_COMPLEXITY = "android.permission.REQUEST_SCREEN_LOCK_COMPLEXITY";
field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final String SEND_SMS = "android.permission.SEND_SMS";
@@ -6646,7 +6646,7 @@
method @Nullable public CharSequence getOrganizationName(@NonNull android.content.ComponentName);
method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(@NonNull android.content.ComponentName);
method @NonNull public android.app.admin.DevicePolicyManager getParentProfileInstance(@NonNull android.content.ComponentName);
- method @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY) public int getPasswordComplexity();
+ method @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY) public int getPasswordComplexity();
method public long getPasswordExpiration(@Nullable android.content.ComponentName);
method public long getPasswordExpirationTimeout(@Nullable android.content.ComponentName);
method public int getPasswordHistoryLength(@Nullable android.content.ComponentName);
@@ -6840,7 +6840,7 @@
field public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final String EXTRA_DELEGATION_SCOPES = "android.app.extra.DELEGATION_SCOPES";
field public static final String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
- field @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY";
+ field @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY";
field public static final String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
field public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
@@ -11482,7 +11482,6 @@
method public void setOriginatingUri(@Nullable android.net.Uri);
method public void setReferrerUri(@Nullable android.net.Uri);
method public void setSize(long);
- method public void setStaged();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionParams> CREATOR;
field public static final int MODE_FULL_INSTALL = 1; // 0x1
@@ -15409,28 +15408,38 @@
method public float getGradientCenterY();
method public float getGradientRadius();
method public int getGradientType();
+ method public int getInnerRadius();
+ method public float getInnerRadiusRatio();
method public int getOpacity();
method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
method public int getShape();
+ method public int getThickness();
+ method public float getThicknessRatio();
method public boolean getUseLevel();
method public void setAlpha(int);
method public void setColor(@ColorInt int);
method public void setColor(@Nullable android.content.res.ColorStateList);
method public void setColorFilter(@Nullable android.graphics.ColorFilter);
method public void setColors(@ColorInt int[]);
+ method public void setColors(@ColorInt int[], @Nullable float[]);
method public void setCornerRadii(@Nullable float[]);
method public void setCornerRadius(float);
method public void setDither(boolean);
method public void setGradientCenter(float, float);
method public void setGradientRadius(float);
method public void setGradientType(int);
+ method public void setInnerRadius(int);
+ method public void setInnerRadiusRatio(float);
method public void setOrientation(android.graphics.drawable.GradientDrawable.Orientation);
+ method public void setPadding(int, int, int, int);
method public void setShape(int);
method public void setSize(int, int);
method public void setStroke(int, @ColorInt int);
method public void setStroke(int, android.content.res.ColorStateList);
method public void setStroke(int, @ColorInt int, float, float);
method public void setStroke(int, android.content.res.ColorStateList, float, float);
+ method public void setThickness(int);
+ method public void setThicknessRatio(float);
method public void setUseLevel(boolean);
field public static final int LINE = 2; // 0x2
field public static final int LINEAR_GRADIENT = 0; // 0x0
@@ -45233,6 +45242,9 @@
field public static final int PHONE_TYPE_GSM = 1; // 0x1
field public static final int PHONE_TYPE_NONE = 0; // 0x0
field public static final int PHONE_TYPE_SIP = 3; // 0x3
+ field public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2; // 0x2
+ field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
+ field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
field public static final int SIM_STATE_ABSENT = 1; // 0x1
field public static final int SIM_STATE_CARD_IO_ERROR = 8; // 0x8
field public static final int SIM_STATE_CARD_RESTRICTED = 9; // 0x9
@@ -56691,6 +56703,8 @@
method public int getMaxValue();
method public int getMinValue();
method public int getSelectionDividerHeight();
+ method @ColorInt public int getTextColor();
+ method @FloatRange(from=0.0, fromInclusive=false) public float getTextSize();
method public int getValue();
method public boolean getWrapSelectorWheel();
method public void setDisplayedValues(String[]);
@@ -56701,6 +56715,8 @@
method public void setOnScrollListener(android.widget.NumberPicker.OnScrollListener);
method public void setOnValueChangedListener(android.widget.NumberPicker.OnValueChangeListener);
method public void setSelectionDividerHeight(@IntRange(from=0) @Px int);
+ method public void setTextColor(@ColorInt int);
+ method public void setTextSize(@FloatRange(from=0.0, fromInclusive=false) float);
method public void setValue(int);
method public void setWrapSelectorWheel(boolean);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index bb34f68..093f916 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -641,7 +641,7 @@
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
method @Deprecated @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
- method public void setProfileOwnerCanAccessDeviceIdsForUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
+ method @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIdsForUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final String ACTION_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION";
@@ -1535,6 +1535,7 @@
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
}
public class PackageItemInfo {
@@ -5779,6 +5780,11 @@
field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
}
+ public static interface DeviceConfig.Runtime {
+ field public static final String NAMESPACE = "runtime";
+ field public static final String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
+ }
+
public static interface DeviceConfig.RuntimeNative {
field public static final String NAMESPACE = "runtime_native";
}
@@ -7754,6 +7760,7 @@
method public void requestEmbeddedSubscriptionInfoListRefresh(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @NonNull java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
field public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index d6f045e..faf2053 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -71,6 +71,7 @@
"src/external/Perfetto.cpp",
"src/external/Perfprofd.cpp",
"src/external/StatsPuller.cpp",
+ "src/external/StatsCallbackPuller.cpp",
"src/external/StatsCompanionServicePuller.cpp",
"src/external/SubsystemSleepStatePuller.cpp",
"src/external/PowerStatsPuller.cpp",
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 86bf3ec..bd21a95 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1057,6 +1057,24 @@
return Status::ok();
}
+Status StatsService::registerPullerCallback(int32_t atomTag,
+ const sp<android::os::IStatsPullerCallback>& pullerCallback,
+ const String16& packageName) {
+ ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
+ VLOG("StatsService::registerPullerCallback called.");
+ mPullerManager->RegisterPullerCallback(atomTag, pullerCallback);
+ return Status::ok();
+}
+
+Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& packageName) {
+ ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
+ VLOG("StatsService::unregisterPullerCallback called.");
+ mPullerManager->UnregisterPullerCallback(atomTag);
+ return Status::ok();
+}
+
hardware::Return<void> StatsService::reportSpeakerImpedance(
const SpeakerImpedance& speakerImpedance) {
LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), speakerImpedance);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index cdff50f..941ed46 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -173,6 +173,19 @@
virtual Status sendAppBreadcrumbAtom(int32_t label, int32_t state) override;
/**
+ * Binder call to register a callback function for a vendor pulled atom.
+ * Note: this atom must NOT have uid as a field.
+ */
+ virtual Status registerPullerCallback(int32_t atomTag,
+ const sp<android::os::IStatsPullerCallback>& pullerCallback,
+ const String16& packageName) override;
+
+ /**
+ * Binder call to unregister any existing callback function for a vendor pulled atom.
+ */
+ virtual Status unregisterPullerCallback(int32_t atomTag, const String16& packageName) override;
+
+ /**
* Binder call to get SpeakerImpedance atom.
*/
virtual Return<void> reportSpeakerImpedance(const SpeakerImpedance& speakerImpedance) override;
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
new file mode 100644
index 0000000..d718273
--- /dev/null
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include <android/os/IStatsPullerCallback.h>
+
+#include "StatsCallbackPuller.h"
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+
+using namespace android::binder;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+StatsCallbackPuller::StatsCallbackPuller(int tagId, const sp<IStatsPullerCallback>& callback) :
+ StatsPuller(tagId), mCallback(callback) {
+ VLOG("StatsCallbackPuller created for tag %d", tagId);
+}
+
+bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ VLOG("StatsCallbackPuller called for tag %d", mTagId)
+ if(mCallback == nullptr) {
+ ALOGW("No callback registered");
+ return false;
+ }
+ int64_t wallClockTimeNs = getWallClockNs();
+ int64_t elapsedTimeNs = getElapsedRealtimeNs();
+ vector<StatsLogEventWrapper> returned_value;
+ Status status = mCallback->pullData(mTagId, elapsedTimeNs, wallClockTimeNs, &returned_value);
+ if (!status.isOk()) {
+ ALOGW("StatsCallbackPuller::pull failed for %d", mTagId);
+ return false;
+ }
+ data->clear();
+ for (const StatsLogEventWrapper& it: returned_value) {
+ LogEvent::createLogEvents(it, *data);
+ }
+ VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId);
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.h b/cmds/statsd/src/external/StatsCallbackPuller.h
new file mode 100644
index 0000000..c4bfa89
--- /dev/null
+++ b/cmds/statsd/src/external/StatsCallbackPuller.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#pragma once
+
+#include <android/os/IStatsPullerCallback.h>
+#include <utils/String16.h>
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class StatsCallbackPuller : public StatsPuller {
+public:
+ explicit StatsCallbackPuller(int tagId, const sp<IStatsPullerCallback>& callback);
+
+private:
+ bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
+ const sp<IStatsPullerCallback> mCallback;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index c7c22ee..9552c0a 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -33,7 +33,7 @@
void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; }
StatsPuller::StatsPuller(const int tagId)
- : mTagId(tagId) {
+ : mTagId(tagId), mLastPullTimeNs(0) {
}
bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ecdcd21..ed72b29 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -18,6 +18,7 @@
#include "Log.h"
#include <android/os/IStatsCompanionService.h>
+#include <android/os/IStatsPullerCallback.h>
#include <cutils/log.h>
#include <math.h>
#include <stdint.h>
@@ -29,6 +30,7 @@
#include "PowerStatsPuller.h"
#include "ResourceHealthManagerPuller.h"
#include "StatsCompanionServicePuller.h"
+#include "StatsCallbackPuller.h"
#include "StatsPullerManager.h"
#include "SubsystemSleepStatePuller.h"
#include "statslog.h"
@@ -49,7 +51,7 @@
// Values smaller than this may require to update the alarm.
const int64_t NO_ALARM_UPDATE = INT64_MAX;
-const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
+std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
// wifi_bytes_transfer
{android::util::WIFI_BYTES_TRANSFER,
{.additiveFields = {2, 3, 4, 5},
@@ -420,6 +422,30 @@
return totalCleared;
}
+void StatsPullerManager::RegisterPullerCallback(int32_t atomTag,
+ const sp<IStatsPullerCallback>& callback) {
+ AutoMutex _l(mLock);
+ // Platform pullers cannot be changed.
+ if (atomTag < StatsdStats::kMaxPlatformAtomTag) {
+ VLOG("RegisterPullerCallback: atom tag %d is less than min tag %d",
+ atomTag, StatsdStats::kMaxPlatformAtomTag);
+ return;
+ }
+ VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
+ kAllPullAtomInfo[atomTag] = {.puller = new StatsCallbackPuller(atomTag, callback)};
+}
+
+void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
+ AutoMutex _l(mLock);
+ // Platform pullers cannot be changed.
+ if (atomTag < StatsdStats::kMaxPlatformAtomTag) {
+ return;
+ }
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
+ kAllPullAtomInfo.erase(atomTag);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 807e4af..45f6b35 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -17,6 +17,7 @@
#pragma once
#include <android/os/IStatsCompanionService.h>
+#include <android/os/IStatsPullerCallback.h>
#include <binder/IServiceManager.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
@@ -91,7 +92,12 @@
void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService);
- const static std::map<int, PullAtomInfo> kAllPullAtomInfo;
+ void RegisterPullerCallback(int32_t atomTag,
+ const sp<IStatsPullerCallback>& callback);
+
+ void UnregisterPullerCallback(int32_t atomTag);
+
+ static std::map<int, PullAtomInfo> kAllPullAtomInfo;
private:
sp<IStatsCompanionService> mStatsCompanionService = nullptr;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index c4034ff..40329b7 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -423,6 +423,15 @@
mPulledAtomStats[atomId].emptyData++;
}
+void StatsdStats::notePullerCallbackRegistrationChanged(int atomId, bool registered) {
+ lock_guard<std::mutex> lock(mLock);
+ if (registered) {
+ mPulledAtomStats[atomId].registeredCount++;
+ } else {
+ mPulledAtomStats[atomId].unregisteredCount++;
+ }
+}
+
void StatsdStats::noteHardDimensionLimitReached(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).hardDimensionLimitReached++;
@@ -514,6 +523,8 @@
pullStats.second.dataError = 0;
pullStats.second.pullTimeout = 0;
pullStats.second.pullExceedMaxDelay = 0;
+ pullStats.second.registeredCount = 0;
+ pullStats.second.unregisteredCount = 0;
}
mAtomMetricStats.clear();
}
@@ -625,12 +636,14 @@
" (average pull time nanos)%lld, (max pull time nanos)%lld, (average pull delay "
"nanos)%lld, "
" (max pull delay nanos)%lld, (data error)%ld\n"
- " (pull timeout)%ld, (pull exceed max delay)%ld\n",
+ " (pull timeout)%ld, (pull exceed max delay)%ld\n"
+ " (registered count) %ld, (unregistered count) %ld\n",
(int)pair.first, (long)pair.second.totalPull, (long)pair.second.totalPullFromCache,
(long)pair.second.minPullIntervalSec, (long long)pair.second.avgPullTimeNs,
(long long)pair.second.maxPullTimeNs, (long long)pair.second.avgPullDelayNs,
(long long)pair.second.maxPullDelayNs, pair.second.dataError,
- pair.second.pullTimeout, pair.second.pullExceedMaxDelay);
+ pair.second.pullTimeout, pair.second.pullExceedMaxDelay,
+ pair.second.registeredCount, pair.second.unregisteredCount);
}
if (mAnomalyAlarmRegisteredStats > 0) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index ea3f3b3..65e8a32 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -146,6 +146,10 @@
// Max time to do a pull.
static const int64_t kPullMaxDelayNs = 10 * NS_PER_SEC;
+
+ // Max platform atom tag number.
+ static const int32_t kMaxPlatformAtomTag = 100000;
+
/**
* Report a new config has been received and report the static stats about the config.
*
@@ -340,6 +344,13 @@
void noteEmptyData(int atomId);
/**
+ * Records that a puller callback for the given atomId was registered or unregistered.
+ *
+ * @param registered True if the callback was registered, false if was unregistered.
+ */
+ void notePullerCallbackRegistrationChanged(int atomId, bool registered);
+
+ /**
* Hard limit was reached in the cardinality of an atom
*/
void noteHardDimensionLimitReached(int64_t metricId);
@@ -416,6 +427,8 @@
long statsCompanionPullFailed = 0;
long statsCompanionPullBinderTransactionFailed = 0;
long emptyData = 0;
+ long registeredCount = 0;
+ long unregisteredCount = 0;
} PulledAtomStats;
typedef struct {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index ac6c27a..851ae99 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -450,6 +450,17 @@
}
mMatchedMetricDimensionKeys.clear();
mHasGlobalBase = true;
+
+ // If we reach the guardrail, we might have dropped some data which means the bucket is
+ // incomplete.
+ //
+ // The base also needs to be reset. If we do not have the full data, we might
+ // incorrectly compute the diff when mUseZeroDefaultBase is true since an existing key
+ // might be missing from mCurrentSlicedBucket.
+ if (hasReachedGuardRailLimit()) {
+ invalidateCurrentBucket();
+ mCurrentSlicedBucket.clear();
+ }
}
void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
@@ -471,6 +482,10 @@
}
}
+bool ValueMetricProducer::hasReachedGuardRailLimit() const {
+ return mCurrentSlicedBucket.size() >= mDimensionHardLimit;
+}
+
bool ValueMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
// ===========GuardRail==============
// 1. Report the tuple count if the tuple count > soft limit
@@ -481,7 +496,7 @@
size_t newTupleCount = mCurrentSlicedBucket.size() + 1;
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
- if (newTupleCount > mDimensionHardLimit) {
+ if (hasReachedGuardRailLimit()) {
ALOGE("ValueMetric %lld dropping data for dimension key %s", (long long)mMetricId,
newKey.toString().c_str());
StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index d1c2315..f26ad85 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -158,6 +158,7 @@
// Util function to check whether the specified dimension hits the guardrail.
bool hitGuardRailLocked(const MetricDimensionKey& newKey);
+ bool hasReachedGuardRailLimit() const;
bool hitFullBucketGuardRailLocked(const MetricDimensionKey& newKey);
@@ -244,6 +245,7 @@
FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket);
FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate);
FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed);
+ FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit);
FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed);
FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 6a07a3f..863261a 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -407,6 +407,8 @@
optional int64 stats_companion_pull_failed = 13;
optional int64 stats_companion_pull_binder_transaction_failed = 14;
optional int64 empty_data = 15;
+ optional int64 registered_count = 16;
+ optional int64 unregistered_count = 17;
}
repeated PulledAtomStats pulled_atom_stats = 10;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index aa8cfc5..0ebf2ca 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -70,6 +70,8 @@
const int FIELD_ID_STATS_COMPANION_FAILED = 13;
const int FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED = 14;
const int FIELD_ID_EMPTY_DATA = 15;
+const int FIELD_ID_PULL_REGISTERED_COUNT = 16;
+const int FIELD_ID_PULL_UNREGISTERED_COUNT = 17;
// for AtomMetricStats proto
const int FIELD_ID_ATOM_METRIC_STATS = 17;
const int FIELD_ID_METRIC_ID = 1;
@@ -480,6 +482,10 @@
(long long)pair.second.statsCompanionPullBinderTransactionFailed);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA,
(long long)pair.second.emptyData);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_REGISTERED_COUNT,
+ (long long) pair.second.registeredCount);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_UNREGISTERED_COUNT,
+ (long long) pair.second.unregisteredCount);
protoOutput->end(token);
}
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 92aa998..44a88f0 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -259,6 +259,10 @@
stats.notePullDelay(android::util::DISK_SPACE, 3335L);
stats.notePull(android::util::DISK_SPACE);
stats.notePullFromCache(android::util::DISK_SPACE);
+ stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, true);
+ stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, false);
+ stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, true);
+
vector<uint8_t> output;
stats.dumpStats(&output, false);
@@ -276,6 +280,8 @@
EXPECT_EQ(3333L, report.pulled_atom_stats(0).max_pull_time_nanos());
EXPECT_EQ(2223L, report.pulled_atom_stats(0).average_pull_delay_nanos());
EXPECT_EQ(3335L, report.pulled_atom_stats(0).max_pull_delay_nanos());
+ EXPECT_EQ(2L, report.pulled_atom_stats(0).registered_count());
+ EXPECT_EQ(1L, report.pulled_atom_stats(0).unregistered_count());
}
TEST(StatsdStatsTest, TestAtomMetricsStats) {
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index ae3cdbc..572b199 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -2390,6 +2390,51 @@
EXPECT_EQ(true, valueProducer.mHasGlobalBase);
}
+TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+ metric.set_condition(StringToId("SCREEN_ON"));
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ for (int i = 0; i < 2000; i++) {
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(i);
+ event->write(i);
+ event->init();
+ data->push_back(event);
+ }
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ valueProducer.mCondition = false;
+ valueProducer.onConditionChanged(true, bucket2StartTimeNs + 2);
+ EXPECT_EQ(true, valueProducer.mCurrentBucketIsInvalid);
+ EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+}
+
TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
ValueMetric metric;
metric.set_id(metricId);
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 010e447..b72ce89 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2439,7 +2439,6 @@
Lcom/android/internal/telephony/cat/CatService;->mCmdIf:Lcom/android/internal/telephony/CommandsInterface;
Lcom/android/internal/telephony/cat/CatService;->mContext:Landroid/content/Context;
Lcom/android/internal/telephony/cat/CatService;->mCurrntCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
-Lcom/android/internal/telephony/cat/CatService;->mHandlerThread:Landroid/os/HandlerThread;
Lcom/android/internal/telephony/cat/CatService;->mMenuCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
Lcom/android/internal/telephony/cat/CatService;->mMsgDecoder:Lcom/android/internal/telephony/cat/RilMessageDecoder;
Lcom/android/internal/telephony/cat/CatService;->mSlotId:I
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index db6ad3d..2b765b2 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -247,8 +247,20 @@
boolean preserveWindows, boolean animate, int animationDuration);
boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop,
boolean animate, in Rect initialBounds, boolean showRecents);
-
-
+ /**
+ * Use the offset to adjust the stack boundary with animation.
+ *
+ * @param stackId Id of the stack to adjust.
+ * @param compareBounds Offset is only applied if the current pinned stack bounds is equal to
+ * the compareBounds.
+ * @param xOffset The horizontal offset.
+ * @param yOffset The vertical offset.
+ * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
+ * default animation duration should be used.
+ * @throws RemoteException
+ */
+ void offsetPinnedStackBounds(int stackId, in Rect compareBounds, int xOffset, int yOffset,
+ int animationDuration);
/**
* Removes stacks in the input windowing modes from the system if they are of activity type
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 3119b37..7746148 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.os.IBinder;
import android.os.IStatsManager;
+import android.os.IStatsPullerCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.AndroidException;
@@ -408,6 +409,39 @@
}
}
+ /**
+ * Registers a callback for an atom when that atom is to be pulled. The stats service will
+ * invoke pullData in the callback when the stats service determines that this atom needs to be
+ * pulled. Currently, this only works for atoms with tags above 100,000 that do not have a uid.
+ *
+ * @param atomTag The tag of the atom for this puller callback. Must be at least 100000.
+ * @param callback The callback to be invoked when the stats service pulls the atom.
+ * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
+ public void setPullerCallback(int atomTag, IStatsPullerCallback callback)
+ throws StatsUnavailableException {
+ synchronized (this) {
+ try {
+ IStatsManager service = getIStatsManagerLocked();
+ if (callback == null) {
+ service.unregisterPullerCallback(atomTag, mContext.getOpPackageName());
+ } else {
+ service.registerPullerCallback(atomTag, callback,
+ mContext.getOpPackageName());
+ }
+
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to connect to statsd when registering data listener.");
+ throw new StatsUnavailableException("could not connect", e);
+ } catch (SecurityException e) {
+ throw new StatsUnavailableException(e.getMessage(), e);
+ }
+ }
+ }
+
private class StatsdDeathRecipient implements IBinder.DeathRecipient {
@Override
public void binderDied() {
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 077b177..dd00e5a 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -97,6 +97,12 @@
public long lastActiveTime;
/**
+ * The id of the display this task is associated with.
+ * @hide
+ */
+ public int displayId;
+
+ /**
* The recent activity values for the highest activity in the stack to have set the values.
* {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
*/
@@ -152,6 +158,7 @@
userId = source.readInt();
stackId = source.readInt();
taskId = source.readInt();
+ displayId = source.readInt();
isRunning = source.readBoolean();
baseIntent = source.readInt() != 0
? Intent.CREATOR.createFromParcel(source)
@@ -179,6 +186,7 @@
dest.writeInt(userId);
dest.writeInt(stackId);
dest.writeInt(taskId);
+ dest.writeInt(displayId);
dest.writeBoolean(isRunning);
if (baseIntent != null) {
@@ -209,6 +217,7 @@
@Override
public String toString() {
return "TaskInfo{userId=" + userId + " stackId=" + stackId + " taskId=" + taskId
+ + " displayId=" + displayId
+ " isRunning=" + isRunning
+ " baseIntent=" + baseIntent + " baseActivity=" + baseActivity
+ " topActivity=" + topActivity + " origActivity=" + origActivity
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8861151..2f70c9d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1376,7 +1376,7 @@
* complexity, and use this activity with extra {@link #EXTRA_PASSWORD_COMPLEXITY} to suggest
* to users how complex the app wants the new screen lock to be. Note that both {@link
* #getPasswordComplexity()} and the extra {@link #EXTRA_PASSWORD_COMPLEXITY} require the
- * calling app to have the permission {@link permission#GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY}.
+ * calling app to have the permission {@link permission#REQUEST_SCREEN_LOCK_COMPLEXITY}.
*
* <p>If the intent is launched from within a managed profile with a profile
* owner built against {@link android.os.Build.VERSION_CODES#M} or before,
@@ -1404,7 +1404,7 @@
*
* <p>If an invalid value is used, it will be treated as {@link #PASSWORD_COMPLEXITY_NONE}.
*/
- @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY)
+ @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY)
public static final String EXTRA_PASSWORD_COMPLEXITY =
"android.app.extra.PASSWORD_COMPLEXITY";
@@ -3346,10 +3346,10 @@
*
* @throws IllegalStateException if the user is not unlocked.
* @throws SecurityException if the calling application does not have the permission
- * {@link permission#GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY}
+ * {@link permission#REQUEST_SCREEN_LOCK_COMPLEXITY}
*/
@PasswordComplexity
- @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY)
+ @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY)
public int getPasswordComplexity() {
throwIfParentInstance("getPasswordComplexity");
if (mService == null) {
@@ -10537,6 +10537,8 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(value = android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS,
+ conditional = true)
public void setProfileOwnerCanAccessDeviceIdsForUser(
@NonNull ComponentName who, @NonNull UserHandle userHandle) {
if (mService == null) {
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 47034a6..7cc4391 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1029,10 +1029,18 @@
}
/**
+ * Returns true if the activity has maximum or minimum aspect ratio.
+ * @hide
+ */
+ public boolean hasFixedAspectRatio() {
+ return maxAspectRatio != 0 || minAspectRatio != 0;
+ }
+
+ /**
* Returns true if the activity's orientation is fixed.
* @hide
*/
- boolean isFixedOrientation() {
+ public boolean isFixedOrientation() {
return isFixedOrientationLandscape() || isFixedOrientationPortrait()
|| screenOrientation == SCREEN_ORIENTATION_LOCKED;
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0ac4f64..8095473 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -791,11 +791,6 @@
* individual session IDs can be added with {@link #addChildSessionId(int)}
* and commit of the multi-package session will result in all child sessions
* being committed atomically.
- * <p>
- * If a package requires to be installed only at reboot, the session should
- * be marked as a staged session by calling {@link SessionParams#setStaged()}
- * with {@code true}. This can also apply to a multi-package session, in
- * which case all the packages in the session will be applied at reboot.
*/
public static class Session implements Closeable {
/** {@hide} */
@@ -1539,7 +1534,11 @@
* Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
* multi-package. In that case, if any of the children sessions fail to install at reboot,
* all the other children sessions are aborted as well.
+ *
+ * {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public void setStaged() {
this.isStaged = true;
}
diff --git a/core/java/android/net/INetworkMonitorCallbacks.aidl b/core/java/android/net/INetworkMonitorCallbacks.aidl
index a8682f9..5146585 100644
--- a/core/java/android/net/INetworkMonitorCallbacks.aidl
+++ b/core/java/android/net/INetworkMonitorCallbacks.aidl
@@ -24,7 +24,7 @@
void onNetworkMonitorCreated(in INetworkMonitor networkMonitor);
void notifyNetworkTested(int testResult, @nullable String redirectUrl);
void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
- void showProvisioningNotification(String action);
+ void showProvisioningNotification(String action, String packageName);
void hideProvisioningNotification();
void logCaptivePortalLoginEvent(int eventId, String packageName);
}
\ No newline at end of file
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index b6cd635..7a4c9bc 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -63,9 +63,6 @@
public static final String PERMISSION_MAINLINE_NETWORK_STACK =
"android.permission.MAINLINE_NETWORK_STACK";
- /** @hide */
- public static final String NETWORKSTACK_PACKAGE_NAME = "com.android.mainline.networkstack";
-
private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
@NonNull
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 93d6f4c..f1bba1a 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -16,6 +16,8 @@
package android.os;
+import android.os.IStatsPullerCallback;
+
/**
* Binder interface to communicate with the statistics management service.
* {@hide}
@@ -178,4 +180,20 @@
* this label. This allows building custom metrics and predicates.
*/
void sendAppBreadcrumbAtom(int label, int state);
+
+ /**
+ * Registers a puller callback function that, when invoked, pulls the data
+ * for the specified vendor atom tag.
+ *
+ * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS
+ */
+ oneway void registerPullerCallback(int atomTag, IStatsPullerCallback pullerCallback,
+ String packageName);
+
+ /**
+ * Unregisters a puller callback function for the given vendor atom.
+ *
+ * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS
+ */
+ oneway void unregisterPullerCallback(int atomTag, String packageName);
}
diff --git a/core/java/android/os/IStatsPullerCallback.aidl b/core/java/android/os/IStatsPullerCallback.aidl
new file mode 100644
index 0000000..1684aeb
--- /dev/null
+++ b/core/java/android/os/IStatsPullerCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android.os;
+
+import android.os.StatsLogEventWrapper;
+
+/**
+ * Binder interface to pull atoms for the stats service.
+ * {@hide}
+ */
+interface IStatsPullerCallback {
+ /**
+ * Pull data for the specified atom tag. Returns an array of StatsLogEventWrapper containing
+ * the data.
+ *
+ * Note: These pulled atoms should not have uid/attribution chain. Additionally, the event
+ * timestamps will be truncated to the nearest 5 minutes.
+ */
+ StatsLogEventWrapper[] pullData(int atomTag, long elapsedNanos, long wallClocknanos);
+
+}
diff --git a/core/java/android/os/ParcelFileDescriptor.aidl b/core/java/android/os/ParcelFileDescriptor.aidl
deleted file mode 100644
index c07b980..0000000
--- a/core/java/android/os/ParcelFileDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/os/ParcelFileDescriptor.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-parcelable ParcelFileDescriptor cpp_header "binder/ParcelFileDescriptor.h";
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index acb9eac..2334242 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -57,20 +57,18 @@
public static final Parcelable.Creator<StatsLogEventWrapper> CREATOR = new
Parcelable.Creator<StatsLogEventWrapper>() {
public StatsLogEventWrapper createFromParcel(Parcel in) {
- android.util.EventLog.writeEvent(0x534e4554, "112550251",
- android.os.Binder.getCallingUid(), "");
- // Purposefully leaving this method not implemented.
- throw new RuntimeException("Not implemented");
+ return new StatsLogEventWrapper(in);
}
public StatsLogEventWrapper[] newArray(int size) {
- android.util.EventLog.writeEvent(0x534e4554, "112550251",
- android.os.Binder.getCallingUid(), "");
- // Purposefully leaving this method not implemented.
- throw new RuntimeException("Not implemented");
+ return new StatsLogEventWrapper[size];
}
};
+ private StatsLogEventWrapper(Parcel in) {
+ readFromParcel(in);
+ }
+
/**
* Set work source if any.
*/
@@ -197,6 +195,70 @@
}
/**
+ * Reads from parcel and appropriately fills member fields.
+ */
+ public void readFromParcel(Parcel in) {
+ mTypes = new ArrayList<>();
+ mValues = new ArrayList<>();
+ mWorkSource = null;
+
+ mTag = in.readInt();
+ mElapsedTimeNs = in.readLong();
+ mWallClockTimeNs = in.readLong();
+
+ // Clear any data.
+ if (DEBUG) {
+ Slog.d(TAG, "Reading " + mTag + " " + mElapsedTimeNs + " " + mWallClockTimeNs);
+ }
+ // Set up worksource if present.
+ int numWorkChains = in.readInt();
+ if (numWorkChains > 0) {
+ mWorkSource = new WorkSource();
+ for (int i = 0; i < numWorkChains; i++) {
+ android.os.WorkSource.WorkChain workChain = mWorkSource.createWorkChain();
+ int workChainSize = in.readInt();
+ for (int j = 0; j < workChainSize; j++) {
+ int uid = in.readInt();
+ String tag = in.readString();
+ workChain.addNode(uid, tag);
+ }
+ }
+ }
+
+ // Do the rest of the types.
+ int numTypes = in.readInt();
+ if (DEBUG) {
+ Slog.d(TAG, "Reading " + numTypes + " elements");
+ }
+ for (int i = 0; i < numTypes; i++) {
+ int type = in.readInt();
+ mTypes.add(type);
+ switch (type) {
+ case EVENT_TYPE_INT:
+ mValues.add(in.readInt());
+ break;
+ case EVENT_TYPE_LONG:
+ mValues.add(in.readLong());
+ break;
+ case EVENT_TYPE_FLOAT:
+ mValues.add(in.readFloat());
+ break;
+ case EVENT_TYPE_DOUBLE:
+ mValues.add(in.readDouble());
+ break;
+ case EVENT_TYPE_STRING:
+ mValues.add(in.readString());
+ break;
+ case EVENT_TYPE_STORAGE:
+ mValues.add(in.createByteArray());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
* Boilerplate for Parcel.
*/
public int describeContents() {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index ec4f397..18e1f59 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -123,6 +123,21 @@
}
/**
+ * Namespace for all runtime related features.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface Runtime {
+ String NAMESPACE = "runtime";
+
+ /**
+ * Whether or not we use the precompiled layout.
+ */
+ String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
+ }
+
+ /**
* Namespace for all runtime native related features.
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 22329ba..c4019ad 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12347,6 +12347,12 @@
public static final String GAME_DRIVER_BLACKLIST = "game_driver_blacklist";
/**
+ * List of blacklists, each blacklist is a blacklist for a specific version of Game Driver.
+ * @hide
+ */
+ public static final String GAME_DRIVER_BLACKLISTS = "game_driver_blacklists";
+
+ /**
* Apps on the whitelist that are allowed to use Game Driver.
* The string is a list of application package names, seperated by comma.
* i.e. <apk1>,<apk2>,...,<apkN>
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 39b6876..b28ac47 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -33,6 +33,8 @@
import android.os.Message;
import android.os.SystemProperties;
import android.os.Trace;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
@@ -80,8 +82,6 @@
private static final String TAG = LayoutInflater.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY
- = "view.precompiled_layout_enabled";
private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex";
/** Empty stack trace used to avoid log spam in re-throw exceptions. */
@@ -412,8 +412,24 @@
}
private void initPrecompiledViews() {
- initPrecompiledViews(
- SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false));
+ // Use the device config if enabled, otherwise default to the system property.
+ String usePrecompiledLayout = null;
+ try {
+ usePrecompiledLayout = DeviceConfig.getProperty(
+ DeviceConfig.Runtime.NAMESPACE,
+ DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT);
+ } catch (Exception e) {
+ // May be caused by permission errors reading the property (i.e. instant apps).
+ }
+ boolean enabled = false;
+ if (TextUtils.isEmpty(usePrecompiledLayout)) {
+ enabled = SystemProperties.getBoolean(
+ DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT,
+ false);
+ } else {
+ enabled = Boolean.parseBoolean(usePrecompiledLayout);
+ }
+ initPrecompiledViews(enabled);
}
private void initPrecompiledViews(boolean enablePrecompiledViews) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 8a09788..e63a406 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1373,7 +1373,7 @@
* @hide
*/
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
try {
Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
diff --git a/core/java/android/view/textclassifier/TEST_MAPPING b/core/java/android/view/textclassifier/TEST_MAPPING
index 0d3c346..01a6ede 100644
--- a/core/java/android/view/textclassifier/TEST_MAPPING
+++ b/core/java/android/view/textclassifier/TEST_MAPPING
@@ -10,14 +10,6 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
- },
- {
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.textclassifier.cts"
- }
- ]
}
]
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 89bb273..dad2669 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -17,6 +17,8 @@
package android.widget;
import android.annotation.CallSuper;
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.Px;
@@ -340,7 +342,7 @@
/**
* The {@link Paint} for drawing the selector.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final Paint mSelectorWheelPaint;
/**
@@ -1718,6 +1720,44 @@
}
/**
+ * Sets the text color for all the states (normal, selected, focused) to be the given color.
+ *
+ * @param color A color value in the form 0xAARRGGBB.
+ */
+ public void setTextColor(@ColorInt int color) {
+ mSelectorWheelPaint.setColor(color);
+ mInputText.setTextColor(color);
+ invalidate();
+ }
+
+ /**
+ * @return the text color.
+ */
+ @ColorInt
+ public int getTextColor() {
+ return mSelectorWheelPaint.getColor();
+ }
+
+ /**
+ * Sets the text size to the given value. This value must be > 0
+ *
+ * @param size The size in pixel units.
+ */
+ public void setTextSize(@FloatRange(from = 0.0, fromInclusive = false) float size) {
+ mSelectorWheelPaint.setTextSize(size);
+ mInputText.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
+ invalidate();
+ }
+
+ /**
+ * @return the size (in pixels) of the text size in this NumberPicker.
+ */
+ @FloatRange(from = 0.0, fromInclusive = false)
+ public float getTextSize() {
+ return mSelectorWheelPaint.getTextSize();
+ }
+
+ /**
* Makes a measure spec that tries greedily to use the max value.
*
* @param measureSpec The measure spec.
diff --git a/core/java/com/android/internal/os/ChildZygoteInit.java b/core/java/com/android/internal/os/ChildZygoteInit.java
index cc74863..1f816c1 100644
--- a/core/java/com/android/internal/os/ChildZygoteInit.java
+++ b/core/java/com/android/internal/os/ChildZygoteInit.java
@@ -102,7 +102,7 @@
// are just isolated UIDs in the range, because for the webview zygote, there is no
// single range that captures all possible isolated UIDs.
// TODO(b/123615476) narrow this down
- if (uidGidMin < Process.FIRST_ISOLATED_UID) {
+ if (uidGidMin < Process.FIRST_APP_ZYGOTE_ISOLATED_UID) {
throw new RuntimeException("Passed in UID range does not map to isolated processes.");
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index d577653..39d61a1 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -448,6 +448,9 @@
optional SettingProto game_driver_whitelist = 12;
// ANGLE - List of Apps that can check ANGLE rules
optional SettingProto angle_whitelist = 13;
+ // Game Driver - List of blacklists, each blacklist is a blacklist for
+ // a specific Game Driver version
+ optional SettingProto game_driver_blacklists = 14;
}
optional Gpu gpu = 59;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 34ec92e..5b74d90 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2151,13 +2151,13 @@
android:label="@string/permlab_disableKeyguard"
android:protectionLevel="normal" />
- <!-- Allows an application to get the screen lock complexity and prompt users to update the
+ <!-- Allows an application to request the screen lock complexity and prompt users to update the
screen lock to a certain complexity level.
<p>Protection level: normal
-->
- <permission android:name="android.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY"
- android:label="@string/permlab_getAndRequestScreenLockComplexity"
- android:description="@string/permdesc_getAndRequestScreenLockComplexity"
+ <permission android:name="android.permission.REQUEST_SCREEN_LOCK_COMPLEXITY"
+ android:label="@string/permlab_requestScreenLockComplexity"
+ android:description="@string/permdesc_requestScreenLockComplexity"
android:protectionLevel="normal" />
<!-- ================================== -->
diff --git a/core/res/res/drawable/bottomsheet_background.xml b/core/res/res/drawable/bottomsheet_background.xml
index bc32ba6..3a8ad71 100644
--- a/core/res/res/drawable/bottomsheet_background.xml
+++ b/core/res/res/drawable/bottomsheet_background.xml
@@ -16,7 +16,7 @@
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners
- android:topLeftRadius="?attr/dialogCornerRadius"
- android:topRightRadius="?attr/dialogCornerRadius" />
+ android:topLeftRadius="@dimen/config_bottomDialogCornerRadius"
+ android:topRightRadius="@dimen/config_bottomDialogCornerRadius"/>
<solid android:color="?attr/colorBackgroundFloating" />
</shape>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 130f629..d14164f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3425,8 +3425,14 @@
-->
<string-array translatable="false" name="config_convert_to_emergency_number_map" />
- <!-- An array of packages for which notifications cannot be blocked. -->
- <string-array translatable="false" name="config_nonBlockableNotificationPackages" />
+ <!-- An array of packages for which notifications cannot be blocked.
+ Should only be used for core device functionality that must not be
+ rendered inoperative for safety reasons, like the phone dialer and
+ SMS handler. -->
+ <string-array translatable="false" name="config_nonBlockableNotificationPackages">
+ <item>com.android.dialer</item>
+ <item>com.android.messaging</item>
+ </string-array>
<!-- An array of packages which can listen for notifications on low ram devices. -->
<string-array translatable="false" name="config_allowedManagedServicesOnLowRamDevices" />
@@ -3897,4 +3903,22 @@
The ambient color temperature (in cct) to which we fall back when the ambient brightness
drops beneath a certain threshold. -->
<item name="config_displayWhiteBalanceLowLightAmbientColorTemperature" format="float" type="dimen">6500.0</item>
+
+ <!-- See DisplayWhiteBalanceController.
+ A float array containing a list of ambient color temperatures, in Kelvin. This array,
+ together with config_displayWhiteBalanceDisplayTemperatureValues, is used to generate a
+ lookup table used in DisplayWhiteBalanceController. This lookup table is used to map
+ ambient color temperature readings to a target color temperature for the display.
+ This table is optional. If used, this array must,
+ 1) Contain at least two entries
+ 2) Be the same length as config_displayWhiteBalanceDisplayTemperatureValues. -->
+ <array name="config_displayWhiteBalanceAmbientTemperatureValues">
+ </array>
+
+ <!-- See DisplayWhiteBalanceController.
+ An array containing a list of display color temperatures, in Kelvin. See
+ config_displayWhiteBalanceAmbientTemperatureValues for additional details.
+ The same restrictions apply to this array. -->
+ <array name="config_displayWhiteBalanceDisplayTemperatureValues">
+ </array>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6d5bd4b..62e79da 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1406,9 +1406,9 @@
re-enables the keylock when the call is finished.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
- <string name="permlab_getAndRequestScreenLockComplexity">get and request screen lock complexity</string>
+ <string name="permlab_requestScreenLockComplexity">request screen lock complexity</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
- <string name="permdesc_getAndRequestScreenLockComplexity">Allows the app to learn the screen
+ <string name="permdesc_requestScreenLockComplexity">Allows the app to learn the screen
lock complexity level (high, medium, low or none), which indicates the possible range of
length and type of the screen lock. The app can also suggest to users that they update the
screen lock to a certain level but users can freely ignore and navigate away. Note that the
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8e251fd..5a7d71f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3643,6 +3643,7 @@
<java-symbol type="array" name="config_displayWhiteBalanceDecreaseThresholds" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientBrightnessThreshold" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientColorTemperature" />
-
+ <java-symbol type="array" name="config_displayWhiteBalanceAmbientTemperatureValues" />
+ <java-symbol type="array" name="config_displayWhiteBalanceDisplayTemperatureValues" />
<java-symbol type="drawable" name="ic_action_open" />
</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 206682a..b919553 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -491,6 +491,7 @@
Settings.Global.GAME_DRIVER_ALL_APPS,
Settings.Global.GAME_DRIVER_OPT_IN_APPS,
Settings.Global.GAME_DRIVER_OPT_OUT_APPS,
+ Settings.Global.GAME_DRIVER_BLACKLISTS,
Settings.Global.GAME_DRIVER_BLACKLIST,
Settings.Global.GAME_DRIVER_WHITELIST,
Settings.Global.GPU_DEBUG_LAYER_APP,
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 6770ae1..7382213 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -209,21 +209,14 @@
<privapp-permissions package="com.android.mainline.networkstack">
<permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/>
- <permission name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"/>
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
<permission name="android.permission.CONTROL_VPN"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
- <permission name="android.permission.MANAGE_IPSEC_TUNNELS"/>
- <permission name="android.permission.MANAGE_NETWORK_POLICY"/>
<permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
<permission name="android.permission.MANAGE_USB"/>
- <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
- <permission name="android.permission.NETWORK_SETTINGS"/>
- <permission name="android.permission.NETWORK_STACK" />
- <permission name="android.permission.NET_TUNNELING"/>
<permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD"/>
- <permission name="android.permission.PEERS_MAC_ADDRESS"/>
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
<permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
@@ -261,6 +254,7 @@
<permission name="android.permission.CHANGE_LOWPAN_STATE"/>
<permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
<permission name="android.permission.CLEAR_APP_CACHE"/>
+ <permission name="android.permission.ACCESS_INSTANT_APPS" />
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.DELETE_CACHE_FILES"/>
<permission name="android.permission.DELETE_PACKAGES"/>
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 991847a..6ecb621 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -44,6 +44,7 @@
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.Xfermode;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -156,12 +157,12 @@
private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
private GradientState mGradientState;
@UnsupportedAppUsage
private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051827)
private Rect mPadding;
@UnsupportedAppUsage
private Paint mStrokePaint; // optional, set by the caller
@@ -670,7 +671,28 @@
* @see #setColor(int)
*/
public void setColors(@ColorInt int[] colors) {
+ setColors(colors, null);
+ }
+
+ /**
+ * Sets the colors and offsets used to draw the gradient.
+ * <p>
+ * Each color is specified as an ARGB integer and the array must contain at
+ * least 2 colors.
+ * <p>
+ * <strong>Note</strong>: changing colors will affect all instances of a
+ * drawable loaded from a resource. It is recommended to invoke
+ * {@link #mutate()} before changing the colors.
+ *
+ * @param colors an array containing 2 or more ARGB colors
+ * @param offsets optional array of floating point parameters representing the positions
+ * of the colors. Null evenly disperses the colors
+ * @see #mutate()
+ * @see #setColors(int[])
+ */
+ public void setColors(@ColorInt int[] colors, @Nullable float[] offsets) {
mGradientState.setGradientColors(colors);
+ mGradientState.mPositions = offsets;
mGradientIsDirty = true;
invalidateSelf();
}
@@ -849,6 +871,115 @@
}
}
+ /**
+ * Inner radius of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #getInnerRadiusRatio()
+ * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ */
+ public void setInnerRadiusRatio(float innerRadiusRatio) {
+ mGradientState.mInnerRadiusRatio = innerRadiusRatio;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the inner radius of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #setInnerRadiusRatio(float)
+ * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ */
+ public float getInnerRadiusRatio() {
+ return mGradientState.mInnerRadiusRatio;
+ }
+
+ /**
+ * Configure the inner radius of the ring.
+ *
+ * @see #getInnerRadius()
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
+ */
+ public void setInnerRadius(int innerRadius) {
+ mGradientState.mInnerRadius = innerRadius;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Retrn the inner radius of the ring
+ *
+ * @see #setInnerRadius(int)
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
+ */
+ public int getInnerRadius() {
+ return mGradientState.mInnerRadius;
+ }
+
+ /**
+ * Configure the thickness of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #getThicknessRatio()
+ * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ */
+ public void setThicknessRatio(float thicknessRatio) {
+ mGradientState.mThicknessRatio = thicknessRatio;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the thickness ratio of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #setThicknessRatio(float)
+ * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ */
+ public float getThicknessRatio() {
+ return mGradientState.mThicknessRatio;
+ }
+
+ /**
+ * Configure the thickness of the ring.
+ *
+ * @attr ref android.R.styleable#GradientDrawable_thickness
+ */
+ public void setThickness(int thickness) {
+ mGradientState.mThickness = thickness;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the thickness of the ring
+ *
+ * @see #setThickness(int)
+ * @attr ref android.R.styleable#GradientDrawable_thickness
+ */
+ public int getThickness() {
+ return mGradientState.mThickness;
+ }
+
+ /**
+ * Configure the padding of the gradient shape
+ * @param left Left padding of the gradient shape
+ * @param top Top padding of the gradient shape
+ * @param right Right padding of the gradient shape
+ * @param bottom Bottom padding of the gradient shape
+ *
+ * @attr ref android.R.styleable#GradientDrawablePadding_left
+ * @attr ref android.R.styleable#GradientDrawablePadding_top
+ * @attr ref android.R.styleable#GradientDrawablePadding_right
+ * @attr ref android.R.styleable#GradientDrawablePadding_bottom
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ if (mGradientState.mPadding == null) {
+ mGradientState.mPadding = new Rect();
+ }
+
+ mGradientState.mPadding.set(left, top, right, bottom);
+ mPadding = mGradientState.mPadding;
+ invalidateSelf();
+ }
+
private Path buildRing(GradientState st) {
if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
mPathIsDirty = false;
@@ -1814,46 +1945,46 @@
final static class GradientState extends ConstantState {
public @Config int mChangingConfigurations;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @Shape int mShape = RECTANGLE;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @GradientType int mGradient = LINEAR_GRADIENT;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mAngle = 0;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public Orientation mOrientation;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public ColorStateList mSolidColors;
public ColorStateList mStrokeColors;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @ColorInt int[] mGradientColors;
public @ColorInt int[] mTempColors; // no need to copy
public float[] mTempPositions; // no need to copy
@UnsupportedAppUsage
public float[] mPositions;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mStrokeWidth = -1; // if >= 0 use stroking.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mStrokeDashWidth = 0.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mStrokeDashGap = 0.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mRadius = 0.0f; // use this if mRadiusArray is null
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float[] mRadiusArray = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public Rect mPadding = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mWidth = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mHeight = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mInnerRadius = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public int mThickness = -1;
public boolean mDither = false;
public Insets mOpticalInsets = Insets.NONE;
diff --git a/media/java/android/media/session/MediaSessionProviderService.java b/media/java/android/media/session/MediaSessionProviderService.java
deleted file mode 100644
index 9a346ff..0000000
--- a/media/java/android/media/session/MediaSessionProviderService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.media.session;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * Abstract class for mainline module services.
- *
- * @hide // TODO: Make it as a @SystemApi
- */
-public abstract class MediaSessionProviderService extends Service {
-
- @Override
- public IBinder onBind(Intent intent) {
- // TODO: Return IMediaSessionProviderService.Stub()
- return null;
- }
-}
diff --git a/media/packages/MediaCore/Android.bp.bak b/media/packages/MediaCore/Android.bp.bak
deleted file mode 100644
index c7fd58b..0000000
--- a/media/packages/MediaCore/Android.bp.bak
+++ /dev/null
@@ -1,21 +0,0 @@
-android_app {
- name: "MediaCore",
-
- srcs: [
- "src/**/*.java",
- ],
-
- static_libs: [
- // TODO: Temporarily statically linked. Should go into "libs"
- "media1",
- ],
-
- // System app
- platform_apis: true,
-
- // Privileged app
- privileged: true,
-
- // Make sure that the implementation only relies on SDK or system APIs.
- sdk_version: "system_current",
-}
diff --git a/media/packages/MediaCore/AndroidManifest.xml b/media/packages/MediaCore/AndroidManifest.xml
deleted file mode 100644
index 4e2b274..0000000
--- a/media/packages/MediaCore/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/AndroidManifest.xml
-**
-** 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.
-*/
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.media" coreApp="true" android:sharedUserId="android.uid.system"
- android:sharedUserLabel="@string/android_system_label">
- <application android:process="system"
- android:persistent="true"
- android:directBootAware="true">
- <service android:name="AmlMediaSessionProviderService" android:singleUser="true">
- <intent-filter>
- <action android:name="android.media.session.MediaSessionProviderService"/>
- </intent-filter>
- </service>
- </application>
-</manifest>
diff --git a/media/packages/MediaCore/res/values/strings.xml b/media/packages/MediaCore/res/values/strings.xml
deleted file mode 100644
index 59fd635..0000000
--- a/media/packages/MediaCore/res/values/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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.
--->
-
-<resources>
- <!-- Label for the Android system components when they are shown to the user. -->
- <string name="android_system_label" translatable="false">Android System</string>
-</resources>
-
diff --git a/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java
deleted file mode 100644
index 43b95ab..0000000
--- a/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.media;
-
-import android.content.Context;
-import android.media.session.MediaSessionProviderService;
-import android.os.PowerManager;
-import android.util.Log;
-
-/**
- * System implementation of MediaSessionProviderService
- */
-public class AmlMediaSessionProviderService extends MediaSessionProviderService {
- private static final String TAG = "AmlMediaSessionProviderS";
- static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private Context mContext;
-
- public AmlMediaSessionProviderService(Context context) {
- mContext = context;
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- }
-}
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index ac55bfa..e4d3591 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -27,8 +27,8 @@
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<!-- Signature permission defined in NetworkStackStub -->
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
- <!-- Launch captive portal app as specific user -->
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <!-- Send latency broadcast as current user -->
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.NETWORK_STACK" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 0d6d080..2e72d82 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -500,7 +500,7 @@
private void showProvisioningNotification(String action) {
try {
- mCallback.showProvisioningNotification(action);
+ mCallback.showProvisioningNotification(action, mContext.getPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error showing provisioning notification", e);
}
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index d11bb64..b98b0f7 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -482,7 +482,7 @@
nm.notifyNetworkConnected();
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
- .showProvisioningNotification(any());
+ .showProvisioningNotification(any(), any());
// Check that startCaptivePortalApp sends the expected intent.
nm.launchCaptivePortalApp();
diff --git a/packages/SettingsLib/res/drawable/ic_system_update.xml b/packages/SettingsLib/res/drawable/ic_system_update.xml
new file mode 100644
index 0000000..3325fdd
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_system_update.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM16,12.5l-4,4l-4,-4l1.41,-1.41L11,12.67V8.5V8h2v0.5v4.17l1.59,-1.59L16,12.5z"/>
+</vector>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index d644833..f5d58d8 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -337,6 +337,9 @@
<string name="data_usage_uninstalled_apps">Removed apps</string>
<!-- Title of data usage item that represents all uninstalled applications or removed users. [CHAR LIMIT=48] -->
<string name="data_usage_uninstalled_apps_users">Removed apps and users</string>
+ <!-- Title of data usage item that represents system updates (OTAs). [CHAR LIMIT=48] -->
+ <string name="data_usage_ota">System updates</string>
+
<!-- Tethering controls, item title to go into the tethering settings -->
<!-- Tethering controls, item title to go into the tethering settings when only USB tethering is available [CHAR LIMIT=25]-->
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index c14f558..e351615 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -28,6 +28,7 @@
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.TrafficStats;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -111,7 +112,7 @@
// handle special case labels
switch (uid) {
- case android.os.Process.SYSTEM_UID:
+ case Process.SYSTEM_UID:
detail.label = res.getString(R.string.process_kernel_label);
detail.icon = pm.getDefaultActivityIcon();
return detail;
@@ -127,6 +128,10 @@
detail.label = res.getString(Utils.getTetheringLabel(cm));
detail.icon = pm.getDefaultActivityIcon();
return detail;
+ case Process.OTA_UPDATE_UID:
+ detail.label = res.getString(R.string.data_usage_ota);
+ detail.icon = mContext.getDrawable(R.drawable.ic_system_update);
+ return detail;
}
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
index 88adcdb..5c9a06f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
@@ -20,6 +20,7 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
public class ThreadUtils {
@@ -59,12 +60,14 @@
/**
* Posts runnable in background using shared background thread pool.
+ *
+ * @Return A future of the task that can be monitored for updates or cancelled.
*/
- public static void postOnBackgroundThread(Runnable runnable) {
+ public static Future postOnBackgroundThread(Runnable runnable) {
if (sSingleThreadExecutor == null) {
sSingleThreadExecutor = Executors.newSingleThreadExecutor();
}
- sSingleThreadExecutor.execute(runnable);
+ return sSingleThreadExecutor.submit(runnable);
}
/**
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 6152b8c..3caa139 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -718,6 +718,9 @@
dumpSetting(s, p,
Settings.Global.GAME_DRIVER_WHITELIST,
GlobalSettingsProto.Gpu.GAME_DRIVER_WHITELIST);
+ dumpSetting(s, p,
+ Settings.Global.GAME_DRIVER_BLACKLISTS,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS);
p.end(gpuToken);
final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e8c728d..0da3b10 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -82,6 +82,7 @@
<uses-permission android:name="android.permission.MOVE_PACKAGE" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
+ <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" />
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.MANAGE_ROLLBACKS" />
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 94481e7..5714556 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -64,6 +64,9 @@
charged, say that it is charged. -->
<string name="keyguard_charged">Fully charged</string>
+ <!-- When the lock screen is showing and the phone plugged in, and the battery is not fully charged, say that it's wirelessly charging. [CHAR LIMIT=50] -->
+ <string name="keyguard_plugged_in_wireless"><xliff:g id="percentage" example="20%">%s</xliff:g> • Wirelessly Charging</string>
+
<!-- When the lock screen is showing and the phone plugged in, and the battery
is not fully charged, say that it's charging. -->
<string name="keyguard_plugged_in"><xliff:g id="percentage">%s</xliff:g> • Charging</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index db92ed2..7d009b5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -955,6 +955,9 @@
<!-- Interruption level: Alarms only. Optimized for narrow two-line display. [CHAR LIMIT=40] -->
<string name="interruption_level_alarms_twoline">Alarms\nonly</string>
+ <!-- Indication on the keyguard that is shown when the device is wirelessly charging. [CHAR LIMIT=80]-->
+ <string name="keyguard_indication_charging_time_wireless"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Wirelessly Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
+
<!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=50]-->
<string name="keyguard_indication_charging_time"><xliff:g id="percentage">%2$s</xliff:g> • Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 82aa473..9c65994 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -79,6 +79,7 @@
private static final int MSG_RESIZE_IMMEDIATE = 1;
private static final int MSG_RESIZE_ANIMATE = 2;
+ private static final int MSG_OFFSET_ANIMATE = 3;
private Context mContext;
private IActivityManager mActivityManager;
@@ -360,9 +361,20 @@
/**
* Animates the PiP to offset it from the IME or shelf.
*/
- void animateToOffset(Rect toBounds) {
+ void animateToOffset(Rect originalBounds, int offset) {
cancelAnimations();
- resizeAndAnimatePipUnchecked(toBounds, SHIFT_DURATION);
+ adjustAndAnimatePipOffset(originalBounds, offset, SHIFT_DURATION);
+ }
+
+ private void adjustAndAnimatePipOffset(Rect originalBounds, int offset, int duration) {
+ if (offset == 0) {
+ return;
+ }
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = originalBounds;
+ args.argi1 = offset;
+ args.argi2 = duration;
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_OFFSET_ANIMATE, args));
}
/**
@@ -549,6 +561,31 @@
return true;
}
+ case MSG_OFFSET_ANIMATE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ Rect originalBounds = (Rect) args.arg1;
+ final int offset = args.argi1;
+ final int duration = args.argi2;
+ try {
+ StackInfo stackInfo = mActivityTaskManager.getStackInfo(
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ if (stackInfo == null) {
+ // In the case where we've already re-expanded or dismissed the PiP, then
+ // just skip the resize
+ return true;
+ }
+
+ mActivityTaskManager.offsetPinnedStackBounds(stackInfo.stackId, originalBounds,
+ 0/* xOffset */, offset, duration);
+ Rect toBounds = new Rect(originalBounds);
+ toBounds.offset(0, offset);
+ mBounds.set(toBounds);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not animate offset pinned stack with offset: " + offset, e);
+ }
+ return true;
+ }
+
default:
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 6a9f24c..cef1b6b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -346,12 +346,11 @@
}
private void animateToOffset(Rect animatingBounds, Rect toAdjustedBounds) {
- final Rect bounds = new Rect(animatingBounds);
- bounds.offset(0, toAdjustedBounds.bottom - bounds.top);
+ int offset = toAdjustedBounds.bottom - animatingBounds.top;
// In landscape mode, PIP window can go offset while launching IME. We want to align the
// the top of the PIP window with the top of the movement bounds in that case.
- bounds.offset(0, Math.max(0, mMovementBounds.top - bounds.top));
- mMotionHelper.animateToOffset(bounds);
+ offset += Math.max(0, mMovementBounds.top - animatingBounds.top);
+ mMotionHelper.animateToOffset(animatingBounds, offset);
}
private void onRegistrationChanged(boolean isRegistered) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index f054345..c43f572 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -54,6 +54,7 @@
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Arrays;
+import java.util.concurrent.Future;
public class PowerUI extends SystemUI {
static final String TAG = "PowerUI";
@@ -80,6 +81,7 @@
private Estimate mLastEstimate;
private boolean mLowWarningShownThisChargeCycle;
private boolean mSevereWarningShownThisChargeCycle;
+ private Future mLastShowWarningTask;
private int mLowBatteryAlertCloseLevel;
private final int[] mLowBatteryReminderLevels = new int[2];
@@ -247,7 +249,10 @@
}
// Show the correct version of low battery warning if needed
- ThreadUtils.postOnBackgroundThread(() -> {
+ if (mLastShowWarningTask != null) {
+ mLastShowWarningTask.cancel(true);
+ }
+ mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
maybeShowBatteryWarning(
oldBatteryLevel, plugged, oldPlugged, oldBucket, bucket);
});
@@ -276,7 +281,7 @@
estimate = mEnhancedEstimates.getEstimate();
mLastEstimate = estimate;
}
- // Turbo is not always booted once SysUI is running so we have ot make sure we actually
+ // Turbo is not always booted once SysUI is running so we have to make sure we actually
// get data back
if (estimate != null) {
mTimeRemaining = estimate.estimateMillis;
@@ -355,13 +360,26 @@
// Only show the low warning once per charge cycle & no battery saver
final boolean canShowWarning = !mLowWarningShownThisChargeCycle && !isPowerSaver
&& (timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
- || mBatteryLevel <= warnLevel);
+ || mBatteryLevel <= warnLevel);
// Only show the severe warning once per charge cycle
final boolean canShowSevereWarning = !mSevereWarningShownThisChargeCycle
&& (timeRemaining < mEnhancedEstimates.getSevereWarningThreshold()
- || mBatteryLevel <= critLevel);
+ || mBatteryLevel <= critLevel);
+ final boolean canShow = canShowWarning || canShowSevereWarning;
+ if (DEBUG) {
+ Slog.d(TAG, "Enhanced trigger is: " + canShow + "\nwith values: "
+ + " mLowWarningShownThisChargeCycle: " + mLowWarningShownThisChargeCycle
+ + " mSevereWarningShownThisChargeCycle: " + mSevereWarningShownThisChargeCycle
+ + " mEnhancedEstimates.timeremaining: " + timeRemaining
+ + " mBatteryLevel: " + mBatteryLevel
+ + " canShowWarning: " + canShowWarning
+ + " canShowSevereWarning: " + canShowSevereWarning
+ + " plugged: " + plugged
+ + " batteryStatus: " + batteryStatus
+ + " isPowerSaver: " + isPowerSaver);
+ }
return canShowWarning || canShowSevereWarning;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index be749ae..164f582 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -424,22 +424,28 @@
final boolean hasChargingTime = chargingTimeRemaining > 0;
int chargingId;
- switch (mChargingSpeed) {
- case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
- chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time_fast
- : R.string.keyguard_plugged_in_charging_fast;
- break;
- case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
- chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time_slowly
- : R.string.keyguard_plugged_in_charging_slowly;
- break;
- default:
- chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time
- : R.string.keyguard_plugged_in;
- break;
+ if (mPowerPluggedInWired) {
+ switch (mChargingSpeed) {
+ case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_fast
+ : R.string.keyguard_plugged_in_charging_fast;
+ break;
+ case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_slowly
+ : R.string.keyguard_plugged_in_charging_slowly;
+ break;
+ default:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time
+ : R.string.keyguard_plugged_in;
+ break;
+ }
+ } else {
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_wireless
+ : R.string.keyguard_plugged_in_wireless;
}
String percentage = NumberFormat.getPercentInstance()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index cad1a96..79bc0a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -521,6 +521,16 @@
verify(extender2).setShouldManageLifetime(mEntry, false);
}
+ /**
+ * Ensure that calling NotificationEntryManager.performRemoveNotification() doesn't crash when
+ * given a notification that has already been removed from NotificationData.
+ */
+ @Test
+ public void testPerformRemoveNotification_removedEntry() {
+ mEntryManager.getNotificationData().remove(mSbn.getKey(), null /* ranking */);
+ mEntryManager.performRemoveNotification(mSbn);
+ }
+
private Notification.Action createAction() {
return new Notification.Action.Builder(
Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 82359c5..ad0ed8b 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -518,6 +518,9 @@
// WifiConfigStore read/write metrics.
optional WifiConfigStoreIO wifi_config_store_io = 137;
+
+ // Total number of saved networks with mac randomization enabled.
+ optional int32 num_saved_networks_with_mac_randomization = 138;
}
// Information that gets logged for every WiFi connection.
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListing.java b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListingMap.java
similarity index 89%
rename from services/backup/java/com/android/server/backup/encryption/chunk/ChunkListing.java
rename to services/backup/java/com/android/server/backup/encryption/chunk/ChunkListingMap.java
index 2d2e88a..a448901 100644
--- a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListing.java
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListingMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 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.
@@ -11,13 +11,14 @@
* 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
+ * limitations under the License.
*/
package com.android.server.backup.encryption.chunk;
import android.annotation.Nullable;
import android.util.proto.ProtoInputStream;
+
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
@@ -30,16 +31,16 @@
* It can then tell the server to use that chunk, through telling it the position and length of the
* chunk in the previous backup's blob.
*/
-public class ChunkListing {
+public class ChunkListingMap {
/**
- * Reads a ChunkListing from a {@link ProtoInputStream}. Expects the message to be of format
+ * Reads a ChunkListingMap from a {@link ProtoInputStream}. Expects the message to be of format
* {@link ChunksMetadataProto.ChunkListing}.
*
* @param inputStream Currently at a {@link ChunksMetadataProto.ChunkListing} message.
* @throws IOException when the message is not structured as expected or a field can not be
* read.
*/
- public static ChunkListing readFromProto(ProtoInputStream inputStream) throws IOException {
+ public static ChunkListingMap readFromProto(ProtoInputStream inputStream) throws IOException {
Map<ChunkHash, Entry> entries = new HashMap();
long start = 0;
@@ -54,12 +55,12 @@
}
}
- return new ChunkListing(entries);
+ return new ChunkListingMap(entries);
}
private final Map<ChunkHash, Entry> mChunksByHash;
- private ChunkListing(Map<ChunkHash, Entry> chunksByHash) {
+ private ChunkListingMap(Map<ChunkHash, Entry> chunksByHash) {
mChunksByHash = Collections.unmodifiableMap(new HashMap<>(chunksByHash));
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index fe4411c..d1cd072 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -38,7 +38,6 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
-import static android.net.NetworkStack.NETWORKSTACK_PACKAGE_NAME;
import static android.net.shared.NetworkMonitorUtils.isValidationRequired;
import static android.net.shared.NetworkParcelableUtil.toStableParcelable;
import static android.os.Process.INVALID_UID;
@@ -2667,9 +2666,9 @@
}
@Override
- public void showProvisioningNotification(String action) {
+ public void showProvisioningNotification(String action, String packageName) {
final Intent intent = new Intent(action);
- intent.setPackage(NETWORKSTACK_PACKAGE_NAME);
+ intent.setPackage(packageName);
final PendingIntent pendingIntent;
// Only the system server can register notifications with package "android"
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 60a45bf..c4a9db6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6630,8 +6630,7 @@
String msg;
if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup "
- + cpr.name.flattenToShortString()
+ throw new SecurityException("Content provider lookup " + name
+ " failed: association not allowed with package " + msg);
}
checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 0194624..0bf5439 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -76,6 +76,7 @@
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class);
// add other global settings here...
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index a14fd17..19bdc09 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -96,6 +96,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -180,6 +181,7 @@
// into a single coherent structure.
private final HashSet<IpServer> mForwardedDownstreams;
private final VersionedBroadcastListener mCarrierConfigChange;
+ private final VersionedBroadcastListener mDefaultSubscriptionChange;
private final TetheringDependencies mDeps;
private final EntitlementManager mEntitlementMgr;
@@ -232,6 +234,15 @@
mEntitlementMgr.reevaluateSimCardProvisioning();
});
+ filter = new IntentFilter();
+ filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
+ mDefaultSubscriptionChange = new VersionedBroadcastListener(
+ "DefaultSubscriptionChangeListener", mContext, smHandler, filter,
+ (Intent ignored) -> {
+ mLog.log("OBSERVED default data subscription change");
+ updateConfiguration();
+ mEntitlementMgr.reevaluateSimCardProvisioning();
+ });
mStateReceiver = new StateReceiver();
// Load tethering configuration.
@@ -242,6 +253,7 @@
private void startStateMachineUpdaters() {
mCarrierConfigChange.startListening();
+ mDefaultSubscriptionChange.startListening();
final Handler handler = mTetherMasterSM.getHandler();
IntentFilter filter = new IntentFilter();
@@ -270,7 +282,8 @@
// NOTE: This is always invoked on the mLooper thread.
private void updateConfiguration() {
- mConfig = new TetheringConfiguration(mContext, mLog);
+ final int subId = mDeps.getDefaultDataSubscriptionId();
+ mConfig = new TetheringConfiguration(mContext, mLog, subId);
mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
mEntitlementMgr.updateConfiguration(mConfig);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 1e6bb04..8a46ff1 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -26,8 +26,8 @@
import static com.android.internal.R.array.config_mobile_hotspot_provision_app;
import static com.android.internal.R.array.config_tether_bluetooth_regexs;
import static com.android.internal.R.array.config_tether_dhcp_range;
-import static com.android.internal.R.array.config_tether_usb_regexs;
import static com.android.internal.R.array.config_tether_upstream_types;
+import static com.android.internal.R.array.config_tether_usb_regexs;
import static com.android.internal.R.array.config_tether_wifi_regexs;
import static com.android.internal.R.bool.config_tether_upstream_automatic;
import static com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui;
@@ -38,6 +38,7 @@
import android.net.ConnectivityManager;
import android.net.util.SharedLog;
import android.provider.Settings;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -100,29 +101,34 @@
public final String[] provisioningApp;
public final String provisioningAppNoUi;
- public TetheringConfiguration(Context ctx, SharedLog log) {
+ public final int subId;
+
+ public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
- tetherableUsbRegexs = getResourceStringArray(ctx, config_tether_usb_regexs);
+ subId = id;
+ Resources res = getResources(ctx, subId);
+
+ tetherableUsbRegexs = getResourceStringArray(res, config_tether_usb_regexs);
// TODO: Evaluate deleting this altogether now that Wi-Fi always passes
// us an interface name. Careful consideration needs to be given to
// implications for Settings and for provisioning checks.
- tetherableWifiRegexs = getResourceStringArray(ctx, config_tether_wifi_regexs);
- tetherableBluetoothRegexs = getResourceStringArray(ctx, config_tether_bluetooth_regexs);
+ tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
+ tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
dunCheck = checkDunRequired(ctx);
configLog.log("DUN check returned: " + dunCheckString(dunCheck));
- chooseUpstreamAutomatically = getResourceBoolean(ctx, config_tether_upstream_automatic);
- preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, dunCheck);
+ chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
+ preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, dunCheck);
isDunRequired = preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN);
- legacyDhcpRanges = getLegacyDhcpRanges(ctx);
+ legacyDhcpRanges = getLegacyDhcpRanges(res);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
enableLegacyDhcpServer = getEnableLegacyDhcpServer(ctx);
- provisioningApp = getResourceStringArray(ctx, config_mobile_hotspot_provision_app);
- provisioningAppNoUi = getProvisioningAppNoUi(ctx);
+ provisioningApp = getResourceStringArray(res, config_mobile_hotspot_provision_app);
+ provisioningAppNoUi = getProvisioningAppNoUi(res);
configLog.log(toString());
}
@@ -144,6 +150,9 @@
}
public void dump(PrintWriter pw) {
+ pw.print("subId: ");
+ pw.println(subId);
+
dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
@@ -169,6 +178,7 @@
public String toString() {
final StringJoiner sj = new StringJoiner(" ");
+ sj.add(String.format("subId:%d", subId));
sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
sj.add(String.format("tetherableBluetoothRegexs:%s",
@@ -235,8 +245,8 @@
}
}
- private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, int dunCheck) {
- final int ifaceTypes[] = ctx.getResources().getIntArray(config_tether_upstream_types);
+ private static Collection<Integer> getUpstreamIfaceTypes(Resources res, int dunCheck) {
+ final int[] ifaceTypes = res.getIntArray(config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
for (int i : ifaceTypes) {
switch (i) {
@@ -286,33 +296,33 @@
return false;
}
- private static String[] getLegacyDhcpRanges(Context ctx) {
- final String[] fromResource = getResourceStringArray(ctx, config_tether_dhcp_range);
+ private static String[] getLegacyDhcpRanges(Resources res) {
+ final String[] fromResource = getResourceStringArray(res, config_tether_dhcp_range);
if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) {
return fromResource;
}
return copy(LEGACY_DHCP_DEFAULT_RANGE);
}
- private static String getProvisioningAppNoUi(Context ctx) {
+ private static String getProvisioningAppNoUi(Resources res) {
try {
- return ctx.getResources().getString(config_mobile_hotspot_provision_app_no_ui);
+ return res.getString(config_mobile_hotspot_provision_app_no_ui);
} catch (Resources.NotFoundException e) {
return "";
}
}
- private static boolean getResourceBoolean(Context ctx, int resId) {
+ private static boolean getResourceBoolean(Resources res, int resId) {
try {
- return ctx.getResources().getBoolean(resId);
+ return res.getBoolean(resId);
} catch (Resources.NotFoundException e404) {
return false;
}
}
- private static String[] getResourceStringArray(Context ctx, int resId) {
+ private static String[] getResourceStringArray(Resources res, int resId) {
try {
- final String[] strArray = ctx.getResources().getStringArray(resId);
+ final String[] strArray = res.getStringArray(resId);
return (strArray != null) ? strArray : EMPTY_STRING_ARRAY;
} catch (Resources.NotFoundException e404) {
return EMPTY_STRING_ARRAY;
@@ -325,6 +335,19 @@
return intVal != 0;
}
+ private Resources getResources(Context ctx, int subId) {
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return getResourcesForSubIdWrapper(ctx, subId);
+ } else {
+ return ctx.getResources();
+ }
+ }
+
+ @VisibleForTesting
+ protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
+ return SubscriptionManager.getResourcesForSubId(ctx, subId);
+ }
+
private static String[] copy(String[] strarray) {
return Arrays.copyOf(strarray, strarray.length);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
index 6d6f81e..3fddac1 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -21,6 +21,7 @@
import android.net.ip.IpServer;
import android.net.util.SharedLog;
import android.os.Handler;
+import android.telephony.SubscriptionManager;
import com.android.internal.util.StateMachine;
import com.android.server.connectivity.MockableSystemProperties;
@@ -85,4 +86,11 @@
SharedLog log, MockableSystemProperties systemProperties) {
return new EntitlementManager(ctx, target, log, systemProperties);
}
+
+ /**
+ * Get default data subscription id to build TetheringConfiguration.
+ */
+ public int getDefaultDataSubscriptionId() {
+ return SubscriptionManager.getDefaultDataSubscriptionId();
+ }
}
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 7ae00af..b9aa34e8 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.util.Slog;
+import android.util.Spline;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
@@ -75,6 +76,9 @@
// Override the ambient color temperature for debugging purposes.
private float mAmbientColorTemperatureOverride;
+ // A piecewise linear relationship between ambient and display color temperatures
+ private Spline.LinearSpline mAmbientToDisplayTemperatureSpline;
+
/**
* @param brightnessSensor
* The sensor used to detect changes in the ambient brightness.
@@ -109,7 +113,8 @@
@NonNull AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
@NonNull AmbientFilter colorTemperatureFilter,
@NonNull DisplayWhiteBalanceThrottler throttler,
- float lowLightAmbientBrightnessThreshold, float lowLightAmbientColorTemperature) {
+ float lowLightAmbientBrightnessThreshold, float lowLightAmbientColorTemperature,
+ float[] ambientTemperatures, float[] displayTemperatures) {
validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
colorTemperatureFilter, throttler);
mLoggingEnabled = false;
@@ -127,6 +132,14 @@
mLastAmbientColorTemperature = -1.0f;
mAmbientColorTemperatureHistory = new History(HISTORY_SIZE);
mAmbientColorTemperatureOverride = -1.0f;
+
+ try {
+ mAmbientToDisplayTemperatureSpline = new Spline.LinearSpline(ambientTemperatures,
+ displayTemperatures);
+ } catch (Exception e) {
+ mAmbientToDisplayTemperatureSpline = null;
+ }
+
mColorDisplayServiceInternal = LocalServices.getService(ColorDisplayServiceInternal.class);
}
@@ -227,6 +240,9 @@
writer.println(" mLastAmbientColorTemperature=" + mLastAmbientColorTemperature);
writer.println(" mAmbientColorTemperatureHistory=" + mAmbientColorTemperatureHistory);
writer.println(" mAmbientColorTemperatureOverride=" + mAmbientColorTemperatureOverride);
+ writer.println(" mAmbientToDisplayTemperatureSpline="
+ + (mAmbientToDisplayTemperatureSpline == null ? "unused" :
+ mAmbientToDisplayTemperatureSpline));
}
@Override // AmbientSensor.AmbientBrightnessSensor.Callbacks
@@ -250,6 +266,11 @@
final long time = System.currentTimeMillis();
float ambientColorTemperature = mColorTemperatureFilter.getEstimate(time);
+ if (mAmbientToDisplayTemperatureSpline != null) {
+ ambientColorTemperature =
+ mAmbientToDisplayTemperatureSpline.interpolate(ambientColorTemperature);
+ }
+
final float ambientBrightness = mBrightnessFilter.getEstimate(time);
if (ambientBrightness < mLowLightAmbientBrightnessThreshold) {
if (mLoggingEnabled) {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index fd78ddb..56f4ca3 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -67,9 +67,14 @@
final float lowLightAmbientColorTemperature = getFloat(resources,
com.android.internal.R.dimen
.config_displayWhiteBalanceLowLightAmbientColorTemperature);
+ final float[] ambientTemperatures = getFloatArray(resources,
+ com.android.internal.R.array.config_displayWhiteBalanceAmbientTemperatureValues);
+ final float[] displayTemperatures = getFloatArray(resources,
+ com.android.internal.R.array.config_displayWhiteBalanceDisplayTemperatureValues);
final DisplayWhiteBalanceController controller = new DisplayWhiteBalanceController(
brightnessSensor, brightnessFilter, colorTemperatureSensor, colorTemperatureFilter,
- throttler, lowLightAmbientBrightnessThreshold, lowLightAmbientColorTemperature);
+ throttler, lowLightAmbientBrightnessThreshold, lowLightAmbientColorTemperature,
+ ambientTemperatures, displayTemperatures);
brightnessSensor.setCallbacks(controller);
colorTemperatureSensor.setCallbacks(controller);
return controller;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 144f2b6..96ba084 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -667,13 +667,19 @@
final int mSequenceNumber;
final long mTimestamp;
final long mWallTime;
+ @UserIdInt
+ final int mImeUserId;
@NonNull
final IBinder mImeToken;
+ final int mImeDisplayId;
@NonNull
final String mImeId;
@StartInputReason
final int mStartInputReason;
final boolean mRestarting;
+ @UserIdInt
+ final int mTargetUserId;
+ final int mTargetDisplayId;
@Nullable
final IBinder mTargetWindow;
@NonNull
@@ -682,17 +688,22 @@
final int mTargetWindowSoftInputMode;
final int mClientBindSequenceNumber;
- StartInputInfo(@NonNull IBinder imeToken, @NonNull String imeId,
- @StartInputReason int startInputReason, boolean restarting,
- @Nullable IBinder targetWindow, @NonNull EditorInfo editorInfo,
- @SoftInputModeFlags int targetWindowSoftInputMode, int clientBindSequenceNumber) {
+ StartInputInfo(@UserIdInt int imeUserId, @NonNull IBinder imeToken, int imeDisplayId,
+ @NonNull String imeId, @StartInputReason int startInputReason, boolean restarting,
+ @UserIdInt int targetUserId, int targetDisplayId, @Nullable IBinder targetWindow,
+ @NonNull EditorInfo editorInfo, @SoftInputModeFlags int targetWindowSoftInputMode,
+ int clientBindSequenceNumber) {
mSequenceNumber = sSequenceNumber.getAndIncrement();
mTimestamp = SystemClock.uptimeMillis();
mWallTime = System.currentTimeMillis();
+ mImeUserId = imeUserId;
mImeToken = imeToken;
+ mImeDisplayId = imeDisplayId;
mImeId = imeId;
mStartInputReason = startInputReason;
mRestarting = restarting;
+ mTargetUserId = targetUserId;
+ mTargetDisplayId = targetDisplayId;
mTargetWindow = targetWindow;
mEditorInfo = editorInfo;
mTargetWindowSoftInputMode = targetWindowSoftInputMode;
@@ -749,13 +760,19 @@
int mSequenceNumber;
long mTimestamp;
long mWallTime;
+ @UserIdInt
+ int mImeUserId;
@NonNull
String mImeTokenString;
+ int mImeDisplayId;
@NonNull
String mImeId;
@StartInputReason
int mStartInputReason;
boolean mRestarting;
+ @UserIdInt
+ int mTargetUserId;
+ int mTargetDisplayId;
@NonNull
String mTargetWindowString;
@NonNull
@@ -772,12 +789,16 @@
mSequenceNumber = original.mSequenceNumber;
mTimestamp = original.mTimestamp;
mWallTime = original.mWallTime;
+ mImeUserId = original.mImeUserId;
// Intentionally convert to String so as not to keep a strong reference to a Binder
// object.
mImeTokenString = String.valueOf(original.mImeToken);
+ mImeDisplayId = original.mImeDisplayId;
mImeId = original.mImeId;
mStartInputReason = original.mStartInputReason;
mRestarting = original.mRestarting;
+ mTargetUserId = original.mTargetUserId;
+ mTargetDisplayId = original.mTargetDisplayId;
// Intentionally convert to String so as not to keep a strong reference to a Binder
// object.
mTargetWindowString = String.valueOf(original.mTargetWindow);
@@ -821,11 +842,15 @@
+ " restarting=" + entry.mRestarting);
pw.print(prefix);
- pw.println(" imeToken=" + entry.mImeTokenString + " [" + entry.mImeId + "]");
+ pw.print(" imeToken=" + entry.mImeTokenString + " [" + entry.mImeId + "]");
+ pw.print(" imeUserId=" + entry.mImeUserId);
+ pw.println(" imeDisplayId=" + entry.mImeDisplayId);
pw.print(prefix);
pw.println(" targetWin=" + entry.mTargetWindowString
+ " [" + entry.mEditorInfo.packageName + "]"
+ + " targetUserId=" + entry.mTargetUserId
+ + " targetDisplayId=" + entry.mTargetDisplayId
+ " clientBindSeq=" + entry.mClientBindSequenceNumber);
pw.print(prefix);
@@ -1904,9 +1929,10 @@
}
final Binder startInputToken = new Binder();
- final StartInputInfo info = new StartInputInfo(mCurToken, mCurId, startInputReason,
- !initial, mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode,
- mCurSeq);
+ final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(), mCurToken,
+ mCurTokenDisplayId, mCurId, startInputReason, !initial,
+ UserHandle.getUserId(mCurClient.uid), mCurClient.selfReportedDisplayId,
+ mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode, mCurSeq);
mImeTargetWindowMap.put(startInputToken, mCurFocusedWindow);
mStartInputHistory.addEntry(info);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 21965e4..f6bd2a9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -481,6 +481,10 @@
}
}
+ if (params.isStaged) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);
+ }
+
if (!params.isMultiPackage) {
// Only system components can circumvent runtime permissions when installing.
if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index bfa539c..2036ed7 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -645,7 +645,7 @@
grantPermissionsToSystemPackage(packageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
- SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
+ SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(packageName, userId,
LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4faf910..0251efb 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -75,12 +75,12 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
@@ -2610,10 +2610,6 @@
}
}
- int getRequestedOrientation() {
- return getOrientation();
- }
-
void setRequestedOrientation(int requestedOrientation) {
setOrientation(requestedOrientation, mayFreezeScreenLocked(app));
mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
@@ -2641,7 +2637,7 @@
int getOrientation() {
if (mAppWindowToken == null) {
- return SCREEN_ORIENTATION_UNSPECIFIED;
+ return info.screenOrientation;
}
return mAppWindowToken.getOrientationIgnoreVisibility();
@@ -2677,25 +2673,92 @@
mLastReportedConfiguration.setConfiguration(global, override);
}
+ /**
+ * Get the configuration orientation by the requested screen orientation
+ * ({@link ActivityInfo.ScreenOrientation}) of this activity.
+ *
+ * @return orientation in ({@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT},
+ * {@link #ORIENTATION_UNDEFINED}).
+ */
+ int getRequestedConfigurationOrientation() {
+ final int screenOrientation = getOrientation();
+ if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+ // NOSENSOR means the display's "natural" orientation, so return that.
+ final ActivityDisplay display = getDisplay();
+ if (display != null && display.mDisplayContent != null) {
+ return display.mDisplayContent.getNaturalOrientation();
+ }
+ } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+ // LOCKED means the activity's orientation remains unchanged, so return existing value.
+ return getConfiguration().orientation;
+ } else if (isFixedOrientationLandscape(screenOrientation)) {
+ return ORIENTATION_LANDSCAPE;
+ } else if (isFixedOrientationPortrait(screenOrientation)) {
+ return ORIENTATION_PORTRAIT;
+ }
+ return ORIENTATION_UNDEFINED;
+ }
+
+ /**
+ * Indicates the activity will keep the bounds and screen configuration when it was first
+ * launched, no matter how its parent changes.
+ *
+ * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
+ * aspect ratio.
+ */
+ private boolean inSizeCompatMode() {
+ return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
+ // The configuration of non-standard type should be enforced by system.
+ && isActivityTypeStandard()
+ && !mAtmService.mForceResizableActivities;
+ }
+
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void updateOverrideConfiguration() {
+ final boolean inSizeCompatMode = inSizeCompatMode();
+ if (inSizeCompatMode) {
+ if (!matchParentBounds()) {
+ // The override configuration is set only once in size compatible mode.
+ return;
+ }
+ if (!hasProcess() && !isConfigurationCompatible(task.getConfiguration())) {
+ // Don't compute when launching in fullscreen and the fixed orientation is not the
+ // current orientation. It is more accurately to compute the override bounds from
+ // the updated configuration after the fixed orientation is applied.
+ return;
+ }
+ }
+
computeBounds(mTmpBounds);
+ if (inSizeCompatMode && mTmpBounds.isEmpty()) {
+ mTmpBounds.set(task.getWindowConfiguration().getBounds());
+ }
if (mTmpBounds.equals(getRequestedOverrideBounds())) {
+ // The bounds is not changed or the activity is resizable (both the 2 bounds are empty).
return;
}
- setBounds(mTmpBounds);
-
- // Bounds changed...update configuration to match.
- if (!matchParentBounds()) {
- mTmpConfig.setTo(getRequestedOverrideConfiguration());
- task.computeConfigResourceOverrides(mTmpConfig, task.getParent().getConfiguration());
- } else {
- mTmpConfig.unset();
+ final Configuration overrideConfig = mTmpConfig;
+ overrideConfig.unset();
+ if (!mTmpBounds.isEmpty()) {
+ overrideConfig.windowConfiguration.setBounds(mTmpBounds);
+ if (inSizeCompatMode) {
+ // Ensure the screen related fields are set. It is used to prevent activity relaunch
+ // when moving between displays. For screenWidthDp and screenWidthDp, because they
+ // are relative to bounds and density, they will be calculated in
+ // {@link TaskRecord#computeConfigResourceOverrides} and the result will also be
+ // relatively fixed.
+ final Configuration srcConfig = task.getConfiguration();
+ overrideConfig.colorMode = srcConfig.colorMode;
+ overrideConfig.densityDpi = srcConfig.densityDpi;
+ overrideConfig.screenLayout = srcConfig.screenLayout;
+ // The smallest screen width is the short side of screen bounds. Because the bounds
+ // and density won't be changed, smallestScreenWidthDp is also fixed.
+ overrideConfig.smallestScreenWidthDp = srcConfig.smallestScreenWidthDp;
+ }
}
-
- onRequestedOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(overrideConfig);
}
@Override
@@ -2707,6 +2770,86 @@
// layout traversals.
mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
getResolvedOverrideConfiguration().seq = mConfigurationSeq;
+
+ if (matchParentBounds()) {
+ return;
+ }
+
+ final Configuration resolvedConfig = getResolvedOverrideConfiguration();
+ if (!inSizeCompatMode()) {
+ computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
+ ORIENTATION_UNDEFINED, true /* insideParentBounds */);
+ return;
+ }
+
+ final Configuration displayConfig = getDisplay().getConfiguration();
+ int orientation = getConfiguration().orientation;
+ if (orientation != displayConfig.orientation && isConfigurationCompatible(displayConfig)) {
+ // The activity is compatible to apply the orientation change or it requests different
+ // fixed orientation.
+ orientation = displayConfig.orientation;
+ } else {
+ if (resolvedConfig.windowConfiguration.getAppBounds() != null) {
+ // Keep the computed resolved override configuration.
+ return;
+ }
+ final int requestedOrientation = getRequestedConfigurationOrientation();
+ if (requestedOrientation != ORIENTATION_UNDEFINED) {
+ orientation = requestedOrientation;
+ }
+ }
+
+ // Adjust the bounds to match the current orientation.
+ if (orientation != ORIENTATION_UNDEFINED) {
+ final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
+ final int longSide = Math.max(resolvedBounds.height(), resolvedBounds.width());
+ final int shortSide = Math.min(resolvedBounds.height(), resolvedBounds.width());
+ final boolean toBeLandscape = orientation == ORIENTATION_LANDSCAPE;
+ final int width = toBeLandscape ? longSide : shortSide;
+ final int height = toBeLandscape ? shortSide : longSide;
+ // Assume the bounds is always started from zero because the size may be bigger than its
+ // parent (task ~ display). The actual letterboxing will be done by surface offset.
+ resolvedBounds.set(0, 0, width, height);
+ }
+
+ // In size compatible mode, activity is allowed to have larger bounds than its parent.
+ computeConfigResourceOverrides(resolvedConfig, newParentConfiguration, orientation,
+ false /* insideParentBounds */);
+ }
+
+ private void computeConfigResourceOverrides(Configuration inOutConfig,
+ Configuration parentConfig, int orientation, boolean insideParentBounds) {
+ // Set the real orientation or undefined value to ensure the output orientation won't be the
+ // old value. Also reset app bounds so it will be updated according to bounds.
+ inOutConfig.orientation = orientation;
+ final Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
+ if (outAppBounds != null) {
+ outAppBounds.setEmpty();
+ }
+
+ // TODO(b/112288258): Remove below calculation because the position information in bounds
+ // will be replaced by the offset of surface.
+ final Rect appBounds = parentConfig.windowConfiguration.getAppBounds();
+ if (appBounds != null) {
+ final Rect outBounds = inOutConfig.windowConfiguration.getBounds();
+ final int activityWidth = outBounds.width();
+ final int navBarPosition = mAtmService.mWindowManager.getNavBarPosition(getDisplayId());
+ if (navBarPosition == NAV_BAR_LEFT) {
+ // Position the activity frame on the opposite side of the nav bar.
+ outBounds.left = appBounds.right - activityWidth;
+ outBounds.right = appBounds.right;
+ } else if (navBarPosition == NAV_BAR_RIGHT) {
+ // Position the activity frame on the opposite side of the nav bar.
+ outBounds.left = 0;
+ outBounds.right = activityWidth + appBounds.left;
+ } else if (appBounds.width() > activityWidth) {
+ // Horizontally center the frame.
+ outBounds.left = appBounds.left + (appBounds.width() - activityWidth) / 2;
+ outBounds.right = outBounds.left + activityWidth;
+ }
+ }
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig, insideParentBounds);
}
@Override
@@ -2739,8 +2882,7 @@
/** Returns true if the configuration is compatible with this activity. */
boolean isConfigurationCompatible(Configuration config) {
- final int orientation = mAppWindowToken != null
- ? getOrientation() : info.screenOrientation;
+ final int orientation = getOrientation();
if (isFixedOrientationPortrait(orientation)
&& config.orientation != ORIENTATION_PORTRAIT) {
return false;
@@ -2822,21 +2964,6 @@
// away later in StackWindowController.adjustConfigurationForBounds(). Otherwise, the app
// bounds would end up too small.
outBounds.set(0, 0, activityWidth + appBounds.left, activityHeight + appBounds.top);
-
- final int navBarPosition = mAtmService.mWindowManager.getNavBarPosition(getDisplayId());
- if (navBarPosition == NAV_BAR_LEFT) {
- // Position the activity frame on the opposite side of the nav bar.
- outBounds.left = appBounds.right - activityWidth;
- outBounds.right = appBounds.right;
- } else if (navBarPosition == NAV_BAR_RIGHT) {
- // Position the activity frame on the opposite side of the nav bar.
- outBounds.left = 0;
- outBounds.right = activityWidth + appBounds.left;
- } else {
- // Horizontally center the frame.
- outBounds.left = appBounds.left + (containingAppWidth - activityWidth) / 2;
- outBounds.right = outBounds.left + activityWidth;
- }
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index cc78588..932cfd3 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -5631,6 +5631,19 @@
}
}
+ /**
+ * Get current bounds of this stack, return empty when it is unavailable.
+ * @see TaskStack#getAnimationOrCurrentBounds(Rect)
+ */
+ void getAnimationOrCurrentBounds(Rect outBounds) {
+ final TaskStack stack = getTaskStack();
+ if (stack == null) {
+ outBounds.setEmpty();
+ return;
+ }
+ stack.getAnimationOrCurrentBounds(outBounds);
+ }
+
private boolean skipResizeAnimation(boolean toFullscreen) {
if (!toFullscreen) {
return false;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 678a896..c33a2c1 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -989,8 +989,8 @@
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
return false;
}
- // don't abort if the callingPackage is a device owner
- if (mService.getDevicePolicyManager().isDeviceOwnerApp(callingPackage)) {
+ // don't abort if the callingPackage is the device owner
+ if (mService.isDeviceOwner(callingPackage)) {
return false;
}
// anything that has fallen through would currently be aborted
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 1a5e6a1..5a20959 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -492,4 +492,9 @@
/** Returns true if uid has a visible window or its process is in a top state. */
public abstract boolean isUidForeground(int uid);
+
+ /**
+ * Called by DevicePolicyManagerService to set the package name of the device owner.
+ */
+ public abstract void setDeviceOwnerPackageName(String deviceOwnerPkg);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 875fc4e..258819f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -151,7 +151,6 @@
import android.app.WaitResult;
import android.app.WindowConfiguration;
import android.app.admin.DevicePolicyCache;
-import android.app.admin.DevicePolicyManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.usage.UsageStatsManagerInternal;
@@ -363,7 +362,6 @@
WindowManagerService mWindowManager;
private UserManagerService mUserManager;
private AppOpsService mAppOpsService;
- private DevicePolicyManager mDpm;
/** All active uids in the system. */
private final SparseArray<Integer> mActiveUids = new SparseArray<>();
private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
@@ -623,6 +621,8 @@
private FontScaleSettingObserver mFontScaleSettingObserver;
+ private String mDeviceOwnerPackageName;
+
private final class FontScaleSettingObserver extends ContentObserver {
private final Uri mFontScaleUri = Settings.System.getUriFor(FONT_SCALE);
private final Uri mHideErrorDialogsUri = Settings.Global.getUriFor(HIDE_ERROR_DIALOGS);
@@ -838,13 +838,6 @@
return mAppOpsService;
}
- DevicePolicyManager getDevicePolicyManager() {
- if (mDpm == null) {
- mDpm = mContext.getSystemService(DevicePolicyManager.class);
- }
- return mDpm;
- }
-
boolean hasUserRestriction(String restriction, int userId) {
return getUserManager().hasUserRestriction(restriction, userId);
}
@@ -1720,7 +1713,7 @@
if (r == null) {
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
- return r.getRequestedOrientation();
+ return r.getOrientation();
}
}
@@ -2452,6 +2445,40 @@
}
}
+ @Override
+ public void offsetPinnedStackBounds(int stackId, Rect compareBounds, int xOffset, int yOffset,
+ int animationDuration) {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "offsetPinnedStackBounds()");
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ if (xOffset == 0 && yOffset == 0) {
+ return;
+ }
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ if (stack == null) {
+ Slog.w(TAG, "offsetPinnedStackBounds: stackId " + stackId + " not found.");
+ return;
+ }
+ if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
+ throw new IllegalArgumentException("Stack: " + stackId
+ + " doesn't support animated resize.");
+ }
+ final Rect destBounds = new Rect();
+ stack.getAnimationOrCurrentBounds(destBounds);
+ if (!destBounds.isEmpty() || !destBounds.equals(compareBounds)) {
+ Slog.w(TAG, "The current stack bounds does not matched! It may be obsolete.");
+ return;
+ }
+ destBounds.offset(xOffset, yOffset);
+ stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
+ animationDuration, false /* fromFullscreen */);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
/**
* Moves the specified task to the primary-split-screen stack.
*
@@ -5691,6 +5718,17 @@
|| mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
}
+ boolean isDeviceOwner(String packageName) {
+ if (packageName == null) {
+ return false;
+ }
+ return packageName.equals(mDeviceOwnerPackageName);
+ }
+
+ void setDeviceOwnerPackageName(String deviceOwnerPkg) {
+ mDeviceOwnerPackageName = deviceOwnerPkg;
+ }
+
/**
* @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on
* the whitelist
@@ -7108,5 +7146,12 @@
return ActivityTaskManagerService.this.isUidForeground(uid);
}
}
+
+ @Override
+ public void setDeviceOwnerPackageName(String deviceOwnerPkg) {
+ synchronized (mGlobalLock) {
+ ActivityTaskManagerService.this.setDeviceOwnerPackageName(deviceOwnerPkg);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index bcf6aba..88c8b95 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -239,6 +239,17 @@
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
+ /**
+ * The scale to fit at least one side of the activity to its parent. If the activity uses
+ * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
+ */
+ private float mSizeCompatScale = 1f;
+ /**
+ * The bounds in global coordinates for activity in size compatibility mode.
+ * @see ActivityRecord#inSizeCompatMode
+ */
+ private Rect mSizeCompatBounds;
+
private boolean mDisablePreviewScreenshots;
private Task mLastParent;
@@ -884,6 +895,10 @@
dc.setFocusedApp(null);
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
}
+ if (mLetterbox != null) {
+ mLetterbox.destroy();
+ mLetterbox = null;
+ }
if (!delayed) {
updateReportedVisibilityLocked();
@@ -1297,6 +1312,10 @@
}
}
}
+
+ if (prevDc != mDisplayContent && mLetterbox != null) {
+ mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
+ }
}
/**
@@ -1555,11 +1574,52 @@
return mOrientation;
}
+ /** @return {@code true} if the compatibility bounds is taking effect. */
+ boolean inSizeCompatMode() {
+ return mSizeCompatBounds != null;
+ }
+
+ @Override
+ float getSizeCompatScale() {
+ return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
+ }
+
+ /**
+ * @return Non-empty bounds if the activity has override bounds.
+ * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
+ */
+ Rect getResolvedOverrideBounds() {
+ // Get bounds from resolved override configuration because it is computed with orientation.
+ return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
+ }
+
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWinMode = getWindowingMode();
mTmpPrevBounds.set(getBounds());
super.onConfigurationChanged(newParentConfig);
+
+ final Task task = getTask();
+ final Rect overrideBounds = getResolvedOverrideBounds();
+ if (task != null && !overrideBounds.isEmpty()
+ // If the changes come from change-listener, the incoming parent configuration is
+ // still the old one. Make sure their orientations are the same to reduce computing
+ // the compatibility bounds for the intermediate state.
+ && getResolvedOverrideConfiguration().orientation == newParentConfig.orientation) {
+ final Rect taskBounds = task.getBounds();
+ // Since we only center the activity horizontally, if only the fixed height is smaller
+ // than its container, the override bounds don't need to take effect.
+ if ((overrideBounds.width() != taskBounds.width()
+ || overrideBounds.height() > taskBounds.height())) {
+ calculateCompatBoundsTransformation(newParentConfig);
+ updateSurfacePosition();
+ } else if (mSizeCompatBounds != null) {
+ mSizeCompatBounds = null;
+ mSizeCompatScale = 1f;
+ updateSurfacePosition();
+ }
+ }
+
final int winMode = getWindowingMode();
if (prevWinMode == winMode) {
@@ -1657,8 +1717,10 @@
final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
false /* reducedResolution */);
- mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
- true /* relative */);
+ if (snapshot != null) {
+ mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
+ true /* relative */);
+ }
}
}
@@ -1671,6 +1733,54 @@
return mThumbnail;
}
+ /**
+ * Calculates the scale and offset to horizontal center the size compatibility bounds into the
+ * region which is available to application.
+ */
+ private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
+ final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
+ final Rect viewportBounds = parentAppBounds != null
+ ? parentAppBounds : newParentConfig.windowConfiguration.getBounds();
+ final Rect contentBounds = getResolvedOverrideBounds();
+ final float contentW = contentBounds.width();
+ final float contentH = contentBounds.height();
+ final float viewportW = viewportBounds.width();
+ final float viewportH = viewportBounds.height();
+ // Only allow to scale down.
+ mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
+ ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
+ final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
+ + viewportBounds.left;
+
+ if (mSizeCompatBounds == null) {
+ mSizeCompatBounds = new Rect();
+ }
+ mSizeCompatBounds.set(contentBounds);
+ mSizeCompatBounds.offsetTo(0, 0);
+ mSizeCompatBounds.scale(mSizeCompatScale);
+ mSizeCompatBounds.left += offsetX;
+ mSizeCompatBounds.right += offsetX;
+ }
+
+ @Override
+ public Rect getBounds() {
+ if (mSizeCompatBounds != null) {
+ return mSizeCompatBounds;
+ }
+ return super.getBounds();
+ }
+
+ @Override
+ public boolean matchParentBounds() {
+ if (super.matchParentBounds()) {
+ return true;
+ }
+ // An activity in size compatibility mode may have override bounds which equals to its
+ // parent bounds, so the exact bounds should also be checked.
+ final WindowContainer parent = getParent();
+ return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
+ }
+
@Override
void checkAppWindowsReadyToShow() {
if (allDrawn == mLastAllDrawn) {
@@ -1844,6 +1954,7 @@
if (needsLetterbox) {
if (mLetterbox == null) {
mLetterbox = new Letterbox(() -> makeChildSurface(null));
+ mLetterbox.attachInput(w);
}
getPosition(mTmpPoint);
mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
@@ -2864,6 +2975,10 @@
if (mPendingRelaunchCount != 0) {
pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
}
+ if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
+ pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
+ + mSizeCompatBounds);
+ }
if (mRemovingFromDisplay) {
pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 9874920..d67193e 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -20,7 +20,15 @@
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Process;
+import android.view.InputChannel;
+import android.view.InputEventReceiver;
+import android.view.InputWindowHandle;
import android.view.SurfaceControl;
+import android.view.WindowManager;
+
+import com.android.server.UiThread;
import java.util.function.Supplier;
@@ -40,6 +48,7 @@
private final LetterboxSurface mLeft = new LetterboxSurface("left");
private final LetterboxSurface mBottom = new LetterboxSurface("bottom");
private final LetterboxSurface mRight = new LetterboxSurface("right");
+ private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom };
/**
* Constructs a Letterbox.
@@ -87,8 +96,12 @@
* Returns true if any part of the letterbox overlaps with the given {@code rect}.
*/
public boolean isOverlappingWith(Rect rect) {
- return mTop.isOverlappingWith(rect) || mLeft.isOverlappingWith(rect)
- || mBottom.isOverlappingWith(rect) || mRight.isOverlappingWith(rect);
+ for (LetterboxSurface surface : mSurfaces) {
+ if (surface.isOverlappingWith(rect)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -107,25 +120,94 @@
mOuter.setEmpty();
mInner.setEmpty();
- mTop.remove();
- mLeft.remove();
- mBottom.remove();
- mRight.remove();
+ for (LetterboxSurface surface : mSurfaces) {
+ surface.remove();
+ }
}
/** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */
public boolean needsApplySurfaceChanges() {
- return mTop.needsApplySurfaceChanges()
- || mLeft.needsApplySurfaceChanges()
- || mBottom.needsApplySurfaceChanges()
- || mRight.needsApplySurfaceChanges();
+ for (LetterboxSurface surface : mSurfaces) {
+ if (surface.needsApplySurfaceChanges()) {
+ return true;
+ }
+ }
+ return false;
}
public void applySurfaceChanges(SurfaceControl.Transaction t) {
- mTop.applySurfaceChanges(t);
- mLeft.applySurfaceChanges(t);
- mBottom.applySurfaceChanges(t);
- mRight.applySurfaceChanges(t);
+ for (LetterboxSurface surface : mSurfaces) {
+ surface.applySurfaceChanges(t);
+ }
+ }
+
+ /** Enables touches to slide into other neighboring surfaces. */
+ void attachInput(WindowState win) {
+ for (LetterboxSurface surface : mSurfaces) {
+ surface.attachInput(win);
+ }
+ }
+
+ void onMovedToDisplay(int displayId) {
+ for (LetterboxSurface surface : mSurfaces) {
+ if (surface.mInputInterceptor != null) {
+ surface.mInputInterceptor.mWindowHandle.displayId = displayId;
+ }
+ }
+ }
+
+ private static class InputInterceptor {
+ final InputChannel mServerChannel;
+ final InputChannel mClientChannel;
+ final InputWindowHandle mWindowHandle;
+ final InputEventReceiver mInputEventReceiver;
+ final WindowManagerService mWmService;
+
+ InputInterceptor(String namePrefix, WindowState win) {
+ mWmService = win.mWmService;
+ final String name = namePrefix + (win.mAppToken != null ? win.mAppToken : win);
+ final InputChannel[] channels = InputChannel.openInputChannelPair(name);
+ mServerChannel = channels[0];
+ mClientChannel = channels[1];
+ mInputEventReceiver = new SimpleInputReceiver(mClientChannel);
+
+ final Binder token = new Binder();
+ mWmService.mInputManager.registerInputChannel(mServerChannel, token);
+
+ mWindowHandle = new InputWindowHandle(null /* inputApplicationHandle */,
+ null /* clientWindow */, win.getDisplayId());
+ mWindowHandle.name = name;
+ mWindowHandle.token = token;
+ mWindowHandle.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_SLIPPERY;
+ mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
+ mWindowHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ mWindowHandle.visible = true;
+ mWindowHandle.ownerPid = Process.myPid();
+ mWindowHandle.ownerUid = Process.myUid();
+ mWindowHandle.scaleFactor = 1.0f;
+ }
+
+ void updateTouchableRegion(Rect frame) {
+ mWindowHandle.touchableRegion.set(frame);
+ mWindowHandle.touchableRegion.translate(-frame.left, -frame.top);
+ }
+
+ void dispose() {
+ mWmService.mInputManager.unregisterInputChannel(mServerChannel);
+ mInputEventReceiver.dispose();
+ mServerChannel.dispose();
+ mClientChannel.dispose();
+ }
+
+ private static class SimpleInputReceiver extends InputEventReceiver {
+ SimpleInputReceiver(InputChannel inputChannel) {
+ super(inputChannel, UiThread.getHandler().getLooper());
+ }
+ }
}
private class LetterboxSurface {
@@ -137,6 +219,8 @@
private final Rect mLayoutFrameGlobal = new Rect();
private final Rect mLayoutFrameRelative = new Rect();
+ private InputInterceptor mInputInterceptor;
+
public LetterboxSurface(String type) {
mType = type;
}
@@ -154,11 +238,22 @@
mSurface.setColor(new float[]{0, 0, 0});
}
+ void attachInput(WindowState win) {
+ if (mInputInterceptor != null) {
+ mInputInterceptor.dispose();
+ }
+ mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", win);
+ }
+
public void remove() {
if (mSurface != null) {
mSurface.remove();
mSurface = null;
}
+ if (mInputInterceptor != null) {
+ mInputInterceptor.dispose();
+ mInputInterceptor = null;
+ }
}
public int getWidth() {
@@ -193,6 +288,10 @@
t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top);
t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(),
mSurfaceFrameRelative.height());
+ if (mInputInterceptor != null) {
+ mInputInterceptor.updateTouchableRegion(mSurfaceFrameRelative);
+ t.setInputWindowInfo(mSurface, mInputInterceptor.mWindowHandle);
+ }
t.show(mSurface);
} else if (mSurface != null) {
t.hide(mSurface);
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 5ea2451..35b8641 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -251,7 +251,7 @@
if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting);
final SurfaceControl leash = mLeash;
final AnimationAdapter animation = mAnimation;
- reset(t, forwardCancel);
+ reset(t, false);
if (animation != null) {
if (!mAnimationStartDelayed && forwardCancel) {
animation.onAnimationCancelled(leash);
@@ -260,6 +260,12 @@
mAnimationFinishedCallback.run();
}
}
+
+ if (forwardCancel && leash != null) {
+ t.remove(leash);
+ mService.scheduleAnimationLocked();
+ }
+
if (!restarting) {
mAnimationStartDelayed = false;
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 69f0012..59d7560 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -119,6 +119,7 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
@@ -1288,22 +1289,7 @@
|| top == null) {
return getRequestedOverrideConfiguration().orientation;
}
- int screenOrientation = top.getOrientation();
- if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
- // NOSENSOR means the display's "natural" orientation, so return that.
- ActivityDisplay display = mStack != null ? mStack.getDisplay() : null;
- if (display != null && display.mDisplayContent != null) {
- return mStack.getDisplay().mDisplayContent.getNaturalOrientation();
- }
- } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
- // LOCKED means the activity's orientation remains unchanged, so return existing value.
- return top.getConfiguration().orientation;
- } else if (ActivityInfo.isFixedOrientationLandscape(screenOrientation)) {
- return ORIENTATION_LANDSCAPE;
- } else if (ActivityInfo.isFixedOrientationPortrait(screenOrientation)) {
- return ORIENTATION_PORTRAIT;
- }
- return ORIENTATION_UNDEFINED;
+ return top.getRequestedConfigurationOrientation();
}
/**
@@ -2084,6 +2070,11 @@
return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
}
+ void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
+ @NonNull Configuration parentConfig) {
+ computeConfigResourceOverrides(inOutConfig, parentConfig, true /* insideParentBounds */);
+ }
+
/**
* Calculates configuration values used by the client to get resources. This should be run
* using app-facing bounds (bounds unmodified by animations or transient interactions).
@@ -2093,7 +2084,7 @@
* just be inherited from the parent configuration.
**/
void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
- @NonNull Configuration parentConfig) {
+ @NonNull Configuration parentConfig, boolean insideParentBounds) {
int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
windowingMode = parentConfig.windowConfiguration.getWindowingMode();
@@ -2111,7 +2102,7 @@
inOutConfig.windowConfiguration.setAppBounds(bounds);
outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
}
- if (windowingMode != WINDOWING_MODE_FREEFORM) {
+ if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
outAppBounds.intersect(parentAppBounds);
@@ -2120,7 +2111,7 @@
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
|| inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- if (mStack != null) {
+ if (insideParentBounds && mStack != null) {
final DisplayInfo di = new DisplayInfo();
mStack.getDisplay().mDisplay.getDisplayInfo(di);
@@ -2135,12 +2126,16 @@
}
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
- inOutConfig.screenWidthDp = Math.min((int) (mTmpStableBounds.width() / density),
- parentConfig.screenWidthDp);
+ final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
+ inOutConfig.screenWidthDp = insideParentBounds
+ ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
+ : overrideScreenWidthDp;
}
if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- inOutConfig.screenHeightDp = Math.min((int) (mTmpStableBounds.height() / density),
- parentConfig.screenHeightDp);
+ final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
+ inOutConfig.screenHeightDp = insideParentBounds
+ ? Math.min(overrideScreenHeightDp, parentConfig.screenWidthDp)
+ : overrideScreenHeightDp;
}
if (inOutConfig.smallestScreenWidthDp
@@ -2162,7 +2157,7 @@
if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
- ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
+ ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
}
if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
// For calculating screen layout, we need to use the non-decor inset screen area for the
@@ -2332,6 +2327,7 @@
info.userId = userId;
info.stackId = getStackId();
info.taskId = taskId;
+ info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
info.isRunning = getTopActivity() != null;
info.baseIntent = new Intent(getBaseIntent());
info.baseActivity = reuseActivitiesReport.base != null
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 00105be..c747c6d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -47,7 +47,6 @@
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
@@ -1839,6 +1838,9 @@
return;
}
outDisplayFrame.set(win.getDisplayFrameLw());
+ if (win.inSizeCompatMode()) {
+ outDisplayFrame.scale(win.mInvGlobalScale);
+ }
}
}
@@ -1963,8 +1965,6 @@
if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
- win.mEnforceSizeCompat =
- (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
winAnimator.mAlpha = attrs.alpha;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 85b251a..48cd6b6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -246,7 +246,6 @@
final boolean mIsWallpaper;
private final boolean mIsFloatingLayer;
int mSeq;
- boolean mEnforceSizeCompat;
int mViewVisibility;
int mSystemUiVisibility;
/**
@@ -505,7 +504,8 @@
*/
private PowerManager.WakeLock mDrawLock;
- final private Rect mTmpRect = new Rect();
+ private final Rect mTmpRect = new Rect();
+ private final Point mTmpPoint = new Point();
/**
* Whether the window was resized by us while it was gone for layout.
@@ -655,7 +655,6 @@
mContext = mWmService.mContext;
DeathRecipient deathRecipient = new DeathRecipient();
mSeq = seq;
- mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
mPowerManagerWrapper = powerManagerWrapper;
mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
if (localLOGV) Slog.v(
@@ -733,6 +732,18 @@
}
/**
+ * @return {@code true} if the application runs in size compatibility mode.
+ * @see android.content.res.CompatibilityInfo#supportsScreen
+ * @see ActivityRecord#inSizeCompatMode
+ */
+ boolean inSizeCompatMode() {
+ return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
+ || (mAppToken != null && mAppToken.inSizeCompatMode()
+ // Exclude starting window because it is not displayed by the application.
+ && mAttrs.type != TYPE_APPLICATION_STARTING);
+ }
+
+ /**
* Returns whether this {@link WindowState} has been considered for drawing by its parent.
*/
boolean getDrawnStateEvaluated() {
@@ -995,7 +1006,7 @@
mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
- if (mEnforceSizeCompat) {
+ if (inSizeCompatMode()) {
// If there is a size compatibility scale being applied to the
// window, we need to apply this to its insets so that they are
// reported to the app in its coordinate space.
@@ -1354,8 +1365,8 @@
}
void prelayout() {
- if (mEnforceSizeCompat) {
- mGlobalScale = getDisplayContent().mCompatibleScreenScale;
+ if (inSizeCompatMode()) {
+ mGlobalScale = mToken.getSizeCompatScale();
mInvGlobalScale = 1 / mGlobalScale;
} else {
mGlobalScale = mInvGlobalScale = 1;
@@ -2145,6 +2156,30 @@
int getSurfaceTouchableRegion(Region region, int flags) {
final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
+ if (mAppToken != null && !mAppToken.getResolvedOverrideBounds().isEmpty()) {
+ // There may have touchable letterboxes around the activity, so in order to let the
+ // letterboxes are able to receive touch event and slip to activity, the activity with
+ // compatibility bounds cannot occupy full screen touchable region.
+ if (modal) {
+ // A modal window uses the whole compatibility bounds.
+ flags |= FLAG_NOT_TOUCH_MODAL;
+ mTmpRect.set(mAppToken.getResolvedOverrideBounds());
+ // TODO(b/112288258): Remove the forced offset when the override bounds always
+ // starts from zero (See {@link ActivityRecord#resolveOverrideConfiguration}).
+ mTmpRect.offsetTo(0, 0);
+ } else {
+ // Non-modal uses the application based frame.
+ mTmpRect.set(mWindowFrames.mCompatFrame);
+ }
+ // The offset of compatibility bounds is applied to surface of {@link #AppWindowToken}
+ // and frame, so it is unnecessary to translate twice in surface based coordinates.
+ final int surfaceOffsetX = mAppToken.inSizeCompatMode()
+ ? mAppToken.getBounds().left : 0;
+ mTmpRect.offset(surfaceOffsetX - mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
+ region.set(mTmpRect);
+ return flags;
+ }
+
if (modal && mAppToken != null) {
// Limit the outer touch to the activity stack region.
flags |= FLAG_NOT_TOUCH_MODAL;
@@ -2943,7 +2978,7 @@
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
- final Rect frame = mWindowFrames.mFrame;
+ final Rect frame = mWindowFrames.mCompatFrame;
final Rect overscanInsets = mWindowFrames.mLastOverscanInsets;
final Rect contentInsets = mWindowFrames.mLastContentInsets;
final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
@@ -3353,7 +3388,7 @@
pw.println(prefix + "mHasSurface=" + mHasSurface
+ " isReadyForDisplay()=" + isReadyForDisplay()
+ " mWindowRemovalAllowed=" + mWindowRemovalAllowed);
- if (mEnforceSizeCompat) {
+ if (inSizeCompatMode()) {
pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB));
}
if (dumpAll) {
@@ -3477,17 +3512,18 @@
float x, y;
int w,h;
+ final boolean inSizeCompatMode = inSizeCompatMode();
if ((mAttrs.flags & FLAG_SCALED) != 0) {
if (mAttrs.width < 0) {
w = pw;
- } else if (mEnforceSizeCompat) {
+ } else if (inSizeCompatMode) {
w = (int)(mAttrs.width * mGlobalScale + .5f);
} else {
w = mAttrs.width;
}
if (mAttrs.height < 0) {
h = ph;
- } else if (mEnforceSizeCompat) {
+ } else if (inSizeCompatMode) {
h = (int)(mAttrs.height * mGlobalScale + .5f);
} else {
h = mAttrs.height;
@@ -3495,21 +3531,21 @@
} else {
if (mAttrs.width == MATCH_PARENT) {
w = pw;
- } else if (mEnforceSizeCompat) {
+ } else if (inSizeCompatMode) {
w = (int)(mRequestedWidth * mGlobalScale + .5f);
} else {
w = mRequestedWidth;
}
if (mAttrs.height == MATCH_PARENT) {
h = ph;
- } else if (mEnforceSizeCompat) {
+ } else if (inSizeCompatMode) {
h = (int)(mRequestedHeight * mGlobalScale + .5f);
} else {
h = mRequestedHeight;
}
}
- if (mEnforceSizeCompat) {
+ if (inSizeCompatMode) {
x = mAttrs.x * mGlobalScale;
y = mAttrs.y * mGlobalScale;
} else {
@@ -3537,7 +3573,7 @@
// We need to make sure we update the CompatFrame as it is used for
// cropping decisions, etc, on systems where we lack a decor layer.
mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
- if (mEnforceSizeCompat) {
+ if (inSizeCompatMode) {
// See comparable block in computeFrameLw.
mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
}
@@ -3650,7 +3686,7 @@
float translateToWindowX(float x) {
float winX = x - mWindowFrames.mFrame.left;
- if (mEnforceSizeCompat) {
+ if (inSizeCompatMode()) {
winX *= mGlobalScale;
}
return winX;
@@ -3658,7 +3694,7 @@
float translateToWindowY(float y) {
float winY = y - mWindowFrames.mFrame.top;
- if (mEnforceSizeCompat) {
+ if (inSizeCompatMode()) {
winY *= mGlobalScale;
}
return winY;
@@ -4233,12 +4269,11 @@
*/
void calculatePolicyCrop(Rect policyCrop) {
final DisplayContent displayContent = getDisplayContent();
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- if (!isDefaultDisplay()) {
+ if (!displayContent.isDefaultDisplay && !displayContent.supportsSystemDecorations()) {
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
- // TODO(multi-display)
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
mWindowFrames.mCompatFrame.height());
policyCrop.intersect(-mWindowFrames.mCompatFrame.left, -mWindowFrames.mCompatFrame.top,
@@ -4304,7 +4339,7 @@
// scale function because we want to round things to make the crop
// always round to a larger rect to ensure we don't crop too
// much and hide part of the window that should be seen.
- if (mEnforceSizeCompat && mInvGlobalScale != 1.0f) {
+ if (inSizeCompatMode() && mInvGlobalScale != 1.0f) {
final float scale = mInvGlobalScale;
systemDecorRect.left = (int) (systemDecorRect.left * scale - 0.5f);
systemDecorRect.top = (int) (systemDecorRect.top * scale - 0.5f);
@@ -4664,8 +4699,9 @@
// Since the parent was outset by its surface insets, we need to undo the outsetting
// with insetting by the same amount.
final WindowState parent = getParentWindow();
- outPoint.offset(-parent.mWindowFrames.mFrame.left + parent.mAttrs.surfaceInsets.left,
- -parent.mWindowFrames.mFrame.top + parent.mAttrs.surfaceInsets.top);
+ transformSurfaceInsetsPosition(mTmpPoint, parent.mAttrs.surfaceInsets);
+ outPoint.offset(-parent.mWindowFrames.mFrame.left + mTmpPoint.x,
+ -parent.mWindowFrames.mFrame.top + mTmpPoint.y);
} else if (parentWindowContainer != null) {
final Rect parentBounds = parentWindowContainer.getDisplayedBounds();
outPoint.offset(-parentBounds.left, -parentBounds.top);
@@ -4683,7 +4719,22 @@
}
// Expand for surface insets. See WindowState.expandForSurfaceInsets.
- outPoint.offset(-mAttrs.surfaceInsets.left, -mAttrs.surfaceInsets.top);
+ transformSurfaceInsetsPosition(mTmpPoint, mAttrs.surfaceInsets);
+ outPoint.offset(-mTmpPoint.x, -mTmpPoint.y);
+ }
+
+ /**
+ * The surface insets from layout parameter are in application coordinate. If the window is
+ * scaled, the insets also need to be scaled for surface position in global coordinate.
+ */
+ private void transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets) {
+ if (!inSizeCompatMode()) {
+ outPos.x = surfaceInsets.left;
+ outPos.y = surfaceInsets.top;
+ return;
+ }
+ outPos.x = (int) (surfaceInsets.left * mGlobalScale + 0.5f);
+ outPos.y = (int) (surfaceInsets.top * mGlobalScale + 0.5f);
}
boolean needsRelativeLayeringToIme() {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 3b9b8ba..f0b9c62 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -182,6 +182,14 @@
}
/**
+ * @return The scale for applications running in compatibility mode. Multiply the size in the
+ * application by this scale will be the size in the screen.
+ */
+ float getSizeCompatScale() {
+ return mDisplayContent.mCompatibleScreenScale;
+ }
+
+ /**
* Returns true if the new window is considered greater than the existing window in terms of
* z-order.
*/
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e30acf7..9523202 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -17,8 +17,8 @@
package com.android.server.devicepolicy;
import static android.Manifest.permission.BIND_DEVICE_ADMIN;
-import static android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+import static android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
@@ -247,6 +247,7 @@
import com.android.server.pm.UserRestrictionsUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
import com.google.android.collect.Sets;
@@ -1870,7 +1871,7 @@
Owners newOwners() {
return new Owners(getUserManager(), getUserManagerInternal(),
- getPackageManagerInternal());
+ getPackageManagerInternal(), getActivityTaskManagerInternal());
}
UserManager getUserManager() {
@@ -1885,6 +1886,10 @@
return LocalServices.getService(PackageManagerInternal.class);
}
+ ActivityTaskManagerInternal getActivityTaskManagerInternal() {
+ return LocalServices.getService(ActivityTaskManagerInternal.class);
+ }
+
UsageStatsManagerInternal getUsageStatsManagerInternal() {
return LocalServices.getService(UsageStatsManagerInternal.class);
}
@@ -4773,8 +4778,8 @@
final int callingUserId = mInjector.userHandleGetCallingUserId();
enforceUserUnlocked(callingUserId);
mContext.enforceCallingOrSelfPermission(
- GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY,
- "Must have " + GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY + " permission.");
+ REQUEST_SCREEN_LOCK_COMPLEXITY,
+ "Must have " + REQUEST_SCREEN_LOCK_COMPLEXITY + " permission.");
synchronized (getLockObject()) {
int targetUserId = getCredentialOwner(callingUserId, /* parent= */ false);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index ee1c1df3..27cd70c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -41,6 +41,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
import libcore.io.IoUtils;
@@ -104,6 +105,7 @@
private final UserManager mUserManager;
private final UserManagerInternal mUserManagerInternal;
private final PackageManagerInternal mPackageManagerInternal;
+ private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
private boolean mSystemReady;
@@ -129,18 +131,22 @@
public Owners(UserManager userManager,
UserManagerInternal userManagerInternal,
- PackageManagerInternal packageManagerInternal) {
- this(userManager, userManagerInternal, packageManagerInternal, new Injector());
+ PackageManagerInternal packageManagerInternal,
+ ActivityTaskManagerInternal activityTaskManagerInternal) {
+ this(userManager, userManagerInternal, packageManagerInternal,
+ activityTaskManagerInternal, new Injector());
}
@VisibleForTesting
Owners(UserManager userManager,
UserManagerInternal userManagerInternal,
PackageManagerInternal packageManagerInternal,
+ ActivityTaskManagerInternal activityTaskManagerInternal,
Injector injector) {
mUserManager = userManager;
mUserManagerInternal = userManagerInternal;
mPackageManagerInternal = packageManagerInternal;
+ mActivityTaskManagerInternal = activityTaskManagerInternal;
mInjector = injector;
}
@@ -187,6 +193,7 @@
getDeviceOwnerUserId()));
}
pushToPackageManagerLocked();
+ pushToActivityTaskManagerLocked();
pushToAppOpsLocked();
}
}
@@ -201,6 +208,11 @@
po);
}
+ private void pushToActivityTaskManagerLocked() {
+ mActivityTaskManagerInternal.setDeviceOwnerPackageName(mDeviceOwner != null
+ ? mDeviceOwner.packageName : null);
+ }
+
String getDeviceOwnerPackageName() {
synchronized (mLock) {
return mDeviceOwner != null ? mDeviceOwner.packageName : null;
@@ -275,6 +287,7 @@
mUserManagerInternal.setDeviceManaged(true);
pushToPackageManagerLocked();
+ pushToActivityTaskManagerLocked();
pushToAppOpsLocked();
}
}
@@ -286,6 +299,7 @@
mUserManagerInternal.setDeviceManaged(false);
pushToPackageManagerLocked();
+ pushToActivityTaskManagerLocked();
pushToAppOpsLocked();
}
}
@@ -333,6 +347,7 @@
mDeviceOwner.remoteBugreportHash, /* canAccessDeviceIds =*/
mDeviceOwner.canAccessDeviceIds);
pushToPackageManagerLocked();
+ pushToActivityTaskManagerLocked();
pushToAppOpsLocked();
}
}
diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java b/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java
similarity index 76%
rename from services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
rename to services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java
index 4354db7..24e5573 100644
--- a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 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.
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package com.android.server.backup.encryption.chunk;
@@ -36,7 +36,7 @@
@RunWith(RobolectricTestRunner.class)
@Presubmit
-public class ChunkListingTest {
+public class ChunkListingMapTest {
private static final String CHUNK_A = "CHUNK_A";
private static final String CHUNK_B = "CHUNK_B";
private static final String CHUNK_C = "CHUNK_C";
@@ -62,13 +62,13 @@
createChunkListingProto(
new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
- ChunkListing chunkListing =
- ChunkListing.readFromProto(
+ ChunkListingMap chunkListingMap =
+ ChunkListingMap.readFromProto(
new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
- boolean chunkAInList = chunkListing.hasChunk(mChunkHashA);
- boolean chunkBInList = chunkListing.hasChunk(mChunkHashB);
- boolean chunkCInList = chunkListing.hasChunk(mChunkHashC);
+ boolean chunkAInList = chunkListingMap.hasChunk(mChunkHashA);
+ boolean chunkBInList = chunkListingMap.hasChunk(mChunkHashB);
+ boolean chunkCInList = chunkListingMap.hasChunk(mChunkHashC);
assertThat(chunkAInList).isTrue();
assertThat(chunkBInList).isTrue();
@@ -81,13 +81,13 @@
createChunkListingProto(
new ChunkHash[] {mChunkHashA, mChunkHashB},
new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH});
- ChunkListing chunkListing =
- ChunkListing.readFromProto(
+ ChunkListingMap chunkListingMap =
+ ChunkListingMap.readFromProto(
new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
ChunkHash chunkHashEmpty = getHash("");
- boolean chunkCInList = chunkListing.hasChunk(mChunkHashC);
- boolean emptyChunkInList = chunkListing.hasChunk(chunkHashEmpty);
+ boolean chunkCInList = chunkListingMap.hasChunk(mChunkHashC);
+ boolean emptyChunkInList = chunkListingMap.hasChunk(chunkHashEmpty);
assertThat(chunkCInList).isFalse();
assertThat(emptyChunkInList).isFalse();
@@ -99,13 +99,13 @@
createChunkListingProto(
new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
- ChunkListing chunkListing =
- ChunkListing.readFromProto(
+ ChunkListingMap chunkListingMap =
+ ChunkListingMap.readFromProto(
new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
- ChunkListing.Entry entryA = chunkListing.getChunkEntry(mChunkHashA);
- ChunkListing.Entry entryB = chunkListing.getChunkEntry(mChunkHashB);
- ChunkListing.Entry entryC = chunkListing.getChunkEntry(mChunkHashC);
+ ChunkListingMap.Entry entryA = chunkListingMap.getChunkEntry(mChunkHashA);
+ ChunkListingMap.Entry entryB = chunkListingMap.getChunkEntry(mChunkHashB);
+ ChunkListingMap.Entry entryC = chunkListingMap.getChunkEntry(mChunkHashC);
assertThat(entryA.getLength()).isEqualTo(CHUNK_A_LENGTH);
assertThat(entryB.getLength()).isEqualTo(CHUNK_B_LENGTH);
@@ -118,13 +118,13 @@
createChunkListingProto(
new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
- ChunkListing chunkListing =
- ChunkListing.readFromProto(
+ ChunkListingMap chunkListingMap =
+ ChunkListingMap.readFromProto(
new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
- ChunkListing.Entry entryA = chunkListing.getChunkEntry(mChunkHashA);
- ChunkListing.Entry entryB = chunkListing.getChunkEntry(mChunkHashB);
- ChunkListing.Entry entryC = chunkListing.getChunkEntry(mChunkHashC);
+ ChunkListingMap.Entry entryA = chunkListingMap.getChunkEntry(mChunkHashA);
+ ChunkListingMap.Entry entryB = chunkListingMap.getChunkEntry(mChunkHashB);
+ ChunkListingMap.Entry entryC = chunkListingMap.getChunkEntry(mChunkHashC);
assertThat(entryA.getStart()).isEqualTo(0);
assertThat(entryB.getStart()).isEqualTo(CHUNK_A_LENGTH);
@@ -137,22 +137,24 @@
createChunkListingProto(
new ChunkHash[] {mChunkHashA, mChunkHashB},
new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH});
- ChunkListing chunkListing =
- ChunkListing.readFromProto(
+ ChunkListingMap chunkListingMap =
+ ChunkListingMap.readFromProto(
new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
- ChunkListing.Entry chunkEntryNonexistentChunk = chunkListing.getChunkEntry(mChunkHashC);
+ ChunkListingMap.Entry chunkEntryNonexistentChunk =
+ chunkListingMap.getChunkEntry(mChunkHashC);
assertThat(chunkEntryNonexistentChunk).isNull();
}
@Test
- public void testReadFromProto_whenEmptyProto_returnsChunkListingWith0Chunks() throws Exception {
+ public void testReadFromProto_whenEmptyProto_returnsChunkListingMapWith0Chunks()
+ throws Exception {
ProtoInputStream emptyProto = new ProtoInputStream(new ByteArrayInputStream(new byte[] {}));
- ChunkListing chunkListing = ChunkListing.readFromProto(emptyProto);
+ ChunkListingMap chunkListingMap = ChunkListingMap.readFromProto(emptyProto);
- assertThat(chunkListing.getChunkCount()).isEqualTo(0);
+ assertThat(chunkListingMap.getChunkCount()).isEqualTo(0);
}
@Test
@@ -162,11 +164,11 @@
new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
- ChunkListing chunkListing =
- ChunkListing.readFromProto(
+ ChunkListingMap chunkListingMap =
+ ChunkListingMap.readFromProto(
new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
- assertThat(chunkListing.getChunkCount()).isEqualTo(3);
+ assertThat(chunkListingMap.getChunkCount()).isEqualTo(3);
}
private byte[] createChunkListingProto(ChunkHash[] hashes, int[] lengths) {
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index dc31c0f..fce7599 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -66,6 +66,8 @@
<uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
<uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
<uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
<!-- Uses API introduced in O (26) -->
<uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index a847b6a..2ce4c54 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -65,7 +65,8 @@
public OwnersTestable(MockSystemServices services) {
super(services.userManager, services.userManagerInternal,
- services.packageManagerInternal, new MockInjector(services));
+ services.packageManagerInternal, services.activityTaskManagerInternal,
+ new MockInjector(services));
}
static class MockInjector extends Injector {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 9ac91dd..de782a5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5199,7 +5199,7 @@
public void testGetPasswordComplexity_currentUserNoPassword() {
when(getServices().userManager.isUserUnlocked(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(true);
- mServiceContext.permissions.add(permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ mServiceContext.permissions.add(permission.REQUEST_SCREEN_LOCK_COMPLEXITY);
when(getServices().userManager.getCredentialOwnerProfile(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(DpmMockContext.CALLER_USER_HANDLE);
@@ -5209,7 +5209,7 @@
public void testGetPasswordComplexity_currentUserHasPassword() {
when(getServices().userManager.isUserUnlocked(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(true);
- mServiceContext.permissions.add(permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ mServiceContext.permissions.add(permission.REQUEST_SCREEN_LOCK_COMPLEXITY);
when(getServices().userManager.getCredentialOwnerProfile(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(DpmMockContext.CALLER_USER_HANDLE);
dpms.mUserPasswordMetrics.put(
@@ -5222,7 +5222,7 @@
public void testGetPasswordComplexity_unifiedChallengeReturnsParentUserPassword() {
when(getServices().userManager.isUserUnlocked(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(true);
- mServiceContext.permissions.add(permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ mServiceContext.permissions.add(permission.REQUEST_SCREEN_LOCK_COMPLEXITY);
UserInfo parentUser = new UserInfo();
parentUser.id = DpmMockContext.CALLER_USER_HANDLE + 10;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 4724f1c..8f0aeea 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -64,6 +64,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.File;
import java.io.IOException;
@@ -94,6 +95,7 @@
public final IActivityManager iactivityManager;
public final IActivityTaskManager iactivityTaskManager;
public ActivityManagerInternal activityManagerInternal;
+ public ActivityTaskManagerInternal activityTaskManagerInternal;
public final IPackageManager ipackageManager;
public final IBackupManager ibackupManager;
public final IAudioService iaudioService;
@@ -133,6 +135,7 @@
iactivityManager = mock(IActivityManager.class);
iactivityTaskManager = mock(IActivityTaskManager.class);
activityManagerInternal = mock(ActivityManagerInternal.class);
+ activityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
ipackageManager = mock(IPackageManager.class);
ibackupManager = mock(IBackupManager.class);
iaudioService = mock(IAudioService.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 2de4ae0..23bae88 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -24,6 +24,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
+
import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -35,9 +36,7 @@
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.SparseIntArray;
-import android.util.proto.ProtoOutputStream;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 4073ff1..8c36905 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -183,11 +183,14 @@
.thenReturn(navBarPosition);
mTask.getConfiguration().windowConfiguration.setAppBounds(taskBounds);
mActivity.info.maxAspectRatio = aspectRatio;
- mActivity.ensureActivityConfiguration(
- 0 /* globalChanges */, false /* preserveWindow */);
+ ensureActivityConfiguration();
assertEquals(expectedActivityBounds, mActivity.getBounds());
}
+ private void ensureActivityConfiguration() {
+ mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ }
+
@Test
public void testCanBeLaunchedOnDisplay() {
mService.mSupportsMultiWindow = true;
@@ -281,7 +284,7 @@
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
- mActivity.ensureActivityConfiguration(0, false, false);
+ ensureActivityConfiguration();
assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE,
mActivity.mRelaunchReason);
@@ -305,7 +308,7 @@
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
- mActivity.ensureActivityConfiguration(0, false, false);
+ ensureActivityConfiguration();
assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE,
mActivity.mRelaunchReason);
@@ -327,7 +330,7 @@
mActivity.mRelaunchReason =
ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
- mActivity.ensureActivityConfiguration(0, false, false);
+ ensureActivityConfiguration();
assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_NONE,
mActivity.mRelaunchReason);
@@ -433,4 +436,46 @@
stack.getDisplay().removeChild(stack);
}
}
+
+ @Test
+ public void testFixedScreenConfigurationWhenMovingToDisplay() {
+ // Initialize different bounds on a new display.
+ final ActivityDisplay newDisplay = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+ newDisplay.setBounds(0, 0, 1000, 2000);
+ newDisplay.getConfiguration().densityDpi = 300;
+
+ mTask.getWindowConfiguration().setAppBounds(mStack.getDisplay().getBounds());
+ mTask.getConfiguration().densityDpi = 200;
+ when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+ mActivity.info.maxAspectRatio = 1.5f;
+ ensureActivityConfiguration();
+ final Rect originalBounds = new Rect(mActivity.getBounds());
+ final int originalDpi = mActivity.getConfiguration().densityDpi;
+
+ // Move the non-resizable activity to the new display.
+ mStack.reparent(newDisplay, true /* onTop */, false /* displayRemoved */);
+ ensureActivityConfiguration();
+
+ assertEquals(originalBounds, mActivity.getBounds());
+ assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
+ }
+
+ @Test
+ public void testFixedScreenBoundsWhenDisplaySizeChanged() {
+ when(mActivity.mAppWindowToken.getOrientationIgnoreVisibility()).thenReturn(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ mTask.getWindowConfiguration().setAppBounds(mStack.getDisplay().getBounds());
+ mActivity.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+ ensureActivityConfiguration();
+ final Rect originalBounds = new Rect(mActivity.getBounds());
+
+ // Change the size of current display.
+ mStack.getDisplay().setBounds(0, 0, 1000, 2000);
+ ensureActivityConfiguration();
+
+ assertEquals(originalBounds, mActivity.getBounds());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 60f1ae26..392b010 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -61,7 +61,6 @@
import android.app.ActivityOptions;
import android.app.IApplicationThread;
-import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -643,7 +642,7 @@
UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
false, false, false, true, false);
runAndVerifyBackgroundActivityStartsSubtest(
- "disallowed_callingPackageIsDeviceOwner_notAborted", false,
+ "disallowed_callingPackageNameIsDeviceOwner_notAborted", false,
UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
false, false, false, false, true);
@@ -655,7 +654,7 @@
boolean hasForegroundActivities, boolean callerIsRecents,
boolean callerIsTempWhitelisted,
boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges,
- boolean isCallingPackageDeviceOwner) {
+ boolean isCallingPackageNameDeviceOwner) {
// window visibility
doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
.isAnyNonToastWindowVisibleForUid(callingUid);
@@ -681,9 +680,8 @@
// caller is instrumenting with background activity starts privileges
callerApp.setInstrumenting(callerIsInstrumentingWithBackgroundActivityStartPrivileges,
callerIsInstrumentingWithBackgroundActivityStartPrivileges);
- // caller is device owner
- DevicePolicyManager dpmMock = mService.getDevicePolicyManager();
- doReturn(isCallingPackageDeviceOwner).when(dpmMock).isDeviceOwnerApp(any());
+ // calling package name is whitelisted
+ doReturn(isCallingPackageNameDeviceOwner).when(mService).isDeviceOwner(any());
final ActivityOptions options = spy(ActivityOptions.makeBasic());
ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 21a4e84..abc0bd6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -42,7 +42,6 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.IApplicationThread;
-import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -437,7 +436,6 @@
spyOn(getLifecycleManager());
spyOn(getLockTaskController());
doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
- doReturn(mock(DevicePolicyManager.class)).when(this).getDevicePolicyManager();
// allow background activity starts by default
doReturn(true).when(this).isBackgroundActivityStartsEnabled();
doNothing().when(this).updateCpuStats();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index bc62de1..cd13209 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -44,6 +44,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -62,7 +63,6 @@
* Build/Install/Run:
* atest FrameworksServicesTests:AppWindowTokenTests
*/
-@FlakyTest(bugId = 68267650)
@SmallTest
@Presubmit
public class AppWindowTokenTests extends WindowTestsBase {
@@ -79,6 +79,7 @@
mTask = createTaskInStack(mStack, 0 /* userId */);
mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+ mToken.mSkipOnParentChanged = false;
mTask.addChild(mToken, 0);
}
@@ -141,6 +142,7 @@
mToken.removeImmediately();
}
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
@Test
public void testLandscapeSeascapeRotationByApp() {
// Some plumbing to get the service ready for rotation updates.
@@ -166,6 +168,8 @@
mDisplayContent.updateOrientationFromAppTokens(
mDisplayContent.getRequestedOverrideConfiguration(),
null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
+ // In this test, DC will not get config update. Set the waiting flag to false.
+ mDisplayContent.mWaitingForConfig = false;
mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
assertTrue(appWindow.mResizeReported);
@@ -211,6 +215,48 @@
}
@Test
+ public void testSizeCompatBounds() {
+ // The real surface transaction is unnecessary.
+ mToken.setSkipPrepareSurfaces(true);
+
+ final Rect fixedBounds = mToken.getRequestedOverrideConfiguration().windowConfiguration
+ .getBounds();
+ fixedBounds.set(0, 0, 1200, 1600);
+ final Configuration newParentConfig = mTask.getConfiguration();
+
+ // Change the size of the container to two times smaller with insets.
+ newParentConfig.windowConfiguration.setAppBounds(200, 0, 800, 800);
+ final Rect containerAppBounds = newParentConfig.windowConfiguration.getAppBounds();
+ final Rect containerBounds = newParentConfig.windowConfiguration.getBounds();
+ containerBounds.set(0, 0, 600, 800);
+ mToken.onConfigurationChanged(newParentConfig);
+
+ assertTrue(mToken.inSizeCompatMode());
+ assertEquals(containerAppBounds, mToken.getBounds());
+ assertEquals((float) containerAppBounds.width() / fixedBounds.width(),
+ mToken.getSizeCompatScale(), 0.0001f /* delta */);
+
+ // Change the width of the container to two times bigger.
+ containerAppBounds.set(0, 0, 2400, 1600);
+ containerBounds.set(containerAppBounds);
+ mToken.onConfigurationChanged(newParentConfig);
+
+ assertTrue(mToken.inSizeCompatMode());
+ // Don't scale up, so the bounds keep the same as the fixed width.
+ assertEquals(fixedBounds.width(), mToken.getBounds().width());
+ // Assert the position is horizontal center.
+ assertEquals((containerAppBounds.width() - fixedBounds.width()) / 2,
+ mToken.getBounds().left);
+ assertEquals(1f, mToken.getSizeCompatScale(), 0.0001f /* delta */);
+
+ // Change the width of the container to fit the fixed bounds.
+ containerBounds.set(0, 0, 1200, 2000);
+ mToken.onConfigurationChanged(newParentConfig);
+ // Assert don't use fixed bounds because the region is enough.
+ assertFalse(mToken.inSizeCompatMode());
+ }
+
+ @Test
@Presubmit
public void testGetOrientation() {
mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -300,6 +346,7 @@
assertNoStartingWindow(mToken);
}
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
@Test
public void testAddRemoveRace() {
// There was once a race condition between adding and removing starting windows
@@ -384,6 +431,7 @@
// bottom one.
tokenTop.setVisibility(false, false);
tokenBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
+ waitUntilHandlersIdle();
// Assert that the bottom window now has the starting window.
assertNoStartingWindow(tokenTop);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
index 2f90baa..3f83cae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -71,7 +71,6 @@
* atest WmTests:AssistDataRequesterTest
*/
@MediumTest
-@FlakyTest(bugId = 113616538)
public class AssistDataRequesterTest extends ActivityTestsBase {
private static final String TAG = AssistDataRequesterTest.class.getSimpleName();
@@ -154,6 +153,7 @@
.checkOpNoThrow(eq(OP_ASSIST_SCREENSHOT), anyInt(), anyString());
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testRequestData() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -174,6 +174,7 @@
assertReceivedDataCount(0, 0, 0, 0);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testCurrentAppDisallow_expectNullCallbacks() throws Exception {
setupMocks(!CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -184,6 +185,7 @@
assertReceivedDataCount(0, 1, 0, 1);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testProcessPendingData() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -241,6 +243,7 @@
assertReceivedDataCount(0, 1, 0, 1);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testDisallowAssistContextExtras_expectNullDataCallbacks() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -254,6 +257,7 @@
assertReceivedDataCount(0, 1, 0, 1);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testNoFetchScreenshots_expectNoScreenshotCallbacks() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
@@ -264,6 +268,7 @@
assertReceivedDataCount(5, 5, 0, 0);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testDisallowAssistScreenshot_expectNullScreenshotCallback() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index 0c363de..a0546d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -19,11 +19,11 @@
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -31,8 +31,6 @@
import android.view.InsetsSource;
import android.view.InsetsState;
-import org.junit.Before;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Before;
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 11526a8..bc62e8c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -35,7 +35,6 @@
import org.junit.Test;
@SmallTest
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@Presubmit
public class InsetsStateControllerTest extends WindowTestsBase {
@@ -48,6 +47,7 @@
assertNotNull(getController().getInsetsForDispatch(app).getSource(TYPE_TOP_BAR));
}
+ @FlakyTest(bugId = 69229402)
@Test
public void testStripForDispatch_own() {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -57,6 +57,7 @@
assertEquals(new InsetsState(), getController().getInsetsForDispatch(topBar));
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testStripForDispatch_navBar() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -68,6 +69,7 @@
assertEquals(new InsetsState(), getController().getInsetsForDispatch(navBar));
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testBarControllingWinChanged() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -80,6 +82,7 @@
assertEquals(2, controls.length);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testControlRevoked() {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -91,6 +94,7 @@
assertNull(getController().getControlsForDispatch(app));
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testControlRevoked_animation() {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
diff --git a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
index 86bf3db..b769fce 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
@@ -24,7 +24,6 @@
import android.platform.test.annotations.Presubmit;
import android.view.RemoteAnimationAdapter;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.testutils.OffsettableClock;
diff --git a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
index c3d2f33..8327440 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
@@ -28,7 +28,6 @@
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
index dad6c95..7111852 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
@@ -21,7 +21,6 @@
import android.app.ActivityOptions;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.Test;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index dfdbf32..6cce9f0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -167,7 +167,6 @@
verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L));
}
- @FlakyTest(bugId = 74780584)
@Test
public void testDeferStartingAnimations() throws Exception {
mSurfaceAnimationRunner.deferStartingAnimations();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 8c32e8c..88ac96d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -34,7 +34,6 @@
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.SurfaceAnimator.Animatable;
@@ -51,7 +50,7 @@
* Test class for {@link SurfaceAnimatorTest}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:SurfaceAnimatorTest
+ * atest WmTests:SurfaceAnimatorTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java
index 12ed3c2..9dfeadf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java
@@ -29,8 +29,6 @@
import android.platform.test.annotations.Presubmit;
import android.util.SparseBooleanArray;
-import androidx.test.filters.FlakyTest;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 8c6ac23..1e58e41 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -43,7 +43,6 @@
* Build/Install/Run:
* atest FrameworksServicesTests:TaskPositioningControllerTests
*/
-@FlakyTest(bugId = 117924387)
@SmallTest
@Presubmit
public class TaskPositioningControllerTests extends WindowTestsBase {
@@ -90,6 +89,7 @@
assertNull(mTarget.getDragWindowHandleLocked());
}
+ @FlakyTest(bugId = 69229402)
@Test
public void testHandleTapOutsideTask() {
synchronized (mWm.mGlobalLock) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 4a734e5..dcca316 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -35,9 +35,11 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
import android.support.test.uiautomator.UiDevice;
import android.text.TextUtils;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.internal.annotations.GuardedBy;
@@ -76,6 +78,7 @@
}
@Test
+ @Presubmit
public void testTaskStackChanged_afterFinish() throws Exception {
registerTaskStackChangedListener(new TaskStackListener() {
@Override
@@ -87,7 +90,8 @@
});
Context context = getInstrumentation().getContext();
- context.startActivity(new Intent(context, ActivityA.class));
+ context.startActivity(
+ new Intent(context, ActivityA.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
UiDevice.getInstance(getInstrumentation()).waitForIdle();
synchronized (sLock) {
assertTrue(sTaskStackChangedCalled);
@@ -96,6 +100,7 @@
}
@Test
+ @FlakyTest(bugId = 119893767)
public void testTaskDescriptionChanged() throws Exception {
final Object[] params = new Object[2];
final CountDownLatch latch = new CountDownLatch(1);
@@ -124,6 +129,7 @@
}
@Test
+ @FlakyTest(bugId = 119893767)
public void testActivityRequestedOrientationChanged() throws Exception {
final int[] params = new int[2];
final CountDownLatch latch = new CountDownLatch(1);
@@ -146,6 +152,7 @@
* Tests for onTaskCreated, onTaskMovedToFront, onTaskRemoved and onTaskRemovalStarted.
*/
@Test
+ @FlakyTest(bugId = 119893767)
public void testTaskChangeCallBacks() throws Exception {
final Object[] params = new Object[2];
final CountDownLatch taskCreatedLaunchLatch = new CountDownLatch(1);
@@ -221,7 +228,8 @@
final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), null, false);
getInstrumentation().addMonitor(monitor);
final Context context = getInstrumentation().getContext();
- context.startActivity(new Intent(context, activityClass));
+ context.startActivity(
+ new Intent(context, activityClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
final TestActivity activity = (TestActivity) monitor.waitForActivityWithTimeout(1000);
if (activity == null) {
throw new RuntimeException("Timed out waiting for Activity");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
index 1c1fe29..e540b3a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
@@ -61,7 +61,7 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.quality.Strictness;
-import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* A Test utility class to create a mock {@link WindowManagerService} instance for tests.
@@ -71,6 +71,8 @@
private static WindowManagerService sService;
private static TestWindowManagerPolicy sPolicy;
+ static AtomicBoolean sCurrentMessagesProcessed = new AtomicBoolean(false);
+
static void setUpWindowManagerService() {
sMockitoSession = mockitoSession()
.spyStatic(LockGuard.class)
@@ -195,21 +197,23 @@
}
private static void waitHandlerIdle(Handler handler) {
- if (!handler.hasMessagesOrCallbacks()) {
- return;
- }
- final CountDownLatch latch = new CountDownLatch(1);
- // Wait for delayed messages are processed.
- handler.getLooper().getQueue().addIdleHandler(() -> {
- if (handler.hasMessagesOrCallbacks()) {
- return true; // keep idle handler.
+ synchronized (sCurrentMessagesProcessed) {
+ // Add a message to the handler queue and make sure it is fully processed before we move
+ // on. This makes sure all previous messages in the handler are fully processed vs. just
+ // popping them from the message queue.
+ sCurrentMessagesProcessed.set(false);
+ handler.post(() -> {
+ synchronized (sCurrentMessagesProcessed) {
+ sCurrentMessagesProcessed.set(true);
+ sCurrentMessagesProcessed.notifyAll();
+ }
+ });
+ while (!sCurrentMessagesProcessed.get()) {
+ try {
+ sCurrentMessagesProcessed.wait();
+ } catch (InterruptedException e) {
+ }
}
- latch.countDown();
- return false; // remove idle handler.
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index 64ceb1b..d6608f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -49,7 +49,7 @@
* Test class to for {@link android.app.WindowConfiguration}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowConfigurationTests
+ * atest WmTests:WindowConfigurationTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
index af8ccc9..fc78635 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -26,7 +26,6 @@
import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -35,7 +34,7 @@
* Test class for {@link WindowContainerController}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowContainerControllerTests
+ * atest WmTests:WindowContainerControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index a9a76c2..b93c994 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -47,7 +47,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -59,11 +58,10 @@
* Test class for {@link WindowContainer}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowContainerTests
+ * atest WmTests:WindowContainerTests
*/
@SmallTest
@Presubmit
-@FlakyTest(bugId = 74078662)
public class WindowContainerTests extends WindowTestsBase {
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 0a4a8a4..fb30f8b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -449,8 +449,7 @@
// Now simulate switch to fullscreen for letterboxed app.
final int xInset = logicalWidth / 10;
- final int yInset = logicalWidth / 10;
- final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset);
+ final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
config.windowConfiguration.setBounds(cf);
w.mAppToken.onRequestedOverrideConfigurationChanged(config);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index a494889..114eac9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -151,6 +151,7 @@
/** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
public static class TestAppWindowToken extends AppWindowToken {
boolean mOnTop = false;
+ private boolean mSkipPrepareSurfaces;
private Transaction mPendingTransactionOverride;
boolean mSkipOnParentChanged = true;
@@ -213,6 +214,17 @@
return mOnTop;
}
+ @Override
+ void prepareSurfaces() {
+ if (!mSkipPrepareSurfaces) {
+ super.prepareSurfaces();
+ }
+ }
+
+ void setSkipPrepareSurfaces(boolean ignore) {
+ mSkipPrepareSurfaces = ignore;
+ }
+
void setPendingTransaction(Transaction transaction) {
mPendingTransactionOverride = transaction;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index d556886..4cdbea0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -28,7 +28,6 @@
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -37,7 +36,7 @@
* Tests for the {@link WindowToken} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowTokenTests
+ * atest WmTests:WindowTokenTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
index 2970c21..3c6e240 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
@@ -58,7 +58,7 @@
* Test class for {@link WindowTracing}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowTracingTest
+ * atest WmTests:WindowTracingTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 3dcea75..f3b8a62 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -51,9 +51,8 @@
* Tests for the {@link DisplayContent#assignChildLayers(SurfaceControl.Transaction)} method.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:ZOrderingTests
+ * atest WmTests:ZOrderingTests
*/
-@FlakyTest(bugId = 74078662)
@SmallTest
@Presubmit
public class ZOrderingTests extends WindowTestsBase {
@@ -207,6 +206,7 @@
return createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, name);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testAssignWindowLayers_ForImeWithNoTarget() {
mDisplayContent.mInputMethodTarget = null;
@@ -224,6 +224,7 @@
assertWindowHigher(mImeDialogWindow, mImeWindow);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testAssignWindowLayers_ForImeWithAppTarget() {
final WindowState imeAppTarget = createWindow("imeAppTarget");
@@ -243,6 +244,7 @@
assertWindowHigher(mImeDialogWindow, mImeWindow);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() {
final WindowState imeAppTarget = createWindow("imeAppTarget");
@@ -269,6 +271,7 @@
assertWindowHigher(mImeDialogWindow, mImeWindow);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() {
final WindowState appBelowImeTarget = createWindow("appBelowImeTarget");
@@ -292,6 +295,7 @@
assertWindowHigher(mImeDialogWindow, mImeWindow);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testAssignWindowLayers_ForImeNonAppImeTarget() {
final WindowState imeSystemOverlayTarget = createWindow(null, TYPE_SYSTEM_OVERLAY,
@@ -319,6 +323,7 @@
assertWindowHigher(mImeDialogWindow, mImeWindow);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testAssignWindowLayers_ForStatusBarImeTarget() {
mDisplayContent.mInputMethodTarget = mStatusBarWindow;
@@ -333,6 +338,7 @@
assertWindowHigher(mImeDialogWindow, mImeWindow);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testStackLayers() {
final WindowState anyWindow1 = createWindow("anyWindow");
@@ -398,6 +404,7 @@
assertWindowHigher(mediaOverlayChild, child);
}
+ @FlakyTest(bugId = 124088319)
@Test
public void testDockedDividerPosition() {
final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 4539ab3..a1c32b5 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2717,6 +2717,41 @@
Uri RCS_EVENT_QUERY_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
RCS_EVENT_QUERY_URI_PATH);
}
+
+ /**
+ * Allows RCS specific canonical address handling.
+ */
+ interface RcsCanonicalAddressHelper {
+ /**
+ * Returns the canonical address ID for a canonical address, if now row exists, this
+ * will add a row and return its ID. This helper works against the same table used by
+ * the SMS and MMS threads, but is accessible only by the phone process for use by RCS
+ * message storage.
+ *
+ * @throws IllegalArgumentException if unable to retrieve or create the canonical
+ * address entry.
+ */
+ static long getOrCreateCanonicalAddressId(
+ ContentResolver contentResolver, String canonicalAddress) {
+
+ Uri.Builder uriBuilder = CONTENT_AND_AUTHORITY.buildUpon();
+ uriBuilder.appendPath("canonical-address");
+ uriBuilder.appendQueryParameter("address", canonicalAddress);
+ Uri uri = uriBuilder.build();
+
+ try (Cursor cursor = contentResolver.query(uri, null, null, null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ return cursor.getLong(cursor.getColumnIndex(CanonicalAddressesColumns._ID));
+ } else {
+ Rlog.e(TAG, "getOrCreateCanonicalAddressId returned no rows");
+ }
+ }
+
+ Rlog.e(TAG, "getOrCreateCanonicalAddressId failed");
+ throw new IllegalArgumentException(
+ "Unable to find or allocate a canonical address ID");
+ }
+ }
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 313146d..3a4d33c 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -59,6 +59,7 @@
import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.PhoneConstants;
@@ -72,6 +73,7 @@
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
@@ -2573,17 +2575,35 @@
* {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
* it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
* is used to determine which modem is preferred.
+ * @param needValidation whether validation is needed before switch happens.
+ * @param executor The executor of where the callback will execute.
+ * @param callback Callback will be triggered once it succeeds or failed.
+ * See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
+ * for more details. Pass null if don't care about the result.
+ *
* @hide
*
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void setPreferredDataSubscriptionId(int subId) {
+ public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+ @NonNull @CallbackExecutor Executor executor, Consumer<Integer> callback) {
if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
- if (iSub != null) {
- iSub.setPreferredDataSubscriptionId(subId);
- }
+ if (iSub == null) return;
+
+ ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ if (callback != null) {
+ callback.accept(result);
+ }
+ }));
+ }
+ };
+ iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
} catch (RemoteException ex) {
// ignore it
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2a03924..6690bd0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10094,6 +10094,29 @@
return false;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
+ SET_OPPORTUNISTIC_SUB_SUCCESS,
+ SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
+ SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER})
+ public @interface SetOpportunisticSubscriptionResult {}
+
+ /**
+ * No error. Operation succeeded.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0;
+
+ /**
+ * Validation failed when trying to switch to preferred subscription.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1;
+
+ /**
+ * The parameter passed in is invalid.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2;
+
/**
* Set preferred opportunistic data subscription id.
*
diff --git a/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl b/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl
new file mode 100644
index 0000000..7a78f34
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Callback to provide asynchronous result of setPreferredOpportunisticData.
+ * @hide
+ */
+oneway interface ISetOpportunisticDataCallback {
+ void onComplete(int result);
+}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6ce9de4..75a4d82 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.telephony.SubscriptionInfo;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
interface ISub {
/**
@@ -217,10 +218,14 @@
* designed to overwrite default data subscription temporarily.
*
* @param subId which subscription is preferred to for cellular data.
+ * @param needValidation whether validation is needed before switching.
+ * @param callback callback upon request completion.
+ *
* @hide
*
*/
- void setPreferredDataSubscriptionId(int subId);
+ void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+ ISetOpportunisticDataCallback callback);
/**
* Get which subscription is preferred for cellular data.
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e2d59d6..a7c95c7 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -554,7 +554,7 @@
if (mNmValidationRedirectUrl != null) {
mNmCallbacks.showProvisioningNotification(
- "test_provisioning_notif_action");
+ "test_provisioning_notif_action", "com.android.test.package");
mNmProvNotificationRequested = true;
}
} catch (RemoteException e) {
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index b635607..a4a735d 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -35,6 +35,7 @@
import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -274,6 +275,11 @@
isTetheringSupportedCalls++;
return true;
}
+
+ @Override
+ public int getDefaultDataSubscriptionId() {
+ return INVALID_SUBSCRIPTION_ID;
+ }
}
private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index ec286759..193f380 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -21,6 +21,7 @@
import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -140,7 +141,8 @@
mMockContext = new MockContext(mContext);
mSM = new TestStateMachine();
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, mSystemProperties);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
}
@After
@@ -168,7 +170,8 @@
@Test
public void canRequireProvisioning() {
setupForRequiredProvisioning();
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
assertTrue(mEnMgr.isTetherProvisioningRequired());
}
@@ -177,7 +180,8 @@
setupForRequiredProvisioning();
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
.thenReturn(null);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
// Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
// Therefore provisioning still be required.
assertTrue(mEnMgr.isTetherProvisioningRequired());
@@ -187,7 +191,8 @@
public void toleratesCarrierConfigMissing() {
setupForRequiredProvisioning();
when(mCarrierConfigManager.getConfig()).thenReturn(null);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
// We still have a provisioning app configured, so still require provisioning.
assertTrue(mEnMgr.isTetherProvisioningRequired());
}
@@ -197,11 +202,13 @@
setupForRequiredProvisioning();
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(null);
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
assertFalse(mEnMgr.isTetherProvisioningRequired());
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(new String[] {"malformedApp"});
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
assertFalse(mEnMgr.isTetherProvisioningRequired());
}
@@ -223,7 +230,8 @@
assertFalse(mEnMgr.everRunUiEntitlement);
setupForRequiredProvisioning();
- mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+ mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
+ INVALID_SUBSCRIPTION_ID));
// 2. No cache value and don't need to run entitlement check.
mEnMgr.everRunUiEntitlement = false;
receiver = new ResultReceiver(null) {
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index 5217784..01b904d8 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -22,10 +22,12 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_NOT_REQUIRED;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_REQUIRED;
import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_UNSPECIFIED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -44,26 +46,39 @@
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
-import java.util.Iterator;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Iterator;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class TetheringConfigurationTest {
private final SharedLog mLog = new SharedLog("TetheringConfigurationTest");
+
+ private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
@Mock private Context mContext;
@Mock private TelephonyManager mTelephonyManager;
@Mock private Resources mResources;
+ @Mock private Resources mResourcesForSubId;
private MockContentResolver mContentResolver;
private Context mMockContext;
private boolean mHasTelephonyManager;
+ private class MockTetheringConfiguration extends TetheringConfiguration {
+ MockTetheringConfiguration(Context ctx, SharedLog log, int id) {
+ super(ctx, log, id);
+ }
+
+ @Override
+ protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
+ return mResourcesForSubId;
+ }
+ }
+
private class MockContext extends BroadcastInterceptingContext {
MockContext(Context base) {
super(base);
@@ -99,6 +114,9 @@
.thenReturn(new String[0]);
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
.thenReturn(new int[0]);
+ when(mResources.getStringArray(
+ com.android.internal.R.array.config_mobile_hotspot_provision_app))
+ .thenReturn(new String[0]);
mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
mMockContext = new MockContext(mContext);
@@ -111,7 +129,8 @@
mHasTelephonyManager = true;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_REQUIRED);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.isDunRequired);
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
@@ -127,7 +146,8 @@
mHasTelephonyManager = true;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_NOT_REQUIRED);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertFalse(cfg.isDunRequired);
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
@@ -143,7 +163,8 @@
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.isDunRequired);
assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
// Just to prove we haven't clobbered Wi-Fi:
@@ -160,7 +181,8 @@
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
assertTrue(upstreamIterator.hasNext());
assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
@@ -181,7 +203,8 @@
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
assertTrue(upstreamIterator.hasNext());
assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
@@ -199,7 +222,8 @@
mHasTelephonyManager = false;
when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
assertTrue(upstreamIterator.hasNext());
assertEquals(TYPE_WIFI, upstreamIterator.next().intValue());
@@ -214,7 +238,8 @@
public void testNewDhcpServerDisabled() {
Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.enableLegacyDhcpServer);
}
@@ -222,7 +247,41 @@
public void testNewDhcpServerEnabled() {
Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertFalse(cfg.enableLegacyDhcpServer);
}
+
+ @Test
+ public void testGetResourcesBySubId() {
+ setUpResourceForSubId();
+ final TetheringConfiguration cfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertTrue(cfg.provisioningApp.length == 0);
+ final int anyValidSubId = 1;
+ final MockTetheringConfiguration mockCfg =
+ new MockTetheringConfiguration(mMockContext, mLog, anyValidSubId);
+ assertEquals(mockCfg.provisioningApp[0], PROVISIONING_APP_NAME[0]);
+ assertEquals(mockCfg.provisioningApp[1], PROVISIONING_APP_NAME[1]);
+ }
+
+ private void setUpResourceForSubId() {
+ when(mResourcesForSubId.getStringArray(
+ com.android.internal.R.array.config_tether_dhcp_range)).thenReturn(new String[0]);
+ when(mResourcesForSubId.getStringArray(
+ com.android.internal.R.array.config_tether_usb_regexs)).thenReturn(new String[0]);
+ when(mResourcesForSubId.getStringArray(
+ com.android.internal.R.array.config_tether_wifi_regexs))
+ .thenReturn(new String[]{ "test_wlan\\d" });
+ when(mResourcesForSubId.getStringArray(
+ com.android.internal.R.array.config_tether_bluetooth_regexs))
+ .thenReturn(new String[0]);
+ when(mResourcesForSubId.getIntArray(
+ com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[0]);
+ when(mResourcesForSubId.getStringArray(
+ com.android.internal.R.array.config_mobile_hotspot_provision_app))
+ .thenReturn(PROVISIONING_APP_NAME);
+ }
+
}
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 85bf6f2..582a5b8 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -294,22 +294,6 @@
}
}
- if (el->FindAttribute("", "platformBuildVersionCode") == nullptr) {
- auto versionCode = el->FindAttribute(xml::kSchemaAndroid, "versionCode");
- if (versionCode != nullptr) {
- el->attributes.push_back(xml::Attribute{"", "platformBuildVersionCode",
- versionCode->value});
- }
- }
-
- if (el->FindAttribute("", "platformBuildVersionName") == nullptr) {
- auto versionName = el->FindAttribute(xml::kSchemaAndroid, "versionName");
- if (versionName != nullptr) {
- el->attributes.push_back(xml::Attribute{"", "platformBuildVersionName",
- versionName->value});
- }
- }
-
return true;
});
@@ -489,8 +473,14 @@
// Make sure we un-compile the value if it was set to something else.
attr->compiled_value = {};
-
attr->value = options_.compile_sdk_version.value();
+
+ attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
+
+ // Make sure we un-compile the value if it was set to something else.
+ attr->compiled_value = {};
+ attr->value = options_.compile_sdk_version.value();
+
}
if (options_.compile_sdk_version_codename) {
@@ -499,7 +489,12 @@
// Make sure we un-compile the value if it was set to something else.
attr->compiled_value = {};
+ attr->value = options_.compile_sdk_version_codename.value();
+ attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
+
+ // Make sure we un-compile the value if it was set to something else.
+ attr->compiled_value = {};
attr->value = options_.compile_sdk_version_codename.value();
}
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index adea627..4842f62 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -725,6 +725,43 @@
attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
ASSERT_THAT(attr, NotNull());
EXPECT_THAT(attr->value, StrEq("P"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
+}
+
+TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
+ std::string input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
+ compileSdkVersion="27" compileSdkVersionCodename="O"
+ platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
+ ManifestFixerOptions options;
+ options.compile_sdk_version = {"28"};
+ options.compile_sdk_version_codename = {"P"};
+
+ std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
+ ASSERT_THAT(manifest, NotNull());
+
+ xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
}
TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
@@ -750,59 +787,6 @@
ASSERT_THAT(manifest, IsNull());
}
-TEST_F(ManifestFixerTest, InsertPlatformBuildVersions) {
- // Test for insertion when versionCode and versionName are included in the manifest
- {
- std::string input = R"(
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
- android:versionCode="27" android:versionName="O"/>)";
- std::unique_ptr<xml::XmlResource> manifest = Verify(input);
- ASSERT_THAT(manifest, NotNull());
-
- xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("27"));
- attr = manifest->root->FindAttribute("", "platformBuildVersionName");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("O"));
- }
-
- // Test for insertion when versionCode and versionName defaults are specified
- {
- std::string input = R"(
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"/>)";
- ManifestFixerOptions options;
- options.version_code_default = {"27"};
- options.version_name_default = {"O"};
- std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
- ASSERT_THAT(manifest, NotNull());
-
- xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("27"));
- attr = manifest->root->FindAttribute("", "platformBuildVersionName");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("O"));
- }
-
- // Test that the platform build version attributes are not changed if they are currently present
- {
- std::string input = R"(
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
- android:versionCode="28" android:versionName="P"
- platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
- std::unique_ptr<xml::XmlResource> manifest = Verify(input);
- ASSERT_THAT(manifest, NotNull());
-
- xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("27"));
- attr = manifest->root->FindAttribute("", "platformBuildVersionName");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("O"));
- }
-}
-
TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
std::string input = R"(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 2cc1d83..c88eee8 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4721,7 +4721,6 @@
*
* @hide
*/
- @SystemApi
private static class EasyConnectCallbackProxy extends IDppCallback.Stub {
private final Executor mExecutor;
private final EasyConnectStatusCallback mEasyConnectStatusCallback;