summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/media/framework/java/android/media/Session2CommandGroup.java2
-rw-r--r--api/Android.bp13
-rw-r--r--api/api.go224
-rw-r--r--core/api/current.txt3
-rw-r--r--core/api/system-current.txt2
-rw-r--r--core/api/test-current.txt4
-rw-r--r--core/java/android/accessibilityservice/GestureDescription.java2
-rw-r--r--core/java/android/content/RestrictionEntry.java2
-rw-r--r--core/java/android/debug/AdbManager.java3
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java3
-rw-r--r--core/java/android/hardware/radio/RadioManager.java3
-rw-r--r--core/java/android/permission/IPermissionManager.aidl2
-rw-r--r--core/java/android/permission/PermissionManager.java20
-rw-r--r--core/java/android/print/PrintJobInfo.java2
-rw-r--r--core/java/android/service/dreams/DreamOverlayService.java10
-rw-r--r--core/java/android/service/dreams/DreamService.java13
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java2
-rw-r--r--core/java/com/android/internal/app/chooser/DisplayResolveInfo.java3
-rw-r--r--core/java/com/android/internal/infra/AndroidFuture.java2
-rw-r--r--core/res/AndroidManifest.xml16
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--data/etc/privapp-permissions-platform.xml3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java1
-rw-r--r--packages/Shell/AndroidManifest.xml9
-rw-r--r--packages/Shell/res/values-watch/strings.xml20
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java21
-rw-r--r--services/core/java/com/android/server/SystemServiceManager.java14
-rw-r--r--services/core/java/com/android/server/adb/AdbDebuggingManager.java21
-rw-r--r--services/core/java/com/android/server/adb/AdbService.java2
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java42
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java9
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java23
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java33
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java13
-rw-r--r--services/java/com/android/server/SystemServer.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java110
-rw-r--r--telecomm/java/android/telecom/Call.java12
-rw-r--r--telecomm/java/android/telecom/CallAudioState.java19
-rw-r--r--telecomm/java/android/telecom/Connection.java9
-rw-r--r--telephony/java/android/telephony/NetworkScanRequest.java3
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java3
-rw-r--r--tools/aapt2/cmd/Compile_test.cpp64
-rw-r--r--tools/aapt2/test/Fixture.cpp5
49 files changed, 741 insertions, 154 deletions
diff --git a/apex/media/framework/java/android/media/Session2CommandGroup.java b/apex/media/framework/java/android/media/Session2CommandGroup.java
index 13aabfc45ab7..af8184a27f0d 100644
--- a/apex/media/framework/java/android/media/Session2CommandGroup.java
+++ b/apex/media/framework/java/android/media/Session2CommandGroup.java
@@ -68,7 +68,7 @@ public final class Session2CommandGroup implements Parcelable {
/**
* Used by parcelable creator.
*/
- @SuppressWarnings("WeakerAccess") /* synthetic access */
+ @SuppressWarnings({"WeakerAccess", "UnsafeParcelApi"}) /* synthetic access */
Session2CommandGroup(Parcel in) {
Parcelable[] commands = in.readParcelableArray(Session2Command.class.getClassLoader());
if (commands != null) {
diff --git a/api/Android.bp b/api/Android.bp
index 2e49a0c56778..70f995a44c86 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -24,6 +24,19 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
+bootstrap_go_package {
+ name: "soong-api",
+ pkgPath: "android/soong/api",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-genrule",
+ ],
+ srcs: ["api.go"],
+ pluginFor: ["soong_build"],
+}
+
python_defaults {
name: "python3_version_defaults",
version: {
diff --git a/api/api.go b/api/api.go
new file mode 100644
index 000000000000..976b140f407f
--- /dev/null
+++ b/api/api.go
@@ -0,0 +1,224 @@
+// Copyright (C) 2021 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 api
+
+import (
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/genrule"
+)
+
+// The intention behind this soong plugin is to generate a number of "merged"
+// API-related modules that would otherwise require a large amount of very
+// similar Android.bp boilerplate to define. For example, the merged current.txt
+// API definitions (created by merging the non-updatable current.txt with all
+// the module current.txts). This simplifies the addition of new android
+// modules, by reducing the number of genrules etc a new module must be added to.
+
+// The properties of the combined_apis module type.
+type CombinedApisProperties struct {
+ // Module libraries that have public APIs
+ Public []string
+ // Module libraries that have system APIs
+ System []string
+ // Module libraries that have module_library APIs
+ Module_lib []string
+ // Module libraries that have system_server APIs
+ System_server []string
+ // ART module library. The only API library not removed from the filtered api database, because
+ // 1) ART apis are available by default to all modules, while other module-to-module deps are
+ // explicit and probably receive more scrutiny anyway
+ // 2) The number of ART/libcore APIs is large, so not linting them would create a large gap
+ // 3) It's a compromise. Ideally we wouldn't be filtering out any module APIs, and have
+ // per-module lint databases that excludes just that module's APIs. Alas, that's more
+ // difficult to achieve.
+ Art_module string
+}
+
+type CombinedApis struct {
+ android.ModuleBase
+
+ properties CombinedApisProperties
+}
+
+func init() {
+ registerBuildComponents(android.InitRegistrationContext)
+}
+
+func registerBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory)
+}
+
+var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
+
+func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+}
+
+type genruleProps struct {
+ Name *string
+ Cmd *string
+ Dists []android.Dist
+ Out []string
+ Srcs []string
+ Tools []string
+ Visibility []string
+}
+
+// Struct to pass parameters for the various merged [current|removed].txt file modules we create.
+type MergedTxtDefinition struct {
+ // "current.txt" or "removed.txt"
+ TxtFilename string
+ // The module for the non-updatable / non-module part of the api.
+ BaseTxt string
+ // The list of modules that are relevant for this merged txt.
+ Modules []string
+ // The output tag for each module to use.e.g. {.public.api.txt} for current.txt
+ ModuleTag string
+ // public, system, module-lib or system-server
+ Scope string
+}
+
+func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) {
+ metalavaCmd := "$(location metalava)"
+ // Silence reflection warnings. See b/168689341
+ metalavaCmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
+ metalavaCmd += " --quiet --no-banner --format=v2 "
+
+ filename := txt.TxtFilename
+ if txt.Scope != "public" {
+ filename = txt.Scope + "-" + filename
+ }
+
+ props := genruleProps{}
+ props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename)
+ props.Tools = []string{"metalava"}
+ props.Out = []string{txt.TxtFilename}
+ props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --api $(out)")
+ props.Srcs = createSrcs(txt.BaseTxt, txt.Modules, txt.ModuleTag)
+ props.Dists = []android.Dist{
+ {
+ Targets: []string{"droidcore"},
+ Dir: proptools.StringPtr("api"),
+ Dest: proptools.StringPtr(filename),
+ },
+ {
+ Targets: []string{"sdk"},
+ Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"),
+ Dest: proptools.StringPtr(txt.TxtFilename),
+ },
+ }
+ props.Visibility = []string{"//visibility:public"}
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
+func createMergedStubsSrcjar(ctx android.LoadHookContext, modules []string) {
+ props := genruleProps{}
+ props.Name = proptools.StringPtr(ctx.ModuleName() + "-current.srcjar")
+ props.Tools = []string{"merge_zips"}
+ props.Out = []string{"current.srcjar"}
+ props.Cmd = proptools.StringPtr("$(location merge_zips) $(out) $(in)")
+ props.Srcs = createSrcs(":api-stubs-docs-non-updatable", modules, "{.public.stubs.source}")
+ props.Visibility = []string{"//visibility:private"} // Used by make module in //development, mind
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
+func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
+ props := genruleProps{}
+ props.Name = proptools.StringPtr("api-versions-xml-public-filtered")
+ props.Tools = []string{"api_versions_trimmer"}
+ props.Out = []string{"api-versions-public-filtered.xml"}
+ props.Cmd = proptools.StringPtr("$(location api_versions_trimmer) $(out) $(in)")
+ // Note: order matters: first parameter is the full api-versions.xml
+ // after that the stubs files in any order
+ // stubs files are all modules that export API surfaces EXCEPT ART
+ props.Srcs = createSrcs(":framework-doc-stubs{.api_versions.xml}", modules, ".stubs{.jar}")
+ props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
+func createSrcs(base string, modules []string, tag string) []string {
+ a := make([]string, 0, len(modules)+1)
+ a = append(a, base)
+ for _, module := range modules {
+ a = append(a, ":"+module+tag)
+ }
+ return a
+}
+
+func remove(s []string, v string) []string {
+ s2 := make([]string, 0, len(s))
+ for _, sv := range s {
+ if sv != v {
+ s2 = append(s2, sv)
+ }
+ }
+ return s2
+}
+
+func createMergedTxts(ctx android.LoadHookContext, props CombinedApisProperties) {
+ var textFiles []MergedTxtDefinition
+ tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
+ for i, f := range []string{"current.txt", "removed.txt"} {
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-" + f,
+ Modules: props.Public,
+ ModuleTag: "{.public" + tagSuffix[i],
+ Scope: "public",
+ })
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-system-" + f,
+ Modules: props.System,
+ ModuleTag: "{.system" + tagSuffix[i],
+ Scope: "system",
+ })
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-module-lib-" + f,
+ Modules: props.Module_lib,
+ ModuleTag: "{.module-lib" + tagSuffix[i],
+ Scope: "module-lib",
+ })
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-system-server-" + f,
+ Modules: props.System_server,
+ ModuleTag: "{.system-server" + tagSuffix[i],
+ Scope: "system-server",
+ })
+ }
+ for _, txt := range textFiles {
+ createMergedTxt(ctx, txt)
+ }
+}
+
+func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
+ createMergedTxts(ctx, a.properties)
+
+ createMergedStubsSrcjar(ctx, a.properties.Public)
+
+ // For the filtered api versions, we prune all APIs except art module's APIs.
+ createFilteredApiVersions(ctx, remove(a.properties.Public, a.properties.Art_module))
+}
+
+func combinedApisModuleFactory() android.Module {
+ module := &CombinedApis{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) })
+ return module
+}
diff --git a/core/api/current.txt b/core/api/current.txt
index 7f0ff7f9955e..407855b107cd 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -40266,6 +40266,7 @@ package android.telecom {
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
+ field public static final int PROPERTY_TETHERED_CALL = 32768; // 0x8000
field public static final int PROPERTY_VOIP_AUDIO_MODE = 4096; // 0x1000
field public static final int PROPERTY_WIFI = 8; // 0x8
}
@@ -40294,6 +40295,7 @@ package android.telecom {
field @NonNull public static final android.os.Parcelable.Creator<android.telecom.CallAudioState> CREATOR;
field public static final int ROUTE_BLUETOOTH = 2; // 0x2
field public static final int ROUTE_EARPIECE = 1; // 0x1
+ field public static final int ROUTE_EXTERNAL = 16; // 0x10
field public static final int ROUTE_SPEAKER = 8; // 0x8
field public static final int ROUTE_WIRED_HEADSET = 4; // 0x4
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
@@ -40568,6 +40570,7 @@ package android.telecom {
field public static final int PROPERTY_IS_RTT = 256; // 0x100
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
+ field public static final int PROPERTY_TETHERED_CALL = 16384; // 0x4000
field public static final int PROPERTY_WIFI = 8; // 0x8
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_DIALING = 3; // 0x3
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 67567a657e2e..3a3813f29d89 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -165,6 +165,7 @@ package android {
field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
field public static final String MANAGE_ROTATION_RESOLVER = "android.permission.MANAGE_ROTATION_RESOLVER";
+ field public static final String MANAGE_SAFETY_CENTER = "android.permission.MANAGE_SAFETY_CENTER";
field public static final String MANAGE_SEARCH_UI = "android.permission.MANAGE_SEARCH_UI";
field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY";
field public static final String MANAGE_SMARTSPACE = "android.permission.MANAGE_SMARTSPACE";
@@ -403,6 +404,7 @@ package android {
field public static final int config_systemAmbientAudioIntelligence = 17039411; // 0x1040033
field public static final int config_systemAppProtectionService;
field public static final int config_systemAudioIntelligence = 17039412; // 0x1040034
+ field public static final int config_systemAutomotiveCalendarSyncManager;
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
field public static final int config_systemCompanionDeviceProvider = 17039417; // 0x1040039
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 34ee0aa55e51..66250fcebe92 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -36,6 +36,7 @@ package android {
field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
+ field public static final String REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL = "android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL";
field public static final String SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS = "android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS";
field public static final String START_TASKS_FROM_RECENTS = "android.permission.START_TASKS_FROM_RECENTS";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
@@ -66,6 +67,7 @@ package android {
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
+ field public static final int config_systemAutomotiveCalendarSyncManager;
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
field public static final int config_systemGallery = 17039399; // 0x1040027
@@ -2044,6 +2046,7 @@ package android.permission {
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean);
method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
+ method public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String, int);
}
}
@@ -2317,6 +2320,7 @@ package android.service.dreams {
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onStartDream(@NonNull android.view.WindowManager.LayoutParams);
method public final void requestExit();
+ method public final boolean shouldShowComplications();
}
}
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index a821dadf4948..857c5416b3bc 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -525,7 +525,7 @@ public final class GestureDescription {
public GestureStep(Parcel parcel) {
timeSinceGestureStart = parcel.readLong();
Parcelable[] parcelables =
- parcel.readParcelableArray(TouchPoint.class.getClassLoader());
+ parcel.readParcelableArray(TouchPoint.class.getClassLoader(), TouchPoint.class);
numTouchPoints = (parcelables == null) ? 0 : parcelables.length;
touchPoints = new TouchPoint[numTouchPoints];
for (int i = 0; i < numTouchPoints; i++) {
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index 63fcb49fff1b..8fd41f2c9e05 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -505,7 +505,7 @@ public class RestrictionEntry implements Parcelable {
mChoiceValues = in.readStringArray();
mCurrentValue = in.readString();
mCurrentValues = in.readStringArray();
- Parcelable[] parcelables = in.readParcelableArray(null);
+ Parcelable[] parcelables = in.readParcelableArray(null, RestrictionEntry.class);
if (parcelables != null) {
mRestrictions = new RestrictionEntry[parcelables.length];
for (int i = 0; i < parcelables.length; i++) {
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index 7714dd80f910..243f80187185 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -38,6 +38,7 @@ public class AdbManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_STATUS";
@@ -46,6 +47,7 @@ public class AdbManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES";
@@ -59,6 +61,7 @@ public class AdbManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT";
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 86ae3a311c9b..5df64e3cca9e 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -599,7 +599,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
synchronized (mSurfacesLock) {
mSurfaceSet.clear();
- Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader());
+ Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader(),
+ Surface.class);
if (parcelableArray != null) {
for (Parcelable p : parcelableArray) {
Surface s = (Surface) p;
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 6ea2ac414704..4cc001a40146 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -436,7 +436,8 @@ public class RadioManager {
mNumAudioSources = in.readInt();
mIsInitializationRequired = in.readInt() == 1;
mIsCaptureSupported = in.readInt() == 1;
- Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader());
+ Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader(),
+ BandDescriptor.class);
mBands = new BandDescriptor[tmp.length];
for (int i = 0; i < tmp.length; i++) {
mBands[i] = (BandDescriptor) tmp[i];
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 4a94c32501a1..90b5e518ef1b 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -67,6 +67,8 @@ interface IPermissionManager {
void revokeRuntimePermission(String packageName, String permissionName, int userId,
String reason);
+ void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId);
+
boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
int userId);
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 3ea50e98879b..4f2287606e05 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -1362,6 +1362,26 @@ public final class PermissionManager {
return false;
}
+ /**
+ * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
+ * USED in CTS or local tests.
+ *
+ * @param packageName The package to be revoked
+ * @param userId The user for which to revoke
+ *
+ * @hide
+ */
+ @TestApi
+ public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String packageName,
+ int userId) {
+ try {
+ mPermissionManager.revokePostNotificationPermissionWithoutKillForTest(packageName,
+ userId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
/* @hide */
private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) {
final IActivityManager am = ActivityManager.getService();
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 9bdfd8e69c00..9d0c8d82ed0d 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -240,7 +240,7 @@ public final class PrintJobInfo implements Parcelable {
mTag = parcel.readString();
mCreationTime = parcel.readLong();
mCopies = parcel.readInt();
- Parcelable[] parcelables = parcel.readParcelableArray(null);
+ Parcelable[] parcelables = parcel.readParcelableArray(null, PageRange.class);
if (parcelables != null) {
mPageRanges = new PageRange[parcelables.length];
for (int i = 0; i < parcelables.length; i++) {
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 50f9d8ac2958..163d6ed4b18b 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -35,6 +35,7 @@ import android.view.WindowManager;
public abstract class DreamOverlayService extends Service {
private static final String TAG = "DreamOverlayService";
private static final boolean DEBUG = false;
+ private boolean mShowComplications;
private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
@Override
@@ -53,6 +54,8 @@ public abstract class DreamOverlayService extends Service {
@Nullable
@Override
public final IBinder onBind(@NonNull Intent intent) {
+ mShowComplications = intent.getBooleanExtra(DreamService.EXTRA_SHOW_COMPLICATIONS,
+ DreamService.DEFAULT_SHOW_COMPLICATIONS);
return mDreamOverlay.asBinder();
}
@@ -74,4 +77,11 @@ public abstract class DreamOverlayService extends Service {
Log.e(TAG, "Could not request exit:" + e);
}
}
+
+ /**
+ * Returns whether to show complications on the dream overlay.
+ */
+ public final boolean shouldShowComplications() {
+ return mShowComplications;
+ }
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 4ae3d7de26c2..133e384dfa8f 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -189,6 +189,19 @@ public class DreamService extends Service implements Window.Callback {
*/
public static final String DREAM_META_DATA = "android.service.dream";
+ /**
+ * Extra containing a boolean for whether to show complications on the overlay.
+ * @hide
+ */
+ public static final String EXTRA_SHOW_COMPLICATIONS =
+ "android.service.dreams.SHOW_COMPLICATIONS";
+
+ /**
+ * The default value for whether to show complications on the overlay.
+ * @hide
+ */
+ public static final boolean DEFAULT_SHOW_COMPLICATIONS = true;
+
private final IDreamManager mDreamManager;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private IBinder mDreamToken;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
index 733c0afff367..0130ef47010a 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
@@ -190,7 +190,7 @@ public class PresResInstanceInfo implements Parcelable{
mResInstanceState = source.readInt();
mPresentityUri = source.readString();
Parcelable[] tempParcelableArray = source.readParcelableArray(
- PresTupleInfo.class.getClassLoader());
+ PresTupleInfo.class.getClassLoader(), PresTupleInfo.class);
mTupleInfoArray = new PresTupleInfo[] {};
if(tempParcelableArray != null) {
mTupleInfoArray = Arrays.copyOf(tempParcelableArray, tempParcelableArray.length,
diff --git a/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java b/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
index 289daee26f52..301de2d3529e 100644
--- a/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
+++ b/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
@@ -239,7 +239,8 @@ public class DisplayResolveInfo implements TargetInfo, Parcelable {
mExtendedInfo = in.readCharSequence();
mResolvedIntent = in.readParcelable(null /* ClassLoader */, android.content.Intent.class);
mSourceIntents.addAll(
- Arrays.asList((Intent[]) in.readParcelableArray(null /* ClassLoader */)));
+ Arrays.asList((Intent[]) in.readParcelableArray(null /* ClassLoader */,
+ Intent.class)));
mIsSuspended = in.readBoolean();
mPinned = in.readBoolean();
mResolveInfo = in.readParcelable(null /* ClassLoader */, android.content.pm.ResolveInfo.class);
diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java
index 84391c169941..0443ad03b6ea 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.java
+++ b/core/java/com/android/internal/infra/AndroidFuture.java
@@ -24,7 +24,6 @@ import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
-import android.util.EventLog;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -585,6 +584,7 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
/**
* @see #writeThrowable
*/
+ @SuppressWarnings("UnsafeParcelApi")
private static @Nullable Throwable readThrowable(@NonNull Parcel parcel) {
final boolean hasThrowable = parcel.readBoolean();
if (!hasThrowable) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index dfcfd5f295e2..ae5414d4fa47 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4438,6 +4438,12 @@
<permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
android:protectionLevel="signature|installer|verifier" />
+ <!-- @TestApi Allows an application to revoke the POST_NOTIFICATIONS permission from an app
+ without killing the app. Only granted to the shell.
+ @hide -->
+ <permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows the system to read runtime permission state.
@hide -->
<permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
@@ -6094,7 +6100,7 @@
@hide -->
<permission android:name="android.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES"
android:protectionLevel="signature|role" />
-
+
<!-- @SystemApi Allows an app to read whether SafetyCenter is enabled/disabled.
<p>Protection level: signature|privileged
@hide
@@ -6102,6 +6108,14 @@
<permission android:name="android.permission.READ_SAFETY_CENTER_STATUS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Required to access the safety center internal APIs using the
+ {@link android.safetycenter.SafetyCenterManager}.
+ <p>Protection level: internal|installer|role
+ @hide
+ -->
+ <permission android:name="android.permission.MANAGE_SAFETY_CENTER"
+ android:protectionLevel="internal|installer|role" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5470e33df12a..2836c9816886 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2133,6 +2133,8 @@
<string name="config_deviceManager" translatable="false"></string>
<!-- The name of the package that will hold the app protection service role. -->
<string name="config_systemAppProtectionService" translatable="false"></string>
+ <!-- The name of the package that will hold the system calendar sync manager role. -->
+ <string name="config_systemAutomotiveCalendarSyncManager" translatable="false"></string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3bd8ec3943bc..5fa7409150ab 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3274,6 +3274,8 @@
<public name="config_deviceManager" />
<!-- @hide @SystemApi -->
<public name="config_systemAppProtectionService" />
+ <!-- @hide @SystemApi @TestApi -->
+ <public name="config_systemAutomotiveCalendarSyncManager" />
</staging-public-group>
<staging-public-group type="dimen" first-id="0x01db0000">
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 3b4b9e5dd33b..878d302d481e 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -519,9 +519,8 @@ applications that come with the platform
<permission name="android.permission.MANAGE_VOICE_KEYPHRASES" />
<!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
<permission name="android.permission.LOCK_DEVICE" />
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
+ <!-- Permissions required for CTS test - CtsSafetyCenterTestCases -->
<permission name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
<permission name="android.permission.READ_SAFETY_CENTER_STATUS" />
</privapp-permissions>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 9374da4c4fab..f878a46d26f2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -231,8 +231,9 @@ public class BubbleFlyoutView extends FrameLayout {
* Fade animation for consecutive flyouts.
*/
void animateUpdate(Bubble.FlyoutMessage flyoutMessage, PointF stackPos,
- boolean hideDot, Runnable onHide) {
+ boolean hideDot, float[] dotCenter, Runnable onHide) {
mOnHide = onHide;
+ mDotCenter = dotCenter;
final Runnable afterFadeOut = () -> {
updateFlyoutMessage(flyoutMessage);
// Wait for TextViews to layout with updated height.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 7bf4439410f9..d5d8b71056d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -2516,6 +2516,7 @@ public class BubbleStackView extends FrameLayout
if (mFlyout.getVisibility() == View.VISIBLE) {
mFlyout.animateUpdate(bubble.getFlyoutMessage(),
mStackAnimationController.getStackPosition(), !bubble.showDot(),
+ bubble.getIconView().getDotCenter(),
mAfterFlyoutHidden /* onHide */);
} else {
mFlyout.setVisibility(INVISIBLE);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index dd07f91ef38b..0c70821527dd 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -608,11 +608,14 @@
<!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
<uses-permission android:name="android.permission.LOCK_DEVICE" />
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
+ <!-- Permissions required for CTS test - CtsSafetyCenterTestCases -->
<uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
-
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
<uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" />
+ <uses-permission android:name="android.permission.MANAGE_SAFETY_CENTER" />
+
+
+ <!-- Permission required for CTS test - Notification test suite -->
+ <uses-permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL" />
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/Shell/res/values-watch/strings.xml b/packages/Shell/res/values-watch/strings.xml
new file mode 100644
index 000000000000..5f7bfcb25d85
--- /dev/null
+++ b/packages/Shell/res/values-watch/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title for Bug report notification indicating the number of the bug report and the
+ percentage complete. Example: "Bug report #3 is 20% complete" [CHAR LIMIT=50] -->
+ <string name="bugreport_in_progress_title">Bug report <xliff:g id="id" example="#3">#%1$d</xliff:g> is <xliff:g id="percentage" example="20%">%2$s</xliff:g> complete</string>
+</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index ee9d4301770a..c5a01a1c2b93 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -199,6 +199,15 @@ public class BugreportProgressService extends Service {
*/
private static final String BUGREPORT_DIR = "bugreports";
+ /**
+ * The directory in which System Trace files from the native System Tracing app are stored for
+ * Wear devices.
+ */
+ private static final String WEAR_SYSTEM_TRACES_DIRECTORY_ON_DEVICE = "data/local/traces/";
+
+ /** The directory that contains System Traces in bugreports that include System Traces. */
+ private static final String WEAR_SYSTEM_TRACES_DIRECTORY_IN_BUGREPORT = "systraces/";
+
private static final String NOTIFICATION_CHANNEL_ID = "bugreports";
/**
@@ -724,14 +733,16 @@ public class BugreportProgressService extends Service {
nf.setMaximumFractionDigits(2);
final String percentageText = nf.format((double) info.progress.intValue() / 100);
- String title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
-
- // TODO: Remove this workaround when notification progress is implemented on Wear.
+ final String title;
if (mIsWatch) {
+ // TODO: Remove this workaround when notification progress is implemented on Wear.
nf.setMinimumFractionDigits(0);
nf.setMaximumFractionDigits(0);
final String watchPercentageText = nf.format((double) info.progress.intValue() / 100);
- title = title + "\n" + watchPercentageText;
+ title = mContext.getString(
+ R.string.bugreport_in_progress_title, info.id, watchPercentageText);
+ } else {
+ title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
}
final String name =
@@ -1456,6 +1467,16 @@ public class BugreportProgressService extends Service {
}
}
+ /** Returns an array of the system trace files collected by the System Tracing native app. */
+ private static File[] getSystemTraceFiles() {
+ try {
+ return new File(WEAR_SYSTEM_TRACES_DIRECTORY_ON_DEVICE).listFiles();
+ } catch (SecurityException e) {
+ Log.e(TAG, "Error getting system trace files.", e);
+ return new File[]{};
+ }
+ }
+
/**
* Adds the user-provided info into the bugreport zip file.
* <p>
@@ -1475,8 +1496,17 @@ public class BugreportProgressService extends Service {
Log.wtf(TAG, "addDetailsToZipFile(): no bugreportFile on " + info);
return;
}
- if (TextUtils.isEmpty(info.getTitle()) && TextUtils.isEmpty(info.getDescription())) {
- Log.d(TAG, "Not touching zip file since neither title nor description are set");
+
+ File[] systemTracesToIncludeInBugreport = new File[] {};
+ if (mIsWatch) {
+ systemTracesToIncludeInBugreport = getSystemTraceFiles();
+ Log.d(TAG, "Found " + systemTracesToIncludeInBugreport.length + " system traces.");
+ }
+
+ if (TextUtils.isEmpty(info.getTitle())
+ && TextUtils.isEmpty(info.getDescription())
+ && systemTracesToIncludeInBugreport.length == 0) {
+ Log.d(TAG, "Not touching zip file: no detail to add.");
return;
}
if (info.addedDetailsToZip || info.addingDetailsToZip) {
@@ -1487,7 +1517,10 @@ public class BugreportProgressService extends Service {
// It's not possible to add a new entry into an existing file, so we need to create a new
// zip, copy all entries, then rename it.
- sendBugreportBeingUpdatedNotification(mContext, info.id); // ...and that takes time
+ if (!mIsWatch) {
+ // TODO(b/184854609): re-introduce this notification for Wear.
+ sendBugreportBeingUpdatedNotification(mContext, info.id); // ...and that takes time
+ }
final File dir = info.bugreportFile.getParentFile();
final File tmpZip = new File(dir, "tmp-" + info.bugreportFile.getName());
@@ -1508,6 +1541,13 @@ public class BugreportProgressService extends Service {
}
// Then add the user-provided info.
+ if (systemTracesToIncludeInBugreport.length != 0) {
+ for (File trace : systemTracesToIncludeInBugreport) {
+ addEntry(zos,
+ WEAR_SYSTEM_TRACES_DIRECTORY_IN_BUGREPORT + trace.getName(),
+ new FileInputStream(trace));
+ }
+ }
addEntry(zos, "title.txt", info.getTitle());
addEntry(zos, "description.txt", info.getDescription());
} catch (IOException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4658a745b680..094b1927480d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -100,6 +100,7 @@ import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.CoreStartable;
+import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -2345,16 +2346,20 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// Block the panel from expanding, in case we were doing a swipe to dismiss gesture.
mKeyguardViewControllerLazy.get().blockPanelExpansionFromCurrentTouch();
final boolean wasShowing = mShowing;
- onKeyguardExitFinished();
+ InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
- if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) {
- mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation();
- }
+ // Post layout changes to the next frame, so we don't hang at the end of the animation.
+ DejankUtils.postAfterTraversal(() -> {
+ onKeyguardExitFinished();
- finishSurfaceBehindRemoteAnimation(cancelled);
- mSurfaceBehindRemoteAnimationRequested = false;
- mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation();
- InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
+ if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) {
+ mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation();
+ }
+
+ finishSurfaceBehindRemoteAnimation(cancelled);
+ mSurfaceBehindRemoteAnimationRequested = false;
+ mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation();
+ });
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 8cd8e4d7382d..c0b7271c6de7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -16,12 +16,15 @@
package com.android.systemui.dreams;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Intent;
import android.os.IBinder;
+import android.service.dreams.DreamService;
import android.service.dreams.IDreamOverlay;
import android.service.dreams.IDreamOverlayCallback;
import android.testing.AndroidTestingRunner;
@@ -195,4 +198,22 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
mService.onDestroy();
verify(mDreamOverlayStateController).removeCallback(callbackCapture.getValue());
}
+
+ @Test
+ public void testShouldShowComplicationsTrueByDefault() {
+ assertThat(mService.shouldShowComplications()).isTrue();
+
+ mService.onBind(new Intent());
+
+ assertThat(mService.shouldShowComplications()).isTrue();
+ }
+
+ @Test
+ public void testShouldShowComplicationsSetByIntentExtra() {
+ final Intent intent = new Intent();
+ intent.putExtra(DreamService.EXTRA_SHOW_COMPLICATIONS, false);
+ mService.onBind(intent);
+
+ assertThat(mService.shouldShowComplications()).isFalse();
+ }
}
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 5f295ac8f20d..e7f4de2a0588 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -26,6 +26,7 @@ import android.os.Environment;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -47,6 +48,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -94,6 +96,7 @@ public final class SystemServiceManager implements Dumpable {
// Services that should receive lifecycle events.
private List<SystemService> mServices;
+ private Set<String> mServiceClassnames;
private int mCurrentPhase = -1;
@@ -116,6 +119,7 @@ public final class SystemServiceManager implements Dumpable {
SystemServiceManager(Context context) {
mContext = context;
mServices = new ArrayList<>();
+ mServiceClassnames = new ArraySet<>();
// Disable using the thread pool for low ram devices
sUseLifecycleThreadPool = sUseLifecycleThreadPool
&& !ActivityManager.isLowRamDeviceStatic();
@@ -210,8 +214,17 @@ public final class SystemServiceManager implements Dumpable {
}
public void startService(@NonNull final SystemService service) {
+ // Check if already started
+ String className = service.getClass().getName();
+ if (mServiceClassnames.contains(className)) {
+ Slog.i(TAG, "Not starting an already started service " + className);
+ return;
+ }
+ mServiceClassnames.add(className);
+
// Register it.
mServices.add(service);
+
// Start it.
long time = SystemClock.elapsedRealtime();
try {
@@ -225,6 +238,7 @@ public final class SystemServiceManager implements Dumpable {
/** Disallow starting new services after this call. */
void sealStartedServices() {
+ mServiceClassnames = Collections.emptySet();
mServices = Collections.unmodifiableList(mServices);
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index f591b26f1770..297d28dadde3 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -18,6 +18,7 @@ package com.android.server.adb;
import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
+import android.annotation.NonNull;
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.Notification;
@@ -170,6 +171,12 @@ public class AdbDebuggingManager {
mAdbConnectionInfo = new AdbConnectionInfo();
}
+ static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent,
+ @NonNull UserHandle userHandle) {
+ context.sendBroadcastAsUser(intent, userHandle,
+ android.Manifest.permission.MANAGE_DEBUGGING);
+ }
+
class PairingThread extends Thread implements NsdManager.RegistrationListener {
private NsdManager mNsdManager;
private String mPublicKey;
@@ -1278,7 +1285,7 @@ public class AdbDebuggingManager {
? AdbManager.WIRELESS_STATUS_CONNECTED
: AdbManager.WIRELESS_STATUS_DISCONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void onAdbdWifiServerConnected(int port) {
@@ -1350,7 +1357,8 @@ public class AdbDebuggingManager {
if (publicKey == null) {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+ UserHandle.ALL);
} else {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
@@ -1366,7 +1374,8 @@ public class AdbDebuggingManager {
device.guid = hostname;
device.connected = false;
intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+ UserHandle.ALL);
// Add the key into the keystore
mAdbKeyStore.setLastConnectionTime(publicKey,
System.currentTimeMillis());
@@ -1380,14 +1389,14 @@ public class AdbDebuggingManager {
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
AdbManager.WIRELESS_STATUS_CONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void sendPairedDevicesToUI(Map<String, PairDevice> devices) {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
// Map is not serializable, so need to downcast
intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void updateUIPairCode(String code) {
@@ -1397,7 +1406,7 @@ public class AdbDebuggingManager {
intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
AdbManager.WIRELESS_STATUS_PAIRING_CODE);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
}
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 7a4d2ce50cd3..2845fbfc6ebf 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -459,7 +459,7 @@ public class AdbService extends IAdbManager.Stub {
? AdbManager.WIRELESS_STATUS_CONNECTED
: AdbManager.WIRELESS_STATUS_DISCONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
Slog.i(TAG, "sent port broadcast port=" + port);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 8d56cda239bc..85e54f3766ea 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -551,6 +551,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
+ public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
+ mPermissionManagerServiceImpl.revokePostNotificationPermissionWithoutKillForTest(
+ packageName, userId);
+ }
+
+ @Override
public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
int userId) {
return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index c1bedb260dbd..21cb2c96fc6a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -167,6 +167,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
private static final String TAG = "PackageManager";
private static final String LOG_TAG = PermissionManagerServiceImpl.class.getSimpleName();
+ private static final String SKIP_KILL_APP_REASON_NOTIFICATION_TEST = "skip permission revoke "
+ + "app kill for notification test";
+
+
private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);
// For automotive products, CarService enforces allow-listing of the privileged permissions
@@ -320,11 +324,15 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
mPackageManagerInt.writeSettings(true);
}
@Override
- public void onPermissionRevoked(int uid, int userId, String reason) {
+ public void onPermissionRevoked(int uid, int userId, String reason, boolean overrideKill) {
mOnPermissionChangeListeners.onPermissionsChanged(uid);
// Critical; after this call the application should never have the permission
mPackageManagerInt.writeSettings(false);
+ if (overrideKill) {
+ return;
+ }
+
final int appId = UserHandle.getAppId(uid);
if (reason == null) {
mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
@@ -1438,9 +1446,29 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
reason, mDefaultPermissionCallback);
}
+ @Override
+ public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final boolean overridePolicy =
+ checkUidPermission(callingUid, ADJUST_RUNTIME_PERMISSIONS_POLICY)
+ == PackageManager.PERMISSION_GRANTED;
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL, "");
+ revokeRuntimePermissionInternal(packageName, Manifest.permission.POST_NOTIFICATIONS,
+ overridePolicy, true, callingUid, userId,
+ SKIP_KILL_APP_REASON_NOTIFICATION_TEST, mDefaultPermissionCallback);
+ }
+
private void revokeRuntimePermissionInternal(String packageName, String permName,
- boolean overridePolicy, int callingUid, final int userId, String reason,
- PermissionCallback callback) {
+ boolean overridePolicy, int callingUid, final int userId,
+ String reason, PermissionCallback callback) {
+ revokeRuntimePermissionInternal(packageName, permName, overridePolicy, false, callingUid,
+ userId, reason, callback);
+ }
+
+ private void revokeRuntimePermissionInternal(String packageName, String permName,
+ boolean overridePolicy, boolean overrideKill, int callingUid, final int userId,
+ String reason, PermissionCallback callback) {
if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
&& PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is revoking " + packageName + " "
@@ -1552,7 +1580,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
if (callback != null) {
if (isRuntimePermission) {
callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
- reason);
+ reason, overrideKill);
} else {
mDefaultPermissionCallback.onInstallPermissionRevoked();
}
@@ -5197,7 +5225,11 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
public void onPermissionChanged() {}
public void onPermissionGranted(int uid, @UserIdInt int userId) {}
public void onInstallPermissionGranted() {}
- public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {}
+ public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {
+ onPermissionRevoked(uid, userId, reason, false);
+ }
+ public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason,
+ boolean overrideKill) {}
public void onInstallPermissionRevoked() {}
public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {}
public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index d2018f26d04a..3771f030aefa 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -318,6 +318,15 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte
String reason);
/**
+ * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
+ * USED in CTS or local tests.
+ *
+ * @param packageName The package to be revoked
+ * @param userId The user for which to revoke
+ */
+ void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId);
+
+ /**
* Get whether you should show UI with rationale for requesting a permission. You should do this
* only if you do not have the permission and the context in which the permission is requested
* does not clearly communicate to the user what would be the benefit from grating this
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b91d3a8525e5..5a420caa176c 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -983,29 +983,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mWmService.checkDrawnWindowsLocked();
}
- final int N = mWmService.mPendingRemove.size();
- if (N > 0) {
- if (mWmService.mPendingRemoveTmp.length < N) {
- mWmService.mPendingRemoveTmp = new WindowState[N + 10];
- }
- mWmService.mPendingRemove.toArray(mWmService.mPendingRemoveTmp);
- mWmService.mPendingRemove.clear();
- ArrayList<DisplayContent> displayList = new ArrayList();
- for (i = 0; i < N; i++) {
- final WindowState w = mWmService.mPendingRemoveTmp[i];
- w.removeImmediately();
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && !displayList.contains(displayContent)) {
- displayList.add(displayContent);
- }
- }
-
- for (int j = displayList.size() - 1; j >= 0; --j) {
- final DisplayContent dc = displayList.get(j);
- dc.assignWindowLayers(true /*setLayoutNeeded*/);
- }
- }
-
forAllDisplays(dc -> {
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
dc.updateSystemGestureExclusion();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7be128b53f8c..b5e6f49146f1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -222,7 +222,6 @@ import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.MergedConfiguration;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.TypedValue;
@@ -588,20 +587,6 @@ public class WindowManagerService extends IWindowManager.Stub
final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
/**
- * Windows whose animations have ended and now must be removed.
- */
- final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
-
- /**
- * Used when processing mPendingRemove to avoid working on the original array.
- */
- WindowState[] mPendingRemoveTmp = new WindowState[20];
-
- // TODO: use WindowProcessController once go/wm-unified is done.
- /** Mapping of process pids to configurations */
- final SparseArray<Configuration> mProcessConfigurations = new SparseArray<>();
-
- /**
* Windows whose surface should be destroyed.
*/
final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
@@ -2038,7 +2023,6 @@ public class WindowManagerService extends IWindowManager.Stub
dc.mWinRemovedSinceNullFocus.add(win);
}
mEmbeddedWindowController.onWindowRemoved(win);
- mPendingRemove.remove(win);
mResizingWindows.remove(win);
updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
mWindowsChanged = true;
@@ -6342,23 +6326,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
- if (mPendingRemove.size() > 0) {
- pw.println();
- pw.println(" Remove pending for:");
- for (int i=mPendingRemove.size()-1; i>=0; i--) {
- WindowState w = mPendingRemove.get(i);
- if (windows == null || windows.contains(w)) {
- pw.print(" Remove #"); pw.print(i); pw.print(' ');
- pw.print(w);
- if (dumpAll) {
- pw.println(":");
- w.dump(pw, " ", true);
- } else {
- pw.println();
- }
- }
- }
- }
if (mForceRemoves != null && mForceRemoves.size() > 0) {
pw.println();
pw.println(" Windows force removing:");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6acd4548392a..5bbe2cd853f6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4835,15 +4835,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (hasSurface) {
mWmService.mDestroySurface.add(this);
}
- if (mRemoveOnExit) {
- mWmService.mPendingRemove.add(this);
- mRemoveOnExit = false;
- }
}
mAnimatingExit = false;
getDisplayContent().mWallpaperController.hideWallpapers(this);
}
+ @Override
+ boolean handleCompleteDeferredRemoval() {
+ if (mRemoveOnExit) {
+ mRemoveOnExit = false;
+ removeImmediately();
+ }
+ return super.handleCompleteDeferredRemoval();
+ }
+
boolean clearAnimatingFlags() {
boolean didSomething = false;
// We don't want to clear it out for windows that get replaced, because the
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4673a6905fc0..e0b8672a0ac0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -3053,7 +3053,6 @@ public final class SystemServer implements Dumpable {
private void startApexServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startApexServices");
Map<String, String> services = ApexManager.getInstance().getApexSystemServices();
- // TODO(satayev): filter out already started services
// TODO(satayev): introduce android:order for services coming the same apexes
for (String name : new TreeSet<>(services.keySet())) {
String jarPath = services.get(name);
diff --git a/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java b/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java
index 4413dc8b9734..f92f5ead2c3b 100644
--- a/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java
@@ -23,6 +23,7 @@ import android.test.AndroidTestCase;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -32,24 +33,52 @@ public class SystemServiceManagerTest extends AndroidTestCase {
private static final String TAG = "SystemServiceManagerTest";
+ private final SystemServiceManager mSystemServiceManager =
+ new SystemServiceManager(getContext());
+
@Test
public void testSealStartedServices() throws Exception {
- SystemServiceManager manager = new SystemServiceManager(getContext());
// must be effectively final, since it's changed from inner class below
AtomicBoolean serviceStarted = new AtomicBoolean(false);
- SystemService service = new SystemService(getContext()) {
+ SystemService service1 = new SystemService(getContext()) {
@Override
public void onStart() {
serviceStarted.set(true);
}
};
+ SystemService service2 = new SystemService(getContext()) {
+ @Override
+ public void onStart() {
+ throw new IllegalStateException("Second service must not be called");
+ }
+ };
// started services have their #onStart methods called
- manager.startService(service);
+ mSystemServiceManager.startService(service1);
assertTrue(serviceStarted.get());
// however, after locking started services, it is not possible to start a new service
- manager.sealStartedServices();
- assertThrows(UnsupportedOperationException.class, () -> manager.startService(service));
+ mSystemServiceManager.sealStartedServices();
+ assertThrows(UnsupportedOperationException.class,
+ () -> mSystemServiceManager.startService(service2));
}
+
+ @Test
+ public void testDuplicateServices() throws Exception {
+ AtomicInteger counter = new AtomicInteger(0);
+ SystemService service = new SystemService(getContext()) {
+ @Override
+ public void onStart() {
+ counter.incrementAndGet();
+ }
+ };
+
+ mSystemServiceManager.startService(service);
+ assertEquals(1, counter.get());
+
+ // manager does not start the same service twice
+ mSystemServiceManager.startService(service);
+ assertEquals(1, counter.get());
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index cffff66b64f1..02cf971a8076 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -23,7 +23,14 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.debug.AdbManager;
+import android.debug.IAdbManager;
+import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
@@ -105,6 +112,7 @@ public final class AdbDebuggingManagerTest {
public void tearDown() throws Exception {
mKeyStore.deleteKeyStore();
setAllowedConnectionTime(mOriginalAllowedConnectionTime);
+ dropShellPermissionIdentity();
}
/**
@@ -813,6 +821,108 @@ public final class AdbDebuggingManagerTest {
return hasAtLeastOneLetter;
}
+ CountDownLatch mAdbActionLatch = new CountDownLatch(1);
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.i(TAG, "Received intent action=" + action);
+ if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ Log.i(TAG, "action=" + action + " paired_device=" + intent.getSerializableExtra(
+ AdbManager.WIRELESS_DEVICES_EXTRA).toString());
+ mAdbActionLatch.countDown();
+ } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_DISCONNECTED);
+ Log.i(TAG, "action=" + action + " status=" + status);
+ mAdbActionLatch.countDown();
+ } else if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ Integer res = intent.getIntExtra(
+ AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_FAIL);
+ Log.i(TAG, "action=" + action + " result=" + res);
+
+ if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) {
+ String pairingCode = intent.getStringExtra(
+ AdbManager.WIRELESS_PAIRING_CODE_EXTRA);
+ Log.i(TAG, "pairingCode=" + pairingCode);
+ } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) {
+ int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0);
+ Log.i(TAG, "port=" + port);
+ }
+ mAdbActionLatch.countDown();
+ }
+ }
+ };
+
+ private void adoptShellPermissionIdentity() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.MANAGE_DEBUGGING);
+ }
+
+ private void dropShellPermissionIdentity() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ @Test
+ public void testBroadcastReceiverWithPermissions() throws Exception {
+ adoptShellPermissionIdentity();
+ final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+ ServiceManager.getService(Context.ADB_SERVICE));
+ IntentFilter intentFilter =
+ new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ assertEquals("Context does not have MANAGE_DEBUGGING permission.",
+ mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ try {
+ mContext.registerReceiver(mReceiver, intentFilter);
+ mAdbManager.enablePairingByPairingCode();
+ if (!mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("Receiver did not receive adb intent action within the timeout duration");
+ }
+ } finally {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ @Test
+ public void testBroadcastReceiverWithoutPermissions() throws Exception {
+ adoptShellPermissionIdentity();
+ final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+ ServiceManager.getService(Context.ADB_SERVICE));
+ IntentFilter intentFilter =
+ new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ mAdbManager.enablePairingByPairingCode();
+
+ dropShellPermissionIdentity();
+ assertEquals("Context has MANAGE_DEBUGGING permission.",
+ mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_DENIED);
+ try {
+ mContext.registerReceiver(mReceiver, intentFilter);
+
+ if (mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("Broadcast receiver received adb action intent without debug permissions");
+ }
+ } finally {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
/**
* Runs an adb test with the provided configuration.
*
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index d94fafc6a5bf..ce9530c196ef 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -701,8 +701,15 @@ public final class Call {
*/
public static final int PROPERTY_CROSS_SIM = 0x00004000;
+ /**
+ * Connection is a tethered external call.
+ * Indicates that the {@link Connection} is fixed on this device but the audio streams are
+ * re-routed to another device.
+ */
+ public static final int PROPERTY_TETHERED_CALL = 0x00008000;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00004000
+ // Next PROPERTY value: 0x00010000
//******************************************************************************************
private final @CallState int mState;
@@ -899,6 +906,9 @@ public final class Call {
if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
builder.append(" PROPERTY_CROSS_SIM");
}
+ if (hasProperty(properties, PROPERTY_TETHERED_CALL)) {
+ builder.append(" PROPERTY_TETHERED_CALL");
+ }
builder.append("]");
return builder.toString();
}
diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java
index fccdf76372dd..389df80497df 100644
--- a/telecomm/java/android/telecom/CallAudioState.java
+++ b/telecomm/java/android/telecom/CallAudioState.java
@@ -27,7 +27,6 @@ import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -42,7 +41,8 @@ import java.util.stream.Collectors;
public final class CallAudioState implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(value={ROUTE_EARPIECE, ROUTE_BLUETOOTH, ROUTE_WIRED_HEADSET, ROUTE_SPEAKER},
+ @IntDef(value = {ROUTE_EARPIECE, ROUTE_BLUETOOTH, ROUTE_WIRED_HEADSET, ROUTE_SPEAKER,
+ ROUTE_EXTERNAL},
flag=true)
public @interface CallAudioRoute {}
@@ -58,6 +58,9 @@ public final class CallAudioState implements Parcelable {
/** Direct the audio stream through the device's speakerphone. */
public static final int ROUTE_SPEAKER = 0x00000008;
+ /** Direct the audio stream through another device. */
+ public static final int ROUTE_EXTERNAL = 0x00000010;
+
/**
* Direct the audio stream through the device's earpiece or wired headset if one is
* connected.
@@ -70,7 +73,7 @@ public final class CallAudioState implements Parcelable {
* @hide
**/
public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
- ROUTE_SPEAKER;
+ ROUTE_SPEAKER | ROUTE_EXTERNAL;
private final boolean isMuted;
private final int route;
@@ -189,7 +192,11 @@ public final class CallAudioState implements Parcelable {
*/
@CallAudioRoute
public int getSupportedRouteMask() {
- return supportedRouteMask;
+ if (route == ROUTE_EXTERNAL) {
+ return ROUTE_EXTERNAL;
+ } else {
+ return supportedRouteMask;
+ }
}
/**
@@ -233,6 +240,10 @@ public final class CallAudioState implements Parcelable {
listAppend(buffer, "SPEAKER");
}
+ if ((route & ROUTE_EXTERNAL) == ROUTE_EXTERNAL) {
+ listAppend(buffer, "EXTERNAL");
+ }
+
return buffer.toString();
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 21a180459978..30d495942ece 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -561,6 +561,15 @@ public abstract class Connection extends Conferenceable {
*/
public static final int PROPERTY_CROSS_SIM = 1 << 13;
+ /**
+ * Connection is a tethered external call.
+ * <p>
+ * Indicates that the {@link Connection} is fixed on this device but the audio streams are
+ * re-routed to another device.
+ * <p>
+ */
+ public static final int PROPERTY_TETHERED_CALL = 1 << 14;
+
//**********************************************************************************************
// Next PROPERTY value: 1<<14
//**********************************************************************************************
diff --git a/telephony/java/android/telephony/NetworkScanRequest.java b/telephony/java/android/telephony/NetworkScanRequest.java
index c8b8ffb9846b..326f4171de3b 100644
--- a/telephony/java/android/telephony/NetworkScanRequest.java
+++ b/telephony/java/android/telephony/NetworkScanRequest.java
@@ -221,7 +221,8 @@ public final class NetworkScanRequest implements Parcelable {
private NetworkScanRequest(Parcel in) {
mScanType = in.readInt();
- Parcelable[] tempSpecifiers = in.readParcelableArray(Object.class.getClassLoader());
+ Parcelable[] tempSpecifiers = in.readParcelableArray(Object.class.getClassLoader(),
+ RadioAccessSpecifier.class);
if (tempSpecifiers != null) {
mSpecifiers = new RadioAccessSpecifier[tempSpecifiers.length];
for (int i = 0; i < tempSpecifiers.length; i++) {
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 7e2d80eb871c..e6d7df34f755 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -851,7 +851,8 @@ public final class ImsCallProfile implements Parcelable {
mHasKnownUserIntentEmergency = in.readBoolean();
mRestrictCause = in.readInt();
mCallerNumberVerificationStatus = in.readInt();
- Object[] accepted = in.readArray(RtpHeaderExtensionType.class.getClassLoader());
+ Object[] accepted = in.readArray(RtpHeaderExtensionType.class.getClassLoader(),
+ RtpHeaderExtensionType.class);
mAcceptedRtpHeaderExtensionTypes = Arrays.stream(accepted)
.map(o -> (RtpHeaderExtensionType) o).collect(Collectors.toSet());
}
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 89757134f3a7..fbfbf68b30bb 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -19,12 +19,11 @@
#include "android-base/file.h"
#include "android-base/stringprintf.h"
#include "android-base/utf8.h"
-
+#include "format/proto/ProtoDeserialize.h"
#include "io/StringStream.h"
#include "io/ZipArchive.h"
#include "java/AnnotationProcessor.h"
#include "test/Test.h"
-#include "format/proto/ProtoDeserialize.h"
namespace aapt {
@@ -59,55 +58,56 @@ TEST_F(CompilerTest, MultiplePeriods) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
const std::string kResDir = BuildPath({android::base::Dirname(android::base::GetExecutablePath()),
"integration-tests", "CompileTest", "res"});
+ const std::string kOutDir = testing::TempDir();
// Resource files without periods in the file name should not throw errors
const std::string path0 = BuildPath({kResDir, "values", "values.xml"});
- const std::string path0_out = BuildPath({kResDir, "values_values.arsc.flat"});
+ const std::string path0_out = BuildPath({kOutDir, "values_values.arsc.flat"});
::android::base::utf8::unlink(path0_out.c_str());
- ASSERT_EQ(TestCompile(path0, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_EQ(TestCompile(path0, kOutDir, /** legacy */ false, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path0_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path0, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path0, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path0_out.c_str()), 0);
const std::string path1 = BuildPath({kResDir, "drawable", "image.png"});
- const std::string path1_out = BuildPath({kResDir, "drawable_image.png.flat"});
+ const std::string path1_out = BuildPath({kOutDir, "drawable_image.png.flat"});
::android::base::utf8::unlink(path1_out.c_str());
- ASSERT_EQ(TestCompile(path1, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_EQ(TestCompile(path1, kOutDir, /** legacy */ false, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path1_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path1, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path1, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path1_out.c_str()), 0);
const std::string path2 = BuildPath({kResDir, "drawable", "image.9.png"});
- const std::string path2_out = BuildPath({kResDir, "drawable_image.9.png.flat"});
+ const std::string path2_out = BuildPath({kOutDir, "drawable_image.9.png.flat"});
::android::base::utf8::unlink(path2_out.c_str());
- ASSERT_EQ(TestCompile(path2, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_EQ(TestCompile(path2, kOutDir, /** legacy */ false, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path2_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path2, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path2, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path2_out.c_str()), 0);
// Resource files with periods in the file name should fail on non-legacy compilations
const std::string path3 = BuildPath({kResDir, "values", "values.all.xml"});
- const std::string path3_out = BuildPath({kResDir, "values_values.all.arsc.flat"});
+ const std::string path3_out = BuildPath({kOutDir, "values_values.all.arsc.flat"});
::android::base::utf8::unlink(path3_out.c_str());
- ASSERT_NE(TestCompile(path3, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_NE(TestCompile(path3, kOutDir, /** legacy */ false, diag), 0);
ASSERT_NE(::android::base::utf8::unlink(path3_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path3, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path3, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path3_out.c_str()), 0);
const std::string path4 = BuildPath({kResDir, "drawable", "image.small.png"});
- const std::string path4_out = BuildPath({kResDir, "drawable_image.small.png.flat"});
+ const std::string path4_out = BuildPath({kOutDir, "drawable_image.small.png.flat"});
::android::base::utf8::unlink(path4_out.c_str());
- ASSERT_NE(TestCompile(path4, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_NE(TestCompile(path4, kOutDir, /** legacy */ false, diag), 0);
ASSERT_NE(::android::base::utf8::unlink(path4_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path4, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path4, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path4_out.c_str()), 0);
const std::string path5 = BuildPath({kResDir, "drawable", "image.small.9.png"});
- const std::string path5_out = BuildPath({kResDir, "drawable_image.small.9.png.flat"});
+ const std::string path5_out = BuildPath({kOutDir, "drawable_image.small.9.png.flat"});
::android::base::utf8::unlink(path5_out.c_str());
- ASSERT_NE(TestCompile(path5, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_NE(TestCompile(path5, kOutDir, /** legacy */ false, diag), 0);
ASSERT_NE(::android::base::utf8::unlink(path5_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path5, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path5, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path5_out.c_str()), 0);
}
@@ -116,9 +116,7 @@ TEST_F(CompilerTest, DirInput) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
const std::string kResDir = BuildPath({android::base::Dirname(android::base::GetExecutablePath()),
"integration-tests", "CompileTest", "DirInput", "res"});
- const std::string kOutputFlata =
- BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
- "CompileTest", "DirInput", "compiled.flata"});
+ const std::string kOutputFlata = BuildPath({testing::TempDir(), "compiled.flata"});
::android::base::utf8::unlink(kOutputFlata.c_str());
std::vector<android::StringPiece> args;
@@ -147,9 +145,7 @@ TEST_F(CompilerTest, ZipInput) {
const std::string kResZip =
BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
"CompileTest", "ZipInput", "res.zip"});
- const std::string kOutputFlata =
- BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
- "CompileTest", "ZipInput", "compiled.flata"});
+ const std::string kOutputFlata = BuildPath({testing::TempDir(), "compiled.flata"});
::android::base::utf8::unlink(kOutputFlata.c_str());
@@ -257,9 +253,9 @@ TEST_F(CompilerTest, DoNotTranslateTest) {
TEST_F(CompilerTest, RelativePathTest) {
StdErrDiagnostics diag;
- const std::string res_path = BuildPath(
- {android::base::Dirname(android::base::GetExecutablePath()),
- "integration-tests", "CompileTest", "res"});
+ const std::string res_path =
+ BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
+ "CompileTest", "res"});
const std::string path_values_colors = GetTestPath("values/colors.xml");
WriteFile(path_values_colors, "<resources>"
@@ -272,9 +268,8 @@ TEST_F(CompilerTest, RelativePathTest) {
"<TextBox android:id=\"@+id/text_one\" android:background=\"@color/color_one\"/>"
"</LinearLayout>");
- const std::string compiled_files_dir = BuildPath(
- {android::base::Dirname(android::base::GetExecutablePath()),
- "integration-tests", "CompileTest", "compiled"});
+ const std::string compiled_files_dir =
+ BuildPath({testing::TempDir(), "integration-tests", "CompileTest", "compiled"});
CHECK(file::mkdirs(compiled_files_dir.data()));
const std::string path_values_colors_out =
@@ -283,9 +278,8 @@ TEST_F(CompilerTest, RelativePathTest) {
BuildPath({compiled_files_dir, "layout_layout_one.flat"});
::android::base::utf8::unlink(path_values_colors_out.c_str());
::android::base::utf8::unlink(path_layout_layout_one_out.c_str());
- const std::string apk_path = BuildPath(
- {android::base::Dirname(android::base::GetExecutablePath()),
- "integration-tests", "CompileTest", "out.apk"});
+ const std::string apk_path =
+ BuildPath({testing::TempDir(), "integration-tests", "CompileTest", "out.apk"});
const std::string source_set_res = BuildPath({"main", "res"});
const std::string relative_path_values_colors =
diff --git a/tools/aapt2/test/Fixture.cpp b/tools/aapt2/test/Fixture.cpp
index e2f71dc45075..ddc1853ca13c 100644
--- a/tools/aapt2/test/Fixture.cpp
+++ b/tools/aapt2/test/Fixture.cpp
@@ -67,8 +67,7 @@ void ClearDirectory(const android::StringPiece& path) {
}
void TestDirectoryFixture::SetUp() {
- temp_dir_ = file::BuildPath({android::base::GetExecutableDirectory(),
- "_temp",
+ temp_dir_ = file::BuildPath({testing::TempDir(), "_temp",
testing::UnitTest::GetInstance()->current_test_case()->name(),
testing::UnitTest::GetInstance()->current_test_info()->name()});
ASSERT_TRUE(file::mkdirs(temp_dir_));
@@ -236,4 +235,4 @@ std::vector<std::string> LinkCommandBuilder::Build(const std::string& out_apk) {
return args_;
}
-} // namespace aapt \ No newline at end of file
+} // namespace aapt