summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp4
-rw-r--r--apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java2
-rw-r--r--api/current.txt20
-rw-r--r--api/system-current.txt25
-rw-r--r--api/test-current.txt7
-rw-r--r--cmds/bootanimation/BootAnimation.cpp46
-rw-r--r--cmds/bootanimation/audioplay.cpp44
-rw-r--r--cmds/bootanimation/iot/iotbootanimation_main.cpp2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java2
-rw-r--r--core/java/android/app/role/RoleControllerManager.java2
-rw-r--r--core/java/android/content/Intent.java13
-rw-r--r--core/java/android/content/pm/PackageInstaller.java42
-rw-r--r--core/java/android/content/pm/PackageParser.java53
-rw-r--r--core/java/android/content/pm/ShortcutManager.java3
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java6
-rw-r--r--core/java/android/hardware/display/AmbientDisplayConfiguration.java5
-rw-r--r--core/java/android/net/Uri.java6
-rw-r--r--core/java/android/os/RecoverySystem.java18
-rw-r--r--core/java/android/os/image/DynamicSystemClient.java24
-rw-r--r--core/java/android/os/storage/IStorageManager.aidl2
-rw-r--r--core/java/android/permission/PermissionControllerManager.java2
-rw-r--r--core/java/android/provider/MediaStore.java27
-rw-r--r--core/java/android/service/carrier/CarrierService.java4
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java27
-rw-r--r--core/java/android/service/watchdog/ExplicitHealthCheckService.java208
-rw-r--r--core/java/android/service/watchdog/IExplicitHealthCheckService.aidl31
-rw-r--r--core/java/android/view/accessibility/AccessibilityCache.java32
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java6
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java53
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureCondition.java106
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java15
-rw-r--r--core/java/android/view/inspector/PropertyReader.java5
-rw-r--r--core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java6
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java14
-rw-r--r--core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java6
-rw-r--r--core/java/com/android/internal/os/KernelCpuThreadReader.java298
-rw-r--r--core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java79
-rw-r--r--core/proto/android/app/settings_enums.proto6
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/tests/coretests/res/raw/com_android_tzdata.apexbin1286419 -> 979219 bytes
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java9
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java9
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java13
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java14
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageParserTest.java20
-rw-r--r--core/tests/coretests/src/android/view/DisplayCutoutTest.java9
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java14
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java19
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java9
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceTest.java11
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java16
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java7
-rw-r--r--core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java17
-rw-r--r--core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java125
-rw-r--r--data/etc/Android.bp8
-rw-r--r--data/etc/com.android.emergency.xml23
-rw-r--r--data/etc/privapp-permissions-platform.xml7
-rw-r--r--graphics/java/android/graphics/Bitmap.java13
-rw-r--r--graphics/java/android/graphics/Canvas.java14
-rw-r--r--graphics/java/android/graphics/Paint.java18
-rw-r--r--graphics/java/android/graphics/RenderNode.java3
-rw-r--r--media/java/android/media/IMediaRoute2Callback.aidl24
-rw-r--r--media/java/android/media/IMediaRoute2Provider.aidl27
-rw-r--r--media/java/android/media/IMediaRouter2ManagerClient.aidl25
-rw-r--r--media/java/android/media/IMediaRouterService.aidl8
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java108
-rw-r--r--media/java/android/media/MediaRouter.java30
-rw-r--r--media/java/android/media/MediaRouter2Manager.java241
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestResultPrinter.java4
-rw-r--r--media/tests/MediaRouteProvider/Android.bp18
-rw-r--r--media/tests/MediaRouteProvider/AndroidManifest.xml30
-rw-r--r--media/tests/MediaRouteProvider/res/values/strings.xml5
-rw-r--r--media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java33
-rw-r--r--media/tests/MediaRouter/Android.bp18
-rw-r--r--media/tests/MediaRouter/AndroidManifest.xml29
-rw-r--r--media/tests/MediaRouter/AndroidTest.xml16
-rw-r--r--media/tests/MediaRouter/res/values/strings.xml5
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java110
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java31
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java45
-rw-r--r--packages/SystemUI/res/layout-land/volume_dialog.xml8
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java5
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto7
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java15
-rw-r--r--services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java3
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java10
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java23
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java3
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java3
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java3
-rw-r--r--services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java3
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java27
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java21
-rw-r--r--services/core/java/com/android/server/accounts/AccountsDb.java37
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java2
-rw-r--r--services/core/java/com/android/server/infra/AbstractPerUserSystemService.java24
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java341
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java176
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java305
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java16
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java1
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java27
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java7
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java12
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java3
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java2
-rw-r--r--services/core/java/com/android/server/wm/AppWindowThumbnail.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java62
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java3
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java30
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyPermissions.java25
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java30
-rw-r--r--tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java (renamed from tests/utils/testutils/java/com/android/server/wm/test/filters/CoreTestsFilter.java)12
-rw-r--r--tools/bit/main.cpp2
136 files changed, 3133 insertions, 782 deletions
diff --git a/Android.bp b/Android.bp
index a6745a923abc..8a3f76c40e86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -318,6 +318,7 @@ java_defaults {
"core/java/android/service/vr/IVrListener.aidl",
"core/java/android/service/vr/IVrManager.aidl",
"core/java/android/service/vr/IVrStateCallbacks.aidl",
+ "core/java/android/service/watchdog/IExplicitHealthCheckService.aidl",
"core/java/android/print/ILayoutResultCallback.aidl",
"core/java/android/print/IPrinterDiscoveryObserver.aidl",
"core/java/android/print/IPrintDocumentAdapter.aidl",
@@ -475,7 +476,10 @@ java_defaults {
"media/java/android/media/IMediaHTTPConnection.aidl",
"media/java/android/media/IMediaHTTPService.aidl",
"media/java/android/media/IMediaResourceMonitor.aidl",
+ "media/java/android/media/IMediaRoute2Callback.aidl",
+ "media/java/android/media/IMediaRoute2Provider.aidl",
"media/java/android/media/IMediaRouterClient.aidl",
+ "media/java/android/media/IMediaRouter2ManagerClient.aidl",
"media/java/android/media/IMediaRouterService.aidl",
"media/java/android/media/IMediaScannerListener.aidl",
"media/java/android/media/IMediaScannerService.aidl",
diff --git a/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java b/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java
index 0c30302d63a3..1f261882b2d3 100644
--- a/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java
@@ -47,7 +47,7 @@ public class KernelCpuThreadReaderPerfTest {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
assertNotNull(mKernelCpuThreadReader);
while (state.keepRunning()) {
- this.mKernelCpuThreadReader.getCurrentProcessCpuUsage();
+ this.mKernelCpuThreadReader.getProcessCpuUsage();
}
}
}
diff --git a/api/current.txt b/api/current.txt
index 8192762c4d63..2a263681d624 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6963,7 +6963,7 @@ package android.app.admin {
public abstract static class DevicePolicyManager.InstallSystemUpdateCallback {
ctor public DevicePolicyManager.InstallSystemUpdateCallback();
- method public void onInstallUpdateError(int, String);
+ method public void onInstallUpdateError(int, @NonNull String);
field public static final int UPDATE_ERROR_BATTERY_LOW = 5; // 0x5
field public static final int UPDATE_ERROR_FILE_NOT_FOUND = 4; // 0x4
field public static final int UPDATE_ERROR_INCORRECT_OS_VERSION = 2; // 0x2
@@ -11384,6 +11384,7 @@ package android.content.pm {
public class PackageInstaller {
method public void abandonSession(int);
method public int createSession(@NonNull android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
+ method @Nullable public android.content.pm.PackageInstaller.SessionInfo getActiveStagedSession();
method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
method @Nullable public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
@@ -11468,6 +11469,7 @@ package android.content.pm {
method @NonNull public String getStagedSessionErrorMessage();
method @NonNull public android.os.UserHandle getUser();
method public boolean isActive();
+ method public boolean isCommitted();
method public boolean isMultiPackage();
method public boolean isSealed();
method public boolean isStaged();
@@ -13087,10 +13089,10 @@ package android.database.sqlite {
method @Deprecated public String buildUnionSubQuery(String, String[], java.util.Set<java.lang.String>, int, String, String, String[], String, String);
method public int delete(@NonNull android.database.sqlite.SQLiteDatabase, @Nullable String, @Nullable String[]);
method @Nullable public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
- method public boolean getDistinct();
method @Nullable public java.util.Map<java.lang.String,java.lang.String> getProjectionMap();
- method public boolean getStrict();
method @Nullable public String getTables();
+ method public boolean isDistinct();
+ method public boolean isStrict();
method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String);
method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String, String);
method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String, String, android.os.CancellationSignal);
@@ -29265,7 +29267,6 @@ package android.net {
method public abstract boolean isRelative();
method public android.net.Uri normalizeScheme();
method public static android.net.Uri parse(String);
- method @NonNull public String toSafeString();
method public abstract String toString();
method public static android.net.Uri withAppendedPath(android.net.Uri, String);
method public static void writeToParcel(android.os.Parcel, android.net.Uri);
@@ -53046,6 +53047,16 @@ package android.view.autofill {
package android.view.contentcapture {
+ public final class ContentCaptureCondition implements android.os.Parcelable {
+ ctor public ContentCaptureCondition(@NonNull android.content.LocusId, int);
+ method public int describeContents();
+ method public int getFlags();
+ method @NonNull public android.content.LocusId getLocusId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureCondition> CREATOR;
+ field public static final int FLAG_IS_REGEX = 2; // 0x2
+ }
+
public final class ContentCaptureContext implements android.os.Parcelable {
method public int describeContents();
method @NonNull public static android.view.contentcapture.ContentCaptureContext forLocusId(@NonNull String);
@@ -53062,6 +53073,7 @@ package android.view.contentcapture {
}
public final class ContentCaptureManager {
+ method @Nullable public java.util.Set<android.view.contentcapture.ContentCaptureCondition> getContentCaptureConditions();
method @Nullable public android.content.ComponentName getServiceComponentName();
method public boolean isContentCaptureEnabled();
method public void removeUserData(@NonNull android.view.contentcapture.UserDataRemovalRequest);
diff --git a/api/system-current.txt b/api/system-current.txt
index 6317ae0e59df..23cecf4890b5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1740,7 +1740,7 @@ package android.content.pm {
}
public class ShortcutManager {
- method @NonNull public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(@NonNull android.content.IntentFilter);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS) public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(@NonNull android.content.IntentFilter);
method public boolean hasShareTargets(@NonNull String);
}
@@ -4233,6 +4233,10 @@ package android.net {
field public static final int TAG_SYSTEM_PROBE = -190; // 0xffffff42
}
+ public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
+ method @NonNull public String toSafeString();
+ }
+
public class VpnService extends android.app.Service {
method @RequiresPermission(android.Manifest.permission.CONTROL_VPN) public static void prepareAndAuthorize(android.content.Context);
}
@@ -5664,7 +5668,7 @@ package android.os.image {
}
public static interface DynamicSystemClient.OnStatusChangedListener {
- method public void onStatusChanged(int, int, long);
+ method public void onStatusChanged(int, int, long, @Nullable Throwable);
}
}
@@ -6444,6 +6448,7 @@ package android.service.contentcapture {
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
+ method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
field public static final String SERVICE_META_DATA = "android.content_capture";
@@ -6895,6 +6900,22 @@ package android.service.wallpaper {
}
+package android.service.watchdog {
+
+ public abstract class ExplicitHealthCheckService extends android.app.Service {
+ ctor public ExplicitHealthCheckService();
+ method public final void notifyHealthCheckPassed(@NonNull String);
+ method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public abstract void onCancelHealthCheck(@NonNull String);
+ method @NonNull public abstract java.util.List<java.lang.String> onGetRequestedPackages();
+ method @NonNull public abstract java.util.List<java.lang.String> onGetSupportedPackages();
+ method public abstract void onRequestHealthCheck(@NonNull String);
+ field public static final String BIND_PERMISSION = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
+ field public static final String SERVICE_INTERFACE = "android.service.watchdog.ExplicitHealthCheckService";
+ }
+
+}
+
package android.telecom {
@Deprecated public class AudioState implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index d3ec216fc333..6c0b92853673 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2150,9 +2150,9 @@ package android.provider {
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
method @NonNull public static java.io.File getVolumePath(@NonNull String) throws java.io.FileNotFoundException;
method @NonNull public static java.util.Collection<java.io.File> getVolumeScanPaths(@NonNull String) throws java.io.FileNotFoundException;
- field public static final String EXTRA_ORIGINATED_FROM_SHELL = "android.intent.extra.originated_from_shell";
- field public static final String SCAN_FILE_CALL = "scan_file";
- field public static final String SCAN_VOLUME_CALL = "scan_volume";
+ method public static android.net.Uri scanFile(android.content.Context, java.io.File);
+ method public static android.net.Uri scanFileFromShell(android.content.Context, java.io.File);
+ method public static void scanVolume(android.content.Context, java.io.File);
}
public final class Settings {
@@ -2457,6 +2457,7 @@ package android.service.contentcapture {
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
+ method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
field public static final String SERVICE_META_DATA = "android.content_capture";
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a6c7cae9bdb6..8e7277c55ed8 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -101,7 +101,7 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16;
BootAnimation::BootAnimation(sp<Callbacks> callbacks)
: Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
- mTimeFormat12Hour(false), mTimeCheckThread(NULL), mCallbacks(callbacks) {
+ mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
mSession = new SurfaceComposerClient();
std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -156,7 +156,7 @@ void BootAnimation::binderDied(const wp<IBinder>&)
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
const char* name) {
Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
- if (asset == NULL)
+ if (asset == nullptr)
return NO_INIT;
SkBitmap bitmap;
sk_sp<SkData> data = SkData::MakeWithoutCopy(asset->getBuffer(false),
@@ -234,7 +234,7 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
case kN32_SkColorType:
if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, 0);
+ GL_UNSIGNED_BYTE, nullptr);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);
} else {
@@ -246,7 +246,7 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
case kRGB_565_SkColorType:
if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
- GL_UNSIGNED_SHORT_5_6_5, 0);
+ GL_UNSIGNED_SHORT_5_6_5, nullptr);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
} else {
@@ -304,10 +304,10 @@ status_t BootAnimation::readyToRun() {
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(display, 0, 0);
+ eglInitialize(display, nullptr, nullptr);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
- surface = eglCreateWindowSurface(display, config, s.get(), NULL);
- context = eglCreateContext(display, config, NULL, NULL);
+ surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
+ context = eglCreateContext(display, config, nullptr, nullptr);
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
@@ -671,7 +671,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
// Parse the description file
for (;;) {
const char* endl = strstr(s, "\n");
- if (endl == NULL) break;
+ if (endl == nullptr) break;
String8 line(s, endl - s);
const char* l = line.string();
int fps = 0;
@@ -699,8 +699,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
part.count = count;
part.pause = pause;
part.path = path;
- part.audioData = NULL;
- part.animation = NULL;
+ part.audioData = nullptr;
+ part.animation = nullptr;
if (!parseColor(color, part.backgroundColor)) {
SLOGE("> invalid color '#%s'", color);
part.backgroundColor[0] = 0.0f;
@@ -716,9 +716,9 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
part.playUntilComplete = false;
part.count = 1;
part.pause = 0;
- part.audioData = NULL;
+ part.audioData = nullptr;
part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
- if (part.animation != NULL)
+ if (part.animation != nullptr)
animation.parts.add(part);
}
s = ++endl;
@@ -731,7 +731,7 @@ bool BootAnimation::preloadZip(Animation& animation)
{
// read all the data structures
const size_t pcount = animation.parts.size();
- void *cookie = NULL;
+ void *cookie = nullptr;
ZipFileRO* zip = animation.zip;
if (!zip->startIteration(&cookie)) {
return false;
@@ -739,7 +739,7 @@ bool BootAnimation::preloadZip(Animation& animation)
ZipEntryRO entry;
char name[ANIM_ENTRY_NAME_MAX];
- while ((entry = zip->nextEntry(cookie)) != NULL) {
+ while ((entry = zip->nextEntry(cookie)) != nullptr) {
const int foundEntryName = zip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX);
if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) {
SLOGE("Error fetching entry file name");
@@ -762,7 +762,7 @@ bool BootAnimation::preloadZip(Animation& animation)
if (path == animation.parts[j].path) {
uint16_t method;
// supports only stored png files
- if (zip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) {
+ if (zip->getEntryInfo(entry, &method, nullptr, nullptr, nullptr, nullptr, nullptr)) {
if (method == ZipFileRO::kCompressStored) {
FileMap* map = zip->createEntryFileMap(entry);
if (map) {
@@ -800,7 +800,7 @@ bool BootAnimation::preloadZip(Animation& animation)
for (size_t frameIdx = 0; frameIdx < part.frames.size(); frameIdx++) {
const char* endl = strstr(trimDataStr, "\n");
// No more trimData for this part.
- if (endl == NULL) {
+ if (endl == nullptr) {
break;
}
String8 line(trimDataStr, endl - trimDataStr);
@@ -927,7 +927,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
glBindTexture(GL_TEXTURE_2D, 0);
// Handle animation package
- if (part.animation != NULL) {
+ if (part.animation != nullptr) {
playAnimation(*part.animation);
if (exitPending())
break;
@@ -1001,7 +1001,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
spec.tv_nsec = (now + delay) % 1000000000;
int err;
do {
- err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
+ err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);
} while (err<0 && errno == EINTR);
}
@@ -1090,13 +1090,13 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
if (mLoadedFiles.indexOf(fn) >= 0) {
SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
fn.string());
- return NULL;
+ return nullptr;
}
ZipFileRO *zip = ZipFileRO::open(fn);
- if (zip == NULL) {
+ if (zip == nullptr) {
SLOGE("Failed to open animation zip \"%s\": %s",
fn.string(), strerror(errno));
- return NULL;
+ return nullptr;
}
Animation *animation = new Animation;
@@ -1107,7 +1107,7 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
parseAnimationDesc(*animation);
if (!preloadZip(*animation)) {
- return NULL;
+ return nullptr;
}
@@ -1135,7 +1135,7 @@ bool BootAnimation::updateIsTimeAccurate() {
}
FILE* file = fopen(LAST_TIME_CHANGED_FILE_PATH, "r");
- if (file != NULL) {
+ if (file != nullptr) {
long long lastChangedTime = 0;
fscanf(file, "%lld", &lastChangedTime);
fclose(file);
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index 874aab08862e..c5e16c6b7deb 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -39,14 +39,14 @@ namespace {
using namespace android;
// engine interfaces
-static SLObjectItf engineObject = NULL;
+static SLObjectItf engineObject = nullptr;
static SLEngineItf engineEngine;
// output mix interfaces
-static SLObjectItf outputMixObject = NULL;
+static SLObjectItf outputMixObject = nullptr;
// buffer queue player interfaces
-static SLObjectItf bqPlayerObject = NULL;
+static SLObjectItf bqPlayerObject = nullptr;
static SLPlayItf bqPlayerPlay;
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
static SLMuteSoloItf bqPlayerMuteSolo;
@@ -89,7 +89,7 @@ void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
}
bool hasPlayer() {
- return (engineObject != NULL && bqPlayerObject != NULL);
+ return (engineObject != nullptr && bqPlayerObject != nullptr);
}
// create the engine and output mix objects
@@ -97,7 +97,7 @@ bool createEngine() {
SLresult result;
// create engine
- result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+ result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
if (result != SL_RESULT_SUCCESS) {
ALOGE("slCreateEngine failed with result %d", result);
return false;
@@ -121,7 +121,7 @@ bool createEngine() {
(void)result;
// create output mix
- result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
+ result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
if (result != SL_RESULT_SUCCESS) {
ALOGE("sl engine CreateOutputMix failed with result %d", result);
return false;
@@ -173,7 +173,7 @@ bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
- SLDataSink audioSnk = {&loc_outmix, NULL};
+ SLDataSink audioSnk = {&loc_outmix, nullptr};
// create audio player
const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, SL_IID_ANDROIDCONFIGURATION};
@@ -236,7 +236,7 @@ bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
(void)result;
// register callback on the buffer queue
- result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
+ result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
if (result != SL_RESULT_SUCCESS) {
ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
return false;
@@ -261,7 +261,7 @@ bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** o
const uint8_t** oSoundBuf, unsigned* oSoundBufSize) {
*oSoundBuf = clipBuf;
*oSoundBufSize = clipBufSize;
- *oChunkFormat = NULL;
+ *oChunkFormat = nullptr;
const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf;
if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
(wavHeader->wave_id != ID_WAVE)) {
@@ -303,7 +303,7 @@ bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** o
}
}
- if (*oChunkFormat == NULL) {
+ if (*oChunkFormat == nullptr) {
ALOGE("format not found in WAV file");
return false;
}
@@ -435,7 +435,7 @@ void setPlaying(bool isPlaying) {
SLresult result;
- if (NULL != bqPlayerPlay) {
+ if (nullptr != bqPlayerPlay) {
// set the player's state
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
@@ -445,28 +445,28 @@ void setPlaying(bool isPlaying) {
void destroy() {
// destroy buffer queue audio player object, and invalidate all associated interfaces
- if (bqPlayerObject != NULL) {
+ if (bqPlayerObject != nullptr) {
CHATTY("destroying audio player");
(*bqPlayerObject)->Destroy(bqPlayerObject);
- bqPlayerObject = NULL;
- bqPlayerPlay = NULL;
- bqPlayerBufferQueue = NULL;
- bqPlayerMuteSolo = NULL;
- bqPlayerVolume = NULL;
+ bqPlayerObject = nullptr;
+ bqPlayerPlay = nullptr;
+ bqPlayerBufferQueue = nullptr;
+ bqPlayerMuteSolo = nullptr;
+ bqPlayerVolume = nullptr;
}
// destroy output mix object, and invalidate all associated interfaces
- if (outputMixObject != NULL) {
+ if (outputMixObject != nullptr) {
(*outputMixObject)->Destroy(outputMixObject);
- outputMixObject = NULL;
+ outputMixObject = nullptr;
}
// destroy engine object, and invalidate all associated interfaces
- if (engineObject != NULL) {
+ if (engineObject != nullptr) {
CHATTY("destroying audio engine");
(*engineObject)->Destroy(engineObject);
- engineObject = NULL;
- engineEngine = NULL;
+ engineObject = nullptr;
+ engineEngine = nullptr;
}
}
diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp
index 2a3d3766ab38..ae3529796b9a 100644
--- a/cmds/bootanimation/iot/iotbootanimation_main.cpp
+++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp
@@ -60,7 +60,7 @@ public:
mBootAction = new BootAction();
if (!mBootAction->init(library_path, mBootParameters)) {
- mBootAction = NULL;
+ mBootAction = nullptr;
}
};
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4c05497479c0..4b0c05f323cd 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2166,7 +2166,7 @@ public class DevicePolicyManager {
* reported back to the IT admin to be read.
*/
public void onInstallUpdateError(
- @InstallUpdateCallbackErrorConstants int errorCode, String errorMessage) {
+ @InstallUpdateCallbackErrorConstants int errorCode, @NonNull String errorMessage) {
}
}
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
index e96c9a541c3f..bd981179e2ff 100644
--- a/core/java/android/app/role/RoleControllerManager.java
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -167,7 +167,7 @@ public class RoleControllerManager {
RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
@NonNull Handler handler, @UserIdInt int userId) {
super(context, RoleControllerService.SERVICE_INTERFACE, componentName, userId,
- service -> Log.e(LOG_TAG, "RemoteService " + service + " died"), handler, false,
+ service -> Log.e(LOG_TAG, "RemoteService " + service + " died"), handler, 0,
false, 1);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 032e5acf12ed..d87171e39595 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3115,21 +3115,14 @@ public class Intent implements Parcelable, Cloneable {
* <p>
* The path to the file is contained in {@link Intent#getData()}.
*
- * @deprecated Starting in the {@link android.os.Build.VERSION_CODES#Q}
- * release, shared storage paths are sandboxed per application,
- * and this broadcast cannot correctly translate those sandboxed
- * paths. Callers will need to instead migrate to using
- * {@link MediaScannerConnection}.
+ * @deprecated Callers should migrate to inserting items directly into
+ * {@link MediaStore}, where they will be automatically scanned
+ * after each mutation.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@Deprecated
public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
- /** @hide */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @Deprecated
- public static final String ACTION_MEDIA_SCANNER_SCAN_VOLUME = "android.intent.action.MEDIA_SCANNER_SCAN_VOLUME";
-
/**
* Broadcast Action: The "Media Button" was pressed. Includes a single
* extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 3edd17a4bb1f..1e6cea39b44d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -497,6 +497,36 @@ public class PackageInstaller {
}
/**
+ * Returns an active staged session, or {@code null} if there is none.
+ *
+ * <p>Staged session is active iff:
+ * <ul>
+ * <li>It is committed.
+ * <li>It is not applied.
+ * <li>It is not failed.
+ * </ul>
+ *
+ * <p>In case of a multi-apk session, parent session will be returned.
+ */
+ public @Nullable SessionInfo getActiveStagedSession() {
+ final List<SessionInfo> stagedSessions = getStagedSessions();
+ for (SessionInfo s : stagedSessions) {
+ if (s.isStagedSessionApplied() || s.isStagedSessionFailed()) {
+ // Finalized session.
+ continue;
+ }
+ if (s.getParentSessionId() != SessionInfo.INVALID_ID) {
+ // Child session.
+ continue;
+ }
+ if (s.isCommitted()) {
+ return s;
+ }
+ }
+ return null;
+ }
+
+ /**
* Uninstall the given package, removing it completely from the device. This
* method is available to:
* <ul>
@@ -1770,6 +1800,9 @@ public class PackageInstaller {
private String mStagedSessionErrorMessage;
/** {@hide} */
+ public boolean isCommitted;
+
+ /** {@hide} */
@UnsupportedAppUsage
public SessionInfo() {
}
@@ -1809,6 +1842,7 @@ public class PackageInstaller {
isStagedSessionFailed = source.readBoolean();
mStagedSessionErrorCode = source.readInt();
mStagedSessionErrorMessage = source.readString();
+ isCommitted = source.readBoolean();
}
/**
@@ -2181,6 +2215,13 @@ public class PackageInstaller {
mStagedSessionErrorMessage = errorMessage;
}
+ /**
+ * Whenever this session was committed.
+ */
+ public boolean isCommitted() {
+ return isCommitted;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -2218,6 +2259,7 @@ public class PackageInstaller {
dest.writeBoolean(isStagedSessionFailed);
dest.writeInt(mStagedSessionErrorCode);
dest.writeString(mStagedSessionErrorMessage);
+ dest.writeBoolean(isCommitted);
}
public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b480939ae450..35d1eac5c0ad 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -166,6 +166,9 @@ public class PackageParser {
private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f;
private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f;
+ private static final int DEFAULT_MIN_SDK_VERSION = 1;
+ private static final int DEFAULT_TARGET_SDK_VERSION = 0;
+
// TODO: switch outError users to PackageParserException
// TODO: refactor "codePath" to "apkPath"
@@ -466,6 +469,8 @@ public class PackageParser {
public final int versionCodeMajor;
public final int revisionCode;
public final int installLocation;
+ public final int minSdkVersion;
+ public final int targetSdkVersion;
public final VerifierInfo[] verifiers;
public final SigningDetails signingDetails;
public final boolean coreApp;
@@ -484,7 +489,8 @@ public class PackageParser {
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
SigningDetails signingDetails, boolean coreApp,
boolean debuggable, boolean multiArch, boolean use32bitAbi,
- boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits) {
+ boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
+ int minSdkVersion, int targetSdkVersion) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -505,6 +511,8 @@ public class PackageParser {
this.extractNativeLibs = extractNativeLibs;
this.isolatedSplits = isolatedSplits;
this.isSplitRequired = isSplitRequired;
+ this.minSdkVersion = minSdkVersion;
+ this.targetSdkVersion = targetSdkVersion;
}
public long getLongVersionCode() {
@@ -1712,6 +1720,8 @@ public class PackageParser {
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
int versionCode = 0;
int versionCodeMajor = 0;
+ int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
+ int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
int revisionCode = 0;
boolean coreApp = false;
boolean debuggable = false;
@@ -1749,7 +1759,7 @@ public class PackageParser {
}
}
- // Only search the tree when the tag is directly below <manifest>
+ // Only search the tree when the tag is the direct child of <manifest> tag
int type;
final int searchDepth = parser.getDepth() + 1;
@@ -1800,13 +1810,25 @@ public class PackageParser {
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"<uses-split> tag requires 'android:name' attribute");
}
+ } else if (TAG_USES_SDK.equals(parser.getName())) {
+ for (int i = 0; i < attrs.getAttributeCount(); ++i) {
+ final String attr = attrs.getAttributeName(i);
+ if ("targetSdkVersion".equals(attr)) {
+ targetSdkVersion = attrs.getAttributeIntValue(i,
+ DEFAULT_TARGET_SDK_VERSION);
+ }
+ if ("minSdkVersion".equals(attr)) {
+ minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
+ }
+ }
}
}
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
- multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits);
+ multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits,
+ minSdkVersion, targetSdkVersion);
}
/**
@@ -8350,6 +8372,7 @@ public class PackageParser {
}
}
+ // TODO(b/129261524): Clean up API
public static PackageInfo generatePackageInfoFromApex(File apexFile, boolean collectCerts)
throws PackageParserException {
PackageInfo pi = new PackageInfo();
@@ -8369,25 +8392,27 @@ public class PackageParser {
}
}
- // TODO(b/123086053) properly fill in the ApplicationInfo with data from AndroidManifest
+ PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile, parseFlags);
+
+ // Properly fill in the ApplicationInfo with data from AndroidManifest
// Add ApplicationInfo to the PackageInfo.
+ // TODO(b/129267599)
ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = apk.packageName;
ai.sourceDir = apexFile.getPath();
ai.flags = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
ai.enabled = true;
- ai.targetSdkVersion = 28;
- ai.targetSandboxVersion = 0;
- pi.applicationInfo = ai;
-
-
- // TODO(b/123052859): We should avoid these repeated calls to parseApkLite each time
- // we want to generate information for APEX modules.
- PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile, parseFlags);
+ ai.minSdkVersion = apk.minSdkVersion;
+ ai.targetSdkVersion = apk.targetSdkVersion;
+ ai.targetSandboxVersion = PARSE_DEFAULT_TARGET_SANDBOX;
+ ai.setVersionCode(apk.getLongVersionCode());
pi.packageName = apk.packageName;
- ai.packageName = apk.packageName;
+ pi.splitNames = new String[]{apk.splitName};
pi.setLongVersionCode(apk.getLongVersionCode());
- ai.setVersionCode(apk.getLongVersionCode());
+ pi.applicationInfo = ai;
+ pi.coreApp = apk.coreApp;
+
if (collectCerts) {
if (apk.signingDetails.hasPastSigningCertificates()) {
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index df6711761702..f85179942938 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -15,8 +15,10 @@
*/
package android.content.pm;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -565,6 +567,7 @@ public class ShortcutManager {
*/
@NonNull
@SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_APP_PREDICTIONS)
public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
try {
return mService.getShareTargets(mContext.getPackageName(), filter,
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index a73a71946bc7..bad80b89a6b0 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -80,7 +80,7 @@ public class SQLiteQueryBuilder {
* Get if the query is marked as {@code DISTINCT}, as last configured by
* {@link #setDistinct(boolean)}.
*/
- public boolean getDistinct() {
+ public boolean isDistinct() {
return mDistinct;
}
@@ -215,7 +215,7 @@ public class SQLiteQueryBuilder {
}
/**
- * Sets the cursor factory to be used for the query, as last configured by
+ * Gets the cursor factory to be used for the query, as last configured by
* {@link #setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory)}.
*/
public @Nullable SQLiteDatabase.CursorFactory getCursorFactory() {
@@ -251,7 +251,7 @@ public class SQLiteQueryBuilder {
* Get if the query is marked as strict, as last configured by
* {@link #setStrict(boolean)}.
*/
- public boolean getStrict() {
+ public boolean isStrict() {
return mStrict;
}
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index b122f199bc6f..c45b8ed52187 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -48,7 +48,10 @@ public class AmbientDisplayConfiguration {
return pulseOnNotificationEnabled(user)
|| pulseOnLongPressEnabled(user)
|| alwaysOnEnabled(user)
- || wakeScreenGestureEnabled(user);
+ || wakeScreenGestureEnabled(user)
+ || pickupGestureEnabled(user)
+ || tapGestureEnabled(user)
+ || doubleTapGestureEnabled(user);
}
/** {@hide} */
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 9e0d95bab7e6..c3166e91fac7 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -18,6 +18,7 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Environment;
@@ -380,9 +381,10 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
* returned as {@code tel:xxx-xxx-xxxx} and {@code http://example.com/path/to/item/} is
* returned as {@code http://example.com/...}.
* @return the common forms PII redacted string of this URI
+ * @hide
*/
- @NonNull
- public String toSafeString() {
+ @SystemApi
+ public @NonNull String toSafeString() {
String scheme = getScheme();
String ssp = getSchemeSpecificPart();
if (scheme != null) {
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 6a01e56cdf52..7cc7ccd2ad16 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -30,6 +30,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.os.storage.IStorageManager;
import android.provider.Settings;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
@@ -38,6 +39,8 @@ import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
+import com.android.internal.content.PackageHelper;
+
import libcore.io.Streams;
import java.io.ByteArrayInputStream;
@@ -854,6 +857,21 @@ public class RecoverySystem {
/** {@hide} */
public static void rebootPromptAndWipeUserData(Context context, String reason)
throws IOException {
+ boolean checkpointing = false;
+
+ // If we are running in checkpointing mode, we should not prompt a wipe.
+ // Checkpointing may save us. If it doesn't, we will wind up here again.
+ try {
+ IStorageManager storageManager = PackageHelper.getStorageManager();
+ if (storageManager.needsCheckpoint()) {
+ Log.i(TAG, "Rescue Party requested wipe. Aborting update instead.");
+ storageManager.abortChanges("rescueparty", false);
+ }
+ return;
+ } catch (RemoteException e) {
+ Log.i(TAG, "Failed to handle with checkpointing. Continuing with wipe.");
+ }
+
String reasonArg = null;
if (!TextUtils.isEmpty(reason)) {
reasonArg = "--reason=" + sanitizeArg(reason);
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 33a6ee888d0a..87367ac7597c 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -19,6 +19,7 @@ import android.annotation.BytesLong;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.ComponentName;
@@ -31,6 +32,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
+import android.os.ParcelableException;
import android.os.RemoteException;
import android.util.Slog;
@@ -100,9 +102,10 @@ public class DynamicSystemClient {
* @param status status code, also defined in {@code DynamicSystemClient}.
* @param cause cause code, also defined in {@code DynamicSystemClient}.
* @param progress number of bytes installed.
+ * @param detail additional detail about the error if available, otherwise null.
*/
void onStatusChanged(@InstallationStatus int status, @StatusChangedCause int cause,
- @BytesLong long progress);
+ @BytesLong long progress, @Nullable Throwable detail);
}
/*
@@ -177,6 +180,12 @@ public class DynamicSystemClient {
*/
public static final String KEY_INSTALLED_SIZE = "KEY_INSTALLED_SIZE";
+ /**
+ * Message key, used when the service is sending exception detail to the client.
+ * @hide
+ */
+ public static final String KEY_EXCEPTION_DETAIL = "KEY_EXCEPTION_DETAIL";
+
/*
* Intent Actions
*/
@@ -248,7 +257,7 @@ public class DynamicSystemClient {
} catch (RemoteException e) {
Slog.e(TAG, "Unable to get status from installation service");
mExecutor.execute(() -> {
- mListener.onStatusChanged(STATUS_UNKNOWN, CAUSE_ERROR_IPC, 0);
+ mListener.onStatusChanged(STATUS_UNKNOWN, CAUSE_ERROR_IPC, 0, e);
});
}
}
@@ -396,14 +405,19 @@ public class DynamicSystemClient {
int status = msg.arg1;
int cause = msg.arg2;
// obj is non-null
- long progress = ((Bundle) msg.obj).getLong(KEY_INSTALLED_SIZE);
+ Bundle bundle = (Bundle) msg.obj;
+ long progress = bundle.getLong(KEY_INSTALLED_SIZE);
+ ParcelableException t = (ParcelableException) bundle.getSerializable(
+ KEY_EXCEPTION_DETAIL);
+
+ Throwable detail = t == null ? null : t.getCause();
if (mExecutor != null) {
mExecutor.execute(() -> {
- mListener.onStatusChanged(status, cause, progress);
+ mListener.onStatusChanged(status, cause, progress, detail);
});
} else {
- mListener.onStatusChanged(status, cause, progress);
+ mListener.onStatusChanged(status, cause, progress, detail);
}
break;
default:
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 25f67f81b70a..9db41116d20a 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -193,4 +193,6 @@ interface IStorageManager {
void commitChanges() = 83;
boolean supportsCheckpoint() = 84;
void startCheckpoint(int numTries) = 85;
+ boolean needsCheckpoint() = 86;
+ void abortChanges(in String message, boolean retry) = 87;
}
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 61511aa509b1..55fae3014666 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -472,7 +472,7 @@ public final class PermissionControllerManager {
@NonNull UserHandle user) {
super(context, SERVICE_INTERFACE, componentName, user.getIdentifier(),
service -> Log.e(TAG, "RemoteService " + service + " died"),
- context.getMainThreadHandler(), false, false, 1);
+ context.getMainThreadHandler(), 0, false, 1);
}
/**
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index dc5fdc0ba67c..7feeeee0f790 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -115,9 +115,9 @@ public final class MediaStore {
*/
public static final String VOLUME_EXTERNAL = "external";
- /** {@hide} */ @TestApi
+ /** {@hide} */
public static final String SCAN_FILE_CALL = "scan_file";
- /** {@hide} */ @TestApi
+ /** {@hide} */
public static final String SCAN_VOLUME_CALL = "scan_volume";
/**
@@ -126,7 +126,6 @@ public final class MediaStore {
*
* {@hide}
*/
- @TestApi
public static final String EXTRA_ORIGINATED_FROM_SHELL =
"android.intent.extra.originated_from_shell";
@@ -3539,12 +3538,32 @@ public final class MediaStore {
}
/** @hide */
+ @TestApi
public static Uri scanFile(Context context, File file) {
+ return scan(context, SCAN_FILE_CALL, file, false);
+ }
+
+ /** @hide */
+ @TestApi
+ public static Uri scanFileFromShell(Context context, File file) {
+ return scan(context, SCAN_FILE_CALL, file, true);
+ }
+
+ /** @hide */
+ @TestApi
+ public static void scanVolume(Context context, File file) {
+ scan(context, SCAN_VOLUME_CALL, file, false);
+ }
+
+ /** @hide */
+ private static Uri scan(Context context, String method, File file,
+ boolean originatedFromShell) {
final ContentResolver resolver = context.getContentResolver();
try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
final Bundle in = new Bundle();
in.putParcelable(Intent.EXTRA_STREAM, Uri.fromFile(file));
- final Bundle out = client.call(SCAN_FILE_CALL, null, in);
+ in.putBoolean(EXTRA_ORIGINATED_FROM_SHELL, originatedFromShell);
+ final Bundle out = client.call(method, null, in);
return out.getParcelable(Intent.EXTRA_STREAM);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index c351d891bc61..aeb186b00686 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -114,9 +114,7 @@ public abstract class CarrierService extends Service {
* this UX, so a carrier app must be sure to call with active set to false
* sometime after calling with it set to true.
* <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * or the calling app has carrier privileges.
+ * Requires Permission: calling app has carrier privileges.
*
* @param active Whether the carrier network change is or shortly will be
* active. Set this value to true to begin showing
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index fb07abaa34a1..7a35b9e8fa74 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -39,6 +39,7 @@ import android.service.autofill.AutofillService;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
+import android.view.contentcapture.ContentCaptureCondition;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureEvent;
import android.view.contentcapture.ContentCaptureManager;
@@ -216,6 +217,32 @@ public abstract class ContentCaptureService extends Service {
}
}
+ /**
+ * Explicitly sets the conditions for which content capture should be available by an app.
+ *
+ * <p>Typically used to restrict content capture to a few websites on browser apps. Example:
+ *
+ * <code>
+ * ArraySet<ContentCaptureCondition> conditions = new ArraySet<>(1);
+ * conditions.add(new ContentCaptureCondition(new LocusId("^https://.*\\.example\\.com$"),
+ * ContentCaptureCondition.FLAG_IS_REGEX));
+ * service.setContentCaptureConditions("com.example.browser_app", conditions);
+ *
+ * </code>
+ *
+ * <p>NOTE: </p> this method doesn't automatically disable content capture for the given
+ * conditions; it's up to the {@code packageName} implementation to call
+ * {@link ContentCaptureManager#getContentCaptureConditions()} and disable it accordingly.
+ *
+ * @param packageName name of the packages where the restrictions are set.
+ * @param conditions list of conditions, or {@code null} to reset the conditions for the
+ * package.
+ */
+ public final void setContentCaptureConditions(@NonNull String packageName,
+ @Nullable Set<ContentCaptureCondition> conditions) {
+ // TODO(b/129267994): implement
+ }
+
private <T> ArrayList<T> toList(@Nullable Set<T> set) {
return set == null ? null : new ArrayList<T>(set);
}
diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
new file mode 100644
index 000000000000..015fba19d785
--- /dev/null
+++ b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
@@ -0,0 +1,208 @@
+/*
+ * 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.service.watchdog;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A service to provide packages supporting explicit health checks and route checks to these
+ * packages on behalf of the package watchdog.
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with the
+ * {@link android.Manifest.permission#BIND_EXPLICIT_HEALTH_CHECK_SERVICE} permission,
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. In adddition,
+ * your implementation must live in {@link PackageManger#SYSTEM_SHARED_LIBRARY_SERVICES}.
+ * For example:</p>
+ * <pre>
+ * &lt;service android:name=".FooExplicitHealthCheckService"
+ * android:exported="true"
+ * android:priority="100"
+ * android:permission="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"&gt;
+ * &lt;intent-filter&gt;
+ * &lt;action android:name="android.service.watchdog.ExplicitHealthCheckService" /&gt;
+ * &lt;/intent-filter&gt;
+ * &lt;/service&gt;
+ * </pre>
+ * @hide
+ */
+@SystemApi
+public abstract class ExplicitHealthCheckService extends Service {
+
+ private static final String TAG = "ExplicitHealthCheckService";
+
+ /**
+ * {@link Bundle} key for a {@link List} of {@link String} value.
+ *
+ * {@hide}
+ */
+ public static final String EXTRA_SUPPORTED_PACKAGES =
+ "android.service.watchdog.extra.supported_packages";
+
+ /**
+ * {@link Bundle} key for a {@link List} of {@link String} value.
+ *
+ * {@hide}
+ */
+ public static final String EXTRA_REQUESTED_PACKAGES =
+ "android.service.watchdog.extra.requested_packages";
+
+ /**
+ * {@link Bundle} key for a {@link String} value.
+ *
+ * {@hide}
+ */
+ public static final String EXTRA_HEALTH_CHECK_PASSED_PACKAGE =
+ "android.service.watchdog.extra.health_check_passed_package";
+
+ /**
+ * The Intent action that a service must respond to. Add it to the intent filter of the service
+ * in its manifest.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE =
+ "android.service.watchdog.ExplicitHealthCheckService";
+
+ /**
+ * The permission that a service must require to ensure that only Android system can bind to it.
+ * If this permission is not enforced in the AndroidManifest of the service, the system will
+ * skip that service.
+ */
+ public static final String BIND_PERMISSION =
+ "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
+
+ private final ExplicitHealthCheckServiceWrapper mWrapper =
+ new ExplicitHealthCheckServiceWrapper();
+
+ /**
+ * Called when the system requests an explicit health check for {@code packageName}.
+ *
+ * <p> When {@code packageName} passes the check, implementors should call
+ * {@link #notifyHealthCheckPassed} to inform the system.
+ *
+ * <p> It could take many hours before a {@code packageName} passes a check and implementors
+ * should never drop requests unless {@link onCancel} is called or the service dies.
+ *
+ * <p> Requests should not be queued and additional calls while expecting a result for
+ * {@code packageName} should have no effect.
+ */
+ public abstract void onRequestHealthCheck(@NonNull String packageName);
+
+ /**
+ * Called when the system cancels the explicit health check request for {@code packageName}.
+ * Should do nothing if there are is no active request for {@code packageName}.
+ */
+ public abstract void onCancelHealthCheck(@NonNull String packageName);
+
+ /**
+ * Called when the system requests for all the packages supporting explicit health checks. The
+ * system may request an explicit health check for any of these packages with
+ * {@link #onRequestHealthCheck}.
+ *
+ * @return all packages supporting explicit health checks
+ */
+ @NonNull public abstract List<String> onGetSupportedPackages();
+
+ /**
+ * Called when the system requests for all the packages that it has currently requested
+ * an explicit health check for.
+ *
+ * @return all packages expecting an explicit health check result
+ */
+ @NonNull public abstract List<String> onGetRequestedPackages();
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
+ @Nullable private RemoteCallback mCallback;
+
+ @Override
+ @NonNull
+ public final IBinder onBind(@NonNull Intent intent) {
+ return mWrapper;
+ }
+
+ /**
+ * Implementors should call this to notify the system when explicit health check passes
+ * for {@code packageName};
+ */
+ public final void notifyHealthCheckPassed(@NonNull String packageName) {
+ mHandler.post(() -> {
+ if (mCallback != null) {
+ Objects.requireNonNull(packageName,
+ "Package passing explicit health check must be non-null");
+ Bundle bundle = new Bundle();
+ bundle.putString(EXTRA_HEALTH_CHECK_PASSED_PACKAGE, packageName);
+ mCallback.sendResult(bundle);
+ } else {
+ Log.wtf(TAG, "System missed explicit health check result for " + packageName);
+ }
+ });
+ }
+
+ private class ExplicitHealthCheckServiceWrapper extends IExplicitHealthCheckService.Stub {
+ @Override
+ public void setCallback(RemoteCallback callback) throws RemoteException {
+ mHandler.post(() -> {
+ mCallback = callback;
+ });
+ }
+
+ @Override
+ public void request(String packageName) throws RemoteException {
+ mHandler.post(() -> ExplicitHealthCheckService.this.onRequestHealthCheck(packageName));
+ }
+
+ @Override
+ public void cancel(String packageName) throws RemoteException {
+ mHandler.post(() -> ExplicitHealthCheckService.this.onCancelHealthCheck(packageName));
+ }
+
+ @Override
+ public void getSupportedPackages(RemoteCallback callback) throws RemoteException {
+ mHandler.post(() -> sendPackages(callback, EXTRA_SUPPORTED_PACKAGES,
+ ExplicitHealthCheckService.this.onGetSupportedPackages()));
+ }
+
+ @Override
+ public void getRequestedPackages(RemoteCallback callback) throws RemoteException {
+ mHandler.post(() -> sendPackages(callback, EXTRA_REQUESTED_PACKAGES,
+ ExplicitHealthCheckService.this.onGetRequestedPackages()));
+ }
+
+ private void sendPackages(RemoteCallback callback, String key, List<String> packages) {
+ Objects.requireNonNull(packages,
+ "Supported and requested package list must be non-null");
+ Bundle bundle = new Bundle();
+ bundle.putStringArrayList(key, new ArrayList<>(packages));
+ callback.sendResult(bundle);
+ }
+ }
+}
diff --git a/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl b/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl
new file mode 100644
index 000000000000..78c0328d36f0
--- /dev/null
+++ b/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.service.watchdog;
+
+import android.os.RemoteCallback;
+
+/**
+ * @hide
+ */
+oneway interface IExplicitHealthCheckService
+{
+ void setCallback(in @nullable RemoteCallback callback);
+ void request(String packageName);
+ void cancel(String packageName);
+ void getSupportedPackages(in RemoteCallback callback);
+ void getRequestedPackages(in RemoteCallback callback);
+}
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index df8690d2eef8..f9e601f36e0e 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -105,11 +105,7 @@ public class AccessibilityCache {
Log.i(LOG_TAG, "Caching window: " + window.getId());
}
final int windowId = window.getId();
- AccessibilityWindowInfo oldWindow = mWindowCache.get(windowId);
- if (oldWindow != null) {
- oldWindow.recycle();
- }
- mWindowCache.put(windowId, AccessibilityWindowInfo.obtain(window));
+ mWindowCache.put(windowId, new AccessibilityWindowInfo(window));
}
}
@@ -225,7 +221,7 @@ public class AccessibilityCache {
if (info != null) {
// Return a copy since the client calls to AccessibilityNodeInfo#recycle()
// will wipe the data of the cached info.
- info = AccessibilityNodeInfo.obtain(info);
+ info = new AccessibilityNodeInfo(info);
}
if (DEBUG) {
Log.i(LOG_TAG, "get(" + accessibilityNodeId + ") = " + info);
@@ -257,7 +253,7 @@ public class AccessibilityCache {
List<AccessibilityWindowInfo> windows = new ArrayList<>(sortedWindowCount);
for (int i = sortedWindowCount - 1; i >= 0; i--) {
AccessibilityWindowInfo window = sortedWindows.valueAt(i);
- windows.add(AccessibilityWindowInfo.obtain(window));
+ windows.add(new AccessibilityWindowInfo(window));
sortedWindows.removeAt(i);
}
@@ -271,7 +267,7 @@ public class AccessibilityCache {
synchronized (mLock) {
AccessibilityWindowInfo window = mWindowCache.get(windowId);
if (window != null) {
- return AccessibilityWindowInfo.obtain(window);
+ return new AccessibilityWindowInfo(window);
}
return null;
}
@@ -326,14 +322,12 @@ public class AccessibilityCache {
final long oldParentId = oldInfo.getParentNodeId();
if (info.getParentNodeId() != oldParentId) {
clearSubTreeLocked(windowId, oldParentId);
- } else {
- oldInfo.recycle();
}
}
// Cache a copy since the client calls to AccessibilityNodeInfo#recycle()
// will wipe the data of the cached info.
- AccessibilityNodeInfo clone = AccessibilityNodeInfo.obtain(info);
+ AccessibilityNodeInfo clone = new AccessibilityNodeInfo(info);
nodes.put(sourceId, clone);
if (clone.isAccessibilityFocused()) {
if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
@@ -371,12 +365,7 @@ public class AccessibilityCache {
}
private void clearWindowCache() {
- final int windowCount = mWindowCache.size();
- for (int i = windowCount - 1; i >= 0; i--) {
- AccessibilityWindowInfo window = mWindowCache.valueAt(i);
- window.recycle();
- mWindowCache.removeAt(i);
- }
+ mWindowCache.clear();
mIsAllWindowsCached = false;
}
@@ -391,13 +380,6 @@ public class AccessibilityCache {
if (nodes == null) {
return;
}
- // Recycle the nodes before clearing the cache.
- final int nodeCount = nodes.size();
- for (int i = nodeCount - 1; i >= 0; i--) {
- AccessibilityNodeInfo info = nodes.valueAt(i);
- nodes.removeAt(i);
- info.recycle();
- }
mNodeCache.remove(windowId);
}
@@ -440,11 +422,9 @@ public class AccessibilityCache {
for (int i = 0; i < childCount; i++) {
final long childNodeId = current.getChildId(i);
if (clearSubTreeRecursiveLocked(nodes, childNodeId)) {
- current.recycle();
return true;
}
}
- current.recycle();
return false;
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index a8a787edde04..385d491f49ef 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -654,6 +654,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
+ // TODO(b/129300068): Remove sNumInstancesInUse.
private static AtomicInteger sNumInstancesInUse;
/**
@@ -766,6 +767,11 @@ public class AccessibilityNodeInfo implements Parcelable {
/* do nothing */
}
+ /** @hide */
+ AccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ init(info);
+ }
+
/**
* Sets the source.
* <p>
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 4383f8a02d43..1e2321cf60d9 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -96,6 +96,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
private static final int MAX_POOL_SIZE = 10;
private static final SynchronizedPool<AccessibilityWindowInfo> sPool =
new SynchronizedPool<AccessibilityWindowInfo>(MAX_POOL_SIZE);
+ // TODO(b/129300068): Remove sNumInstancesInUse.
private static AtomicInteger sNumInstancesInUse;
// Data.
@@ -115,6 +116,11 @@ public final class AccessibilityWindowInfo implements Parcelable {
/* do nothing - hide constructor */
}
+ /** @hide */
+ AccessibilityWindowInfo(AccessibilityWindowInfo info) {
+ init(info);
+ }
+
/**
* Gets the title of the window.
*
@@ -448,26 +454,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
*/
public static AccessibilityWindowInfo obtain(AccessibilityWindowInfo info) {
AccessibilityWindowInfo infoClone = obtain();
-
- infoClone.mType = info.mType;
- infoClone.mLayer = info.mLayer;
- infoClone.mBooleanProperties = info.mBooleanProperties;
- infoClone.mId = info.mId;
- infoClone.mParentId = info.mParentId;
- infoClone.mBoundsInScreen.set(info.mBoundsInScreen);
- infoClone.mTitle = info.mTitle;
- infoClone.mAnchorId = info.mAnchorId;
-
- if (info.mChildIds != null && info.mChildIds.size() > 0) {
- if (infoClone.mChildIds == null) {
- infoClone.mChildIds = info.mChildIds.clone();
- } else {
- infoClone.mChildIds.addAll(info.mChildIds);
- }
- }
-
- infoClone.mConnectionId = info.mConnectionId;
-
+ infoClone.init(info);
return infoClone;
}
@@ -529,6 +516,32 @@ public final class AccessibilityWindowInfo implements Parcelable {
parcel.writeInt(mConnectionId);
}
+ /**
+ * Initializes this instance from another one.
+ *
+ * @param other The other instance.
+ */
+ private void init(AccessibilityWindowInfo other) {
+ mType = other.mType;
+ mLayer = other.mLayer;
+ mBooleanProperties = other.mBooleanProperties;
+ mId = other.mId;
+ mParentId = other.mParentId;
+ mBoundsInScreen.set(other.mBoundsInScreen);
+ mTitle = other.mTitle;
+ mAnchorId = other.mAnchorId;
+
+ if (other.mChildIds != null && other.mChildIds.size() > 0) {
+ if (mChildIds == null) {
+ mChildIds = other.mChildIds.clone();
+ } else {
+ mChildIds.addAll(other.mChildIds);
+ }
+ }
+
+ mConnectionId = other.mConnectionId;
+ }
+
private void initFromParcel(Parcel parcel) {
mType = parcel.readInt();
mLayer = parcel.readInt();
diff --git a/core/java/android/view/contentcapture/ContentCaptureCondition.java b/core/java/android/view/contentcapture/ContentCaptureCondition.java
new file mode 100644
index 000000000000..ed872578d069
--- /dev/null
+++ b/core/java/android/view/contentcapture/ContentCaptureCondition.java
@@ -0,0 +1,106 @@
+/*
+ * 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.view.contentcapture;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.LocusId;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Defines a condition for when content capture should be allowed.
+ *
+ * <p>See {@link ContentCaptureManager#getContentCaptureConditions()} for more.
+ */
+public final class ContentCaptureCondition implements Parcelable {
+
+ /**
+ * When set, package should use the {@link LocusId#getId()} as a regular expression.
+ */
+ public static final int FLAG_IS_REGEX = 0x2;
+
+ /** @hide */
+ @IntDef(prefix = { "FLAG" }, flag = true, value = {
+ FLAG_IS_REGEX
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Flags {}
+
+ private final @NonNull LocusId mLocusId;
+ private final @Flags int mFlags;
+
+ /**
+ * Default constructor.
+ *
+ * @param locusId id of the condition, as defined by
+ * {@link ContentCaptureContext#getLocusId()}.
+ * @param flags either {@link ContentCaptureCondition#FLAG_IS_REGEX} or {@code 0}.
+ */
+ public ContentCaptureCondition(@NonNull LocusId locusId, @Flags int flags) {
+ this.mLocusId = Preconditions.checkNotNull(locusId);
+ this.mFlags = flags;
+ // TODO(b/129267994): check flags, add test case for null and invalid flags
+ }
+
+ /**
+ * Gets the {@code LocusId} per se.
+ */
+ @NonNull
+ public LocusId getLocusId() {
+ return mLocusId;
+ }
+
+ /**
+ * Gets the flags associates with this condition.
+ *
+ * @return either {@link ContentCaptureCondition#FLAG_IS_REGEX} or {@code 0}.
+ */
+ public @Flags int getFlags() {
+ return mFlags;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeParcelable(mLocusId, flags);
+ parcel.writeInt(mFlags);
+ }
+
+ public static final @NonNull Parcelable.Creator<ContentCaptureCondition> CREATOR =
+ new Parcelable.Creator<ContentCaptureCondition>() {
+
+ @Override
+ public ContentCaptureCondition createFromParcel(@NonNull Parcel parcel) {
+ return new ContentCaptureCondition(parcel.readParcelable(null),
+ parcel.readInt());
+ }
+
+ @Override
+ public ContentCaptureCondition[] newArray(int size) {
+ return new ContentCaptureCondition[size];
+ }
+ };
+}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 9e546a80dfd3..817b13011402 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -43,6 +43,7 @@ import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
/**
* TODO(b/123577059): add javadocs / mention it can be null
@@ -362,6 +363,20 @@ public final class ContentCaptureManager {
}
/**
+ * Gets the list of conditions for when content capture should be allowed.
+ *
+ * <p>This method is typically used by web browsers so they don't generate unnecessary content
+ * capture events for websites the content capture service is not interested on.
+ *
+ * @return list of conditions, or {@code null} if the service didn't set any restriction
+ * (in which case content capture events should always be generated).
+ */
+ @Nullable
+ public Set<ContentCaptureCondition> getContentCaptureConditions() {
+ return null; // TODO(b/129267994): implement
+ }
+
+ /**
* Called by apps to explicitly enable or disable content capture.
*
* <p><b>Note: </b> this call is not persisted accross reboots, so apps should typically call
diff --git a/core/java/android/view/inspector/PropertyReader.java b/core/java/android/view/inspector/PropertyReader.java
index b5020ce6495f..5be0e3f3ccf2 100644
--- a/core/java/android/view/inspector/PropertyReader.java
+++ b/core/java/android/view/inspector/PropertyReader.java
@@ -133,10 +133,11 @@ public interface PropertyReader {
void readColor(int id, @ColorInt int value);
/**
- * Read a color packed into a {@link ColorLong} as a property.
+ * Read a color packed into a {@code ColorLong} as a property.
*
* @param id Identifier of the property from a {@link PropertyMapper}
- * @param value Value of the property
+ * @param value Value of the property packed as a {@code ColorLong}. See the
+ * {@link Color} class for details of the packing.
* @throws PropertyTypeMismatchException If the property ID is not mapped as a color
*/
void readColor(int id, @ColorLong long value);
diff --git a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
index 37f61bf650c7..206efa94b7f6 100644
--- a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
@@ -45,9 +45,9 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S
public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context,
@NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
@NonNull VultureCallback<S> callback, @NonNull Handler handler,
- boolean bindInstantServiceAllowed, boolean verbose, int initialCapacity) {
- super(context, serviceInterface, componentName, userId, callback, handler,
- bindInstantServiceAllowed, verbose);
+ int bindingFlags, boolean verbose, int initialCapacity) {
+ super(context, serviceInterface, componentName, userId, callback, handler, bindingFlags,
+ verbose);
mInitialCapacity = initialCapacity;
}
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 0a83fcc6db61..1155854efd55 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -82,7 +82,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
private final VultureCallback<S> mVultureCallback;
private final int mUserId;
private final ServiceConnection mServiceConnection = new RemoteServiceConnection();
- private final boolean mBindInstantServiceAllowed;
+ private final int mBindingFlags;
protected I mService;
private boolean mBinding;
@@ -113,7 +113,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
// NOTE: must be package-protected so this class is not extended outside
AbstractRemoteService(@NonNull Context context, @NonNull String serviceInterface,
@NonNull ComponentName componentName, int userId, @NonNull VultureCallback<S> callback,
- @NonNull Handler handler, boolean bindInstantServiceAllowed, boolean verbose) {
+ @NonNull Handler handler, int bindingFlags, boolean verbose) {
mContext = context;
mVultureCallback = callback;
mVerbose = verbose;
@@ -121,7 +121,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
mIntent = new Intent(serviceInterface).setComponent(mComponentName);
mUserId = userId;
mHandler = new Handler(handler.getLooper());
- mBindInstantServiceAllowed = bindInstantServiceAllowed;
+ mBindingFlags = bindingFlags;
}
/**
@@ -264,7 +264,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
}
}
pw.println();
- pw.append(prefix).append("mBindInstantServiceAllowed=").println(mBindInstantServiceAllowed);
+ pw.append(prefix).append("mBindingFlags=").println(mBindingFlags);
pw.append(prefix).append("idleTimeout=")
.append(Long.toString(idleTimeout / 1000)).append("s\n");
pw.append(prefix).append("requestTimeout=");
@@ -407,10 +407,8 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
if (mVerbose) Slog.v(mTag, "ensureBound()");
mBinding = true;
- int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
- if (mBindInstantServiceAllowed) {
- flags |= Context.BIND_ALLOW_INSTANT;
- }
+ final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | mBindingFlags;
final boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags,
mHandler, new UserHandle(mUserId));
diff --git a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
index a70fc3e17d60..66bee95b0302 100644
--- a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
@@ -44,9 +44,9 @@ public abstract class AbstractSinglePendingRequestRemoteService<S
public AbstractSinglePendingRequestRemoteService(@NonNull Context context,
@NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
@NonNull VultureCallback<S> callback, @NonNull Handler handler,
- boolean bindInstantServiceAllowed, boolean verbose) {
- super(context, serviceInterface, componentName, userId, callback, handler,
- bindInstantServiceAllowed, verbose);
+ int bindingFlags, boolean verbose) {
+ super(context, serviceInterface, componentName, userId, callback, handler, bindingFlags,
+ verbose);
}
@Override // from AbstractRemoteService
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
index 248e0266b70b..e4de1586bc51 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -32,15 +32,18 @@ import java.util.ArrayList;
import java.util.function.Predicate;
/**
- * Given a process, will iterate over the child threads of the process, and return the CPU usage
- * statistics for each child thread. The CPU usage statistics contain the amount of time spent in a
- * frequency band.
+ * Iterates over processes, and all threads owned by those processes, and return the CPU usage for
+ * each thread. The CPU usage statistics contain the amount of time spent in a frequency band. CPU
+ * usage is collected using {@link ProcTimeInStateReader}.
+ *
+ * <p>We only collect CPU data for processes and threads that are owned by certain UIDs. These UIDs
+ * are configured via {@link #setUidPredicate}.
*
* <p>Frequencies are bucketed together to reduce the amount of data created. This means that we
- * return less frequencies than provided by {@link ProcTimeInStateReader}. The number of
- * frequencies is configurable by {@link #setNumBuckets}. Frequencies are reported as the lowest
- * frequency in that range. Frequencies are spread as evenly as possible across the buckets. The
- * buckets do not cross over the little/big frequencies reported.
+ * return less frequencies than provided by {@link ProcTimeInStateReader}. The number of frequencies
+ * is configurable by {@link #setNumBuckets}. Frequencies are reported as the lowest frequency in
+ * that range. Frequencies are spread as evenly as possible across the buckets. The buckets do not
+ * cross over the little/big frequencies reported.
*
* <p>N.B.: In order to bucket across little/big frequencies correctly, we assume that the {@code
* time_in_state} file contains every little core frequency in ascending order, followed by every
@@ -60,56 +63,39 @@ public class KernelCpuThreadReader {
private static final String CPU_STATISTICS_FILENAME = "time_in_state";
/**
- * The name of the file to read process command line invocation from, must be found in
- * {@code /proc/$PID/}
+ * The name of the file to read process command line invocation from, must be found in {@code
+ * /proc/$PID/}
*/
private static final String PROCESS_NAME_FILENAME = "cmdline";
/**
- * The name of the file to read thread name from, must be found in
- * {@code /proc/$PID/task/$TID}
+ * The name of the file to read thread name from, must be found in {@code /proc/$PID/task/$TID}
*/
private static final String THREAD_NAME_FILENAME = "comm";
- /**
- * Glob pattern for the process directory names under {@code proc}
- */
+ /** Glob pattern for the process directory names under {@code proc} */
private static final String PROCESS_DIRECTORY_FILTER = "[0-9]*";
- /**
- * Default process name when the name can't be read
- */
+ /** Default process name when the name can't be read */
private static final String DEFAULT_PROCESS_NAME = "unknown_process";
- /**
- * Default thread name when the name can't be read
- */
+ /** Default thread name when the name can't be read */
private static final String DEFAULT_THREAD_NAME = "unknown_thread";
- /**
- * Default mount location of the {@code proc} filesystem
- */
+ /** Default mount location of the {@code proc} filesystem */
private static final Path DEFAULT_PROC_PATH = Paths.get("/proc");
- /**
- * The initial {@code time_in_state} file for {@link ProcTimeInStateReader}
- */
+ /** The initial {@code time_in_state} file for {@link ProcTimeInStateReader} */
private static final Path DEFAULT_INITIAL_TIME_IN_STATE_PATH =
DEFAULT_PROC_PATH.resolve("self/time_in_state");
- /**
- * Value returned when there was an error getting an integer ID value (e.g. PID, UID)
- */
+ /** Value returned when there was an error getting an integer ID value (e.g. PID, UID) */
private static final int ID_ERROR = -1;
- /**
- * Thread ID used when reporting CPU used by other threads
- */
+ /** Thread ID used when reporting CPU used by other threads */
private static final int OTHER_THREADS_ID = -1;
- /**
- * Thread name used when reporting CPU used by other threads
- */
+ /** Thread name used when reporting CPU used by other threads */
private static final String OTHER_THREADS_NAME = "__OTHER_THREADS";
/**
@@ -124,9 +110,7 @@ public class KernelCpuThreadReader {
*/
private int mMinimumTotalCpuUsageMillis;
- /**
- * Where the proc filesystem is mounted
- */
+ /** Where the proc filesystem is mounted */
private final Path mProcPath;
/**
@@ -135,14 +119,10 @@ public class KernelCpuThreadReader {
*/
private int[] mFrequenciesKhz;
- /**
- * Used to read and parse {@code time_in_state} files
- */
+ /** Used to read and parse {@code time_in_state} files */
private final ProcTimeInStateReader mProcTimeInStateReader;
- /**
- * Used to sort frequencies and usage times into buckets
- */
+ /** Used to sort frequencies and usage times into buckets */
private FrequencyBucketCreator mFrequencyBucketCreator;
private final Injector mInjector;
@@ -150,10 +130,9 @@ public class KernelCpuThreadReader {
/**
* Create with a path where `proc` is mounted. Used primarily for testing
*
- * @param procPath where `proc` is mounted (to find, see {@code mount | grep
- * ^proc})
+ * @param procPath where `proc` is mounted (to find, see {@code mount | grep ^proc})
* @param initialTimeInStatePath where the initial {@code time_in_state} file exists to define
- * format
+ * format
*/
@VisibleForTesting
public KernelCpuThreadReader(
@@ -162,7 +141,8 @@ public class KernelCpuThreadReader {
int minimumTotalCpuUsageMillis,
Path procPath,
Path initialTimeInStatePath,
- Injector injector) throws IOException {
+ Injector injector)
+ throws IOException {
mUidPredicate = uidPredicate;
mMinimumTotalCpuUsageMillis = minimumTotalCpuUsageMillis;
mProcPath = procPath;
@@ -205,7 +185,7 @@ public class KernelCpuThreadReader {
* #setUidPredicate}.
*/
@Nullable
- public ArrayList<ProcessCpuUsage> getProcessCpuUsageByUids() {
+ public ArrayList<ProcessCpuUsage> getProcessCpuUsage() {
if (DEBUG) {
Slog.d(TAG, "Reading CPU thread usages for processes owned by UIDs");
}
@@ -213,7 +193,7 @@ public class KernelCpuThreadReader {
final ArrayList<ProcessCpuUsage> processCpuUsages = new ArrayList<>();
try (DirectoryStream<Path> processPaths =
- Files.newDirectoryStream(mProcPath, PROCESS_DIRECTORY_FILTER)) {
+ Files.newDirectoryStream(mProcPath, PROCESS_DIRECTORY_FILTER)) {
for (Path processPath : processPaths) {
final int processId = getProcessId(processPath);
final int uid = mInjector.getUidForPid(processId);
@@ -231,7 +211,7 @@ public class KernelCpuThreadReader {
}
}
} catch (IOException e) {
- Slog.w("Failed to iterate over process paths", e);
+ Slog.w(TAG, "Failed to iterate over process paths", e);
return null;
}
@@ -248,30 +228,68 @@ public class KernelCpuThreadReader {
}
/**
- * Read all of the CPU usage statistics for each child thread of the current process
- *
- * @return process CPU usage containing usage of all child threads
+ * Get the CPU frequencies that correspond to the times reported in {@link
+ * ThreadCpuUsage#usageTimesMillis}
*/
@Nullable
- public ProcessCpuUsage getCurrentProcessCpuUsage() {
- return getProcessCpuUsage(mProcPath.resolve("self"), mInjector.myPid(), mInjector.myUid());
+ public int[] getCpuFrequenciesKhz() {
+ return mFrequenciesKhz;
+ }
+
+ /** Set the number of frequency buckets to use */
+ void setNumBuckets(int numBuckets) {
+ if (numBuckets < 1) {
+ Slog.w(TAG, "Number of buckets must be at least 1, but was " + numBuckets);
+ return;
+ }
+ // If `numBuckets` hasn't changed since the last set, do nothing
+ if (mFrequenciesKhz != null && mFrequenciesKhz.length == numBuckets) {
+ return;
+ }
+ mFrequencyBucketCreator =
+ new FrequencyBucketCreator(mProcTimeInStateReader.getFrequenciesKhz(), numBuckets);
+ mFrequenciesKhz =
+ mFrequencyBucketCreator.getBucketMinFrequencies(
+ mProcTimeInStateReader.getFrequenciesKhz());
+ }
+
+ /** Set the UID predicate for {@link #getProcessCpuUsage} */
+ void setUidPredicate(Predicate<Integer> uidPredicate) {
+ mUidPredicate = uidPredicate;
+ }
+
+ /**
+ * If a thread has strictly less than {@code minimumTotalCpuUsageMillis} total CPU usage, it
+ * will not be reported
+ */
+ void setMinimumTotalCpuUsageMillis(int minimumTotalCpuUsageMillis) {
+ if (minimumTotalCpuUsageMillis < 0) {
+ Slog.w(TAG, "Negative minimumTotalCpuUsageMillis: " + minimumTotalCpuUsageMillis);
+ return;
+ }
+ mMinimumTotalCpuUsageMillis = minimumTotalCpuUsageMillis;
}
/**
* Read all of the CPU usage statistics for each child thread of a process
*
* @param processPath the {@code /proc} path of the thread
- * @param processId the ID of the process
- * @param uid the ID of the user who owns the process
+ * @param processId the ID of the process
+ * @param uid the ID of the user who owns the process
* @return process CPU usage containing usage of all child threads. Null if the process exited
- * and its {@code proc} directory was removed while collecting information
+ * and its {@code proc} directory was removed while collecting information
*/
@Nullable
private ProcessCpuUsage getProcessCpuUsage(Path processPath, int processId, int uid) {
if (DEBUG) {
- Slog.d(TAG, "Reading CPU thread usages with directory " + processPath
- + " process ID " + processId
- + " and user ID " + uid);
+ Slog.d(
+ TAG,
+ "Reading CPU thread usages with directory "
+ + processPath
+ + " process ID "
+ + processId
+ + " and user ID "
+ + uid);
}
int[] filteredThreadsCpuUsage = null;
@@ -305,64 +323,15 @@ public class KernelCpuThreadReader {
// Add the filtered out thread CPU usage under an "other threads" ThreadCpuUsage
if (filteredThreadsCpuUsage != null) {
- threadCpuUsages.add(new ThreadCpuUsage(
- OTHER_THREADS_ID, OTHER_THREADS_NAME, filteredThreadsCpuUsage));
+ threadCpuUsages.add(
+ new ThreadCpuUsage(
+ OTHER_THREADS_ID, OTHER_THREADS_NAME, filteredThreadsCpuUsage));
}
if (DEBUG) {
Slog.d(TAG, "Read CPU usage of " + threadCpuUsages.size() + " threads");
}
- return new ProcessCpuUsage(
- processId,
- getProcessName(processPath),
- uid,
- threadCpuUsages);
- }
-
- /**
- * Set the number of frequency buckets to use
- */
- void setNumBuckets(int numBuckets) {
- if (numBuckets < 1) {
- Slog.w(TAG, "Number of buckets must be at least 1, but was " + numBuckets);
- return;
- }
- // If `numBuckets` hasn't changed since the last set, do nothing
- if (mFrequenciesKhz != null && mFrequenciesKhz.length == numBuckets) {
- return;
- }
- mFrequencyBucketCreator = new FrequencyBucketCreator(
- mProcTimeInStateReader.getFrequenciesKhz(), numBuckets);
- mFrequenciesKhz = mFrequencyBucketCreator.getBucketMinFrequencies(
- mProcTimeInStateReader.getFrequenciesKhz());
- }
-
- /**
- * Set the UID predicate for {@link #getProcessCpuUsageByUids}
- */
- void setUidPredicate(Predicate<Integer> uidPredicate) {
- mUidPredicate = uidPredicate;
- }
-
- /**
- * If a thread has strictly less than {@code minimumTotalCpuUsageMillis} total CPU usage, it
- * will not be reported
- */
- void setMinimumTotalCpuUsageMillis(int minimumTotalCpuUsageMillis) {
- if (minimumTotalCpuUsageMillis < 0) {
- Slog.w(TAG, "Negative minimumTotalCpuUsageMillis: " + minimumTotalCpuUsageMillis);
- return;
- }
- mMinimumTotalCpuUsageMillis = minimumTotalCpuUsageMillis;
- }
-
- /**
- * Get the CPU frequencies that correspond to the times reported in
- * {@link ThreadCpuUsage#usageTimesMillis}
- */
- @Nullable
- public int[] getCpuFrequenciesKhz() {
- return mFrequenciesKhz;
+ return new ProcessCpuUsage(processId, getProcessName(processPath), uid, threadCpuUsages);
}
/**
@@ -370,7 +339,7 @@ public class KernelCpuThreadReader {
*
* @param threadDirectory the {@code /proc} directory of the thread
* @return thread CPU usage. Null if the thread exited and its {@code proc} directory was
- * removed while collecting information
+ * removed while collecting information
*/
@Nullable
private ThreadCpuUsage getThreadCpuUsage(Path threadDirectory) {
@@ -398,27 +367,21 @@ public class KernelCpuThreadReader {
return new ThreadCpuUsage(threadId, threadName, cpuUsages);
}
- /**
- * Get the command used to start a process
- */
+ /** Get the command used to start a process */
private String getProcessName(Path processPath) {
final Path processNamePath = processPath.resolve(PROCESS_NAME_FILENAME);
- final String processName =
- ProcStatsUtil.readSingleLineProcFile(processNamePath.toString());
+ final String processName = ProcStatsUtil.readSingleLineProcFile(processNamePath.toString());
if (processName != null) {
return processName;
}
return DEFAULT_PROCESS_NAME;
}
- /**
- * Get the name of a thread, given the {@code /proc} path of the thread
- */
+ /** Get the name of a thread, given the {@code /proc} path of the thread */
private String getThreadName(Path threadPath) {
final Path threadNamePath = threadPath.resolve(THREAD_NAME_FILENAME);
- final String threadName =
- ProcStatsUtil.readNullSeparatedFile(threadNamePath.toString());
+ final String threadName = ProcStatsUtil.readNullSeparatedFile(threadNamePath.toString());
if (threadName == null) {
return DEFAULT_THREAD_NAME;
}
@@ -441,9 +404,8 @@ public class KernelCpuThreadReader {
}
}
- /**
- * Get the sum of all CPU usage across all frequencies
- */
+ /** Get the sum of all CPU usage across all frequencies */
+ @SuppressWarnings("ForLoopReplaceableByForEach")
private static int totalCpuUsage(int[] cpuUsage) {
int total = 0;
for (int i = 0; i < cpuUsage.length; i++) {
@@ -452,9 +414,7 @@ public class KernelCpuThreadReader {
return total;
}
- /**
- * Add two CPU frequency usages together
- */
+ /** Add two CPU frequency usages together */
private static int[] sumCpuUsage(int[] a, int[] b) {
int[] summed = new int[a.length];
for (int i = 0; i < a.length; i++) {
@@ -463,9 +423,7 @@ public class KernelCpuThreadReader {
return summed;
}
- /**
- * Puts frequencies and usage times into buckets
- */
+ /** Puts frequencies and usage times into buckets */
@VisibleForTesting
public static class FrequencyBucketCreator {
private final int mNumBuckets;
@@ -480,7 +438,7 @@ public class KernelCpuThreadReader {
* Buckets based of a list of frequencies
*
* @param frequencies the frequencies to base buckets off
- * @param numBuckets how many buckets to create
+ * @param numBuckets how many buckets to create
*/
@VisibleForTesting
public FrequencyBucketCreator(long[] frequencies, int numBuckets) {
@@ -502,20 +460,20 @@ public class KernelCpuThreadReader {
// Ensure that we don't have more buckets than frequencies
mLittleNumBuckets = Math.min(littleNumBuckets, mBigFrequenciesStartIndex);
- mBigNumBuckets = Math.min(
- bigNumBuckets, frequencies.length - mBigFrequenciesStartIndex);
+ mBigNumBuckets =
+ Math.min(bigNumBuckets, frequencies.length - mBigFrequenciesStartIndex);
mNumBuckets = mLittleNumBuckets + mBigNumBuckets;
// Set the size of each little and big bucket. If they have no buckets, the size is zero
- mLittleBucketSize = mLittleNumBuckets == 0 ? 0 :
- mBigFrequenciesStartIndex / mLittleNumBuckets;
- mBigBucketSize = mBigNumBuckets == 0 ? 0 :
- (frequencies.length - mBigFrequenciesStartIndex) / mBigNumBuckets;
+ mLittleBucketSize =
+ mLittleNumBuckets == 0 ? 0 : mBigFrequenciesStartIndex / mLittleNumBuckets;
+ mBigBucketSize =
+ mBigNumBuckets == 0
+ ? 0
+ : (frequencies.length - mBigFrequenciesStartIndex) / mBigNumBuckets;
}
- /**
- * Find the index where frequencies change from little core to big core
- */
+ /** Find the index where frequencies change from little core to big core */
@VisibleForTesting
public static int getBigFrequenciesStartIndex(long[] frequenciesKhz) {
for (int i = 0; i < frequenciesKhz.length - 1; i++) {
@@ -527,16 +485,14 @@ public class KernelCpuThreadReader {
return frequenciesKhz.length;
}
- /**
- * Get the minimum frequency in each bucket
- */
+ /** Get the minimum frequency in each bucket */
@VisibleForTesting
public int[] getBucketMinFrequencies(long[] frequenciesKhz) {
Preconditions.checkArgument(frequenciesKhz.length == mNumFrequencies);
// If there's only one bucket, we bucket everything together so the first bucket is the
// min frequency
if (mNumBuckets == 1) {
- return new int[]{(int) frequenciesKhz[0]};
+ return new int[] {(int) frequenciesKhz[0]};
}
final int[] bucketMinFrequencies = new int[mNumBuckets];
@@ -561,6 +517,7 @@ public class KernelCpuThreadReader {
* @return the bucketed usage times
*/
@VisibleForTesting
+ @SuppressWarnings("ForLoopReplaceableByForEach")
public int[] getBucketedValues(long[] values) {
Preconditions.checkArgument(values.length == mNumFrequencies);
final int[] bucketed = new int[mNumBuckets];
@@ -580,18 +537,18 @@ public class KernelCpuThreadReader {
}
// Initialize the big buckets
for (int i = mBigFrequenciesStartIndex; i < values.length; i++) {
- final int bucketIndex = Math.min(
- mLittleNumBuckets + (i - mBigFrequenciesStartIndex) / mBigBucketSize,
- mNumBuckets - 1);
+ final int bucketIndex =
+ Math.min(
+ mLittleNumBuckets
+ + (i - mBigFrequenciesStartIndex) / mBigBucketSize,
+ mNumBuckets - 1);
bucketed[bucketIndex] += values[i];
}
return bucketed;
}
}
- /**
- * CPU usage of a process
- */
+ /** CPU usage of a process */
public static class ProcessCpuUsage {
public final int processId;
public final String processName;
@@ -610,46 +567,23 @@ public class KernelCpuThreadReader {
}
}
- /**
- * CPU usage of a thread
- */
+ /** CPU usage of a thread */
public static class ThreadCpuUsage {
public final int threadId;
public final String threadName;
public final int[] usageTimesMillis;
- ThreadCpuUsage(
- int threadId,
- String threadName,
- int[] usageTimesMillis) {
+ ThreadCpuUsage(int threadId, String threadName, int[] usageTimesMillis) {
this.threadId = threadId;
this.threadName = threadName;
this.usageTimesMillis = usageTimesMillis;
}
}
- /**
- * Used to inject static methods from {@link Process}
- */
+ /** Used to inject static methods from {@link Process} */
@VisibleForTesting
public static class Injector {
- /**
- * Get the PID of the current process
- */
- public int myPid() {
- return Process.myPid();
- }
-
- /**
- * Get the UID that owns the current process
- */
- public int myUid() {
- return Process.myUid();
- }
-
- /**
- * Get the UID for the process with ID {@code pid}
- */
+ /** Get the UID for the process with ID {@code pid} */
public int getUidForPid(int pid) {
return Process.getUidForPid(pid);
}
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
index b8dfe0d63a66..3851ce6d9cbd 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
@@ -47,33 +47,29 @@ import java.util.regex.Pattern;
public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
private static final String TAG = "KernelCpuThreadReaderSettingsObserver";
- /**
- * The number of frequency buckets to report
- */
+ /** The number of frequency buckets to report */
private static final String NUM_BUCKETS_SETTINGS_KEY = "num_buckets";
+
private static final int NUM_BUCKETS_DEFAULT = 8;
- /**
- * List of UIDs to report data for
- */
+ /** List of UIDs to report data for */
private static final String COLLECTED_UIDS_SETTINGS_KEY = "collected_uids";
+
private static final String COLLECTED_UIDS_DEFAULT = "0-0;1000-1000";
- /**
- * Minimum total CPU usage to report
- */
+ /** Minimum total CPU usage to report */
private static final String MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY =
"minimum_total_cpu_usage_millis";
+
private static final int MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT = 10000;
private final Context mContext;
- @Nullable
- private final KernelCpuThreadReader mKernelCpuThreadReader;
+ @Nullable private final KernelCpuThreadReader mKernelCpuThreadReader;
/**
- * @return returns a created {@link KernelCpuThreadReader} that will be modified by any
- * change in settings, returns null if creation failed
+ * @return returns a created {@link KernelCpuThreadReader} that will be modified by any change
+ * in settings, returns null if creation failed
*/
@Nullable
public static KernelCpuThreadReader getSettingsModifiedReader(Context context) {
@@ -81,10 +77,10 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
KernelCpuThreadReaderSettingsObserver settingsObserver =
new KernelCpuThreadReaderSettingsObserver(context);
// Register the observer to listen for setting changes
- Uri settingsUri =
- Settings.Global.getUriFor(Settings.Global.KERNEL_CPU_THREAD_READER);
- context.getContentResolver().registerContentObserver(
- settingsUri, false, settingsObserver, UserHandle.USER_SYSTEM);
+ Uri settingsUri = Settings.Global.getUriFor(Settings.Global.KERNEL_CPU_THREAD_READER);
+ context.getContentResolver()
+ .registerContentObserver(
+ settingsUri, false, settingsObserver, UserHandle.USER_SYSTEM);
// Return the observer's reader
return settingsObserver.mKernelCpuThreadReader;
}
@@ -92,10 +88,11 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
private KernelCpuThreadReaderSettingsObserver(Context context) {
super(BackgroundThread.getHandler());
mContext = context;
- mKernelCpuThreadReader = KernelCpuThreadReader.create(
- NUM_BUCKETS_DEFAULT,
- UidPredicate.fromString(COLLECTED_UIDS_DEFAULT),
- MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT);
+ mKernelCpuThreadReader =
+ KernelCpuThreadReader.create(
+ NUM_BUCKETS_DEFAULT,
+ UidPredicate.fromString(COLLECTED_UIDS_DEFAULT),
+ MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT);
}
@Override
@@ -103,9 +100,7 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
updateReader();
}
- /**
- * Update the reader with new settings
- */
+ /** Update the reader with new settings */
private void updateReader() {
if (mKernelCpuThreadReader == null) {
return;
@@ -113,8 +108,10 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
final KeyValueListParser parser = new KeyValueListParser(',');
try {
- parser.setString(Settings.Global.getString(
- mContext.getContentResolver(), Settings.Global.KERNEL_CPU_THREAD_READER));
+ parser.setString(
+ Settings.Global.getString(
+ mContext.getContentResolver(),
+ Settings.Global.KERNEL_CPU_THREAD_READER));
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Bad settings", e);
return;
@@ -122,8 +119,9 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
final UidPredicate uidPredicate;
try {
- uidPredicate = UidPredicate.fromString(
- parser.getString(COLLECTED_UIDS_SETTINGS_KEY, COLLECTED_UIDS_DEFAULT));
+ uidPredicate =
+ UidPredicate.fromString(
+ parser.getString(COLLECTED_UIDS_SETTINGS_KEY, COLLECTED_UIDS_DEFAULT));
} catch (NumberFormatException e) {
Slog.w(TAG, "Failed to get UID predicate", e);
return;
@@ -132,14 +130,13 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
mKernelCpuThreadReader.setNumBuckets(
parser.getInt(NUM_BUCKETS_SETTINGS_KEY, NUM_BUCKETS_DEFAULT));
mKernelCpuThreadReader.setUidPredicate(uidPredicate);
- mKernelCpuThreadReader.setMinimumTotalCpuUsageMillis(parser.getInt(
- MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY,
- MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT));
+ mKernelCpuThreadReader.setMinimumTotalCpuUsageMillis(
+ parser.getInt(
+ MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY,
+ MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT));
}
- /**
- * Check whether a UID belongs to a set of UIDs
- */
+ /** Check whether a UID belongs to a set of UIDs */
@VisibleForTesting
public static class UidPredicate implements Predicate<Integer> {
private static final Pattern UID_RANGE_PATTERN = Pattern.compile("([0-9]+)-([0-9]+)");
@@ -150,14 +147,14 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
* Create a UID predicate from a string representing a list of UID ranges
*
* <p>UID ranges are a pair of integers separated by a '-'. If you want to specify a single
- * UID (e.g. UID 1000), you can use {@code 1000-1000}. Lists of ranges are separated by
- * a single ';'. For example, this would be a valid string representation: {@code
+ * UID (e.g. UID 1000), you can use {@code 1000-1000}. Lists of ranges are separated by a
+ * single ';'. For example, this would be a valid string representation: {@code
* "1000-1999;2003-2003;2004-2004;2050-2060"}.
*
* <p>We do not use ',' to delimit as it is already used in separating different setting
* arguments.
*
- * @throws NumberFormatException if the input string is incorrectly formatted
+ * @throws NumberFormatException if the input string is incorrectly formatted
* @throws IllegalArgumentException if an UID range has a lower end than start
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -169,9 +166,10 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
throw new NumberFormatException(
"Failed to recognize as number range: " + uidSpecifier);
}
- acceptedUidRanges.add(Range.create(
- Integer.parseInt(uidRangeMatcher.group(1)),
- Integer.parseInt(uidRangeMatcher.group(2))));
+ acceptedUidRanges.add(
+ Range.create(
+ Integer.parseInt(uidRangeMatcher.group(1)),
+ Integer.parseInt(uidRangeMatcher.group(2))));
}
return new UidPredicate(acceptedUidRanges);
}
@@ -181,6 +179,7 @@ public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
}
@Override
+ @SuppressWarnings("ForLoopReplaceableByForEach")
public boolean test(Integer uid) {
for (int i = 0; i < mAcceptedUidRanges.size(); i++) {
if (mAcceptedUidRanges.get(i).contains(uid)) {
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index b4be3f599604..0c53fb2f697a 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2319,4 +2319,10 @@ enum PageId {
// Settings > Display > Theme
DARK_UI_SETTINGS = 1698;
+
+ // Settings > global bubble settings
+ BUBBLE_SETTINGS = 1699;
+
+ // Settings > app > bubble settings
+ APP_BUBBLE_SETTINGS = 1700;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cb8ece7070be..8bfa038c8e8f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4426,6 +4426,13 @@
<permission android:name="android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE"
android:protectionLevel="signature" />
+ <!-- Must be required by an {@link android.service.watchdog.ExplicitHealthCheckService} to
+ ensure that only the system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
<!-- @hide Permission that allows configuring appops.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MANAGE_APPOPS"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8168933f6ba8..bb473705b416 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4838,10 +4838,10 @@
<string name="confirm_battery_saver">Confirm</string>
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description, with a "learn more" link. -->
- <string name="battery_saver_description_with_learn_more">To extend your battery life, Battery Saver turns off some device features and restricts apps. <annotation id="url">Learn More</annotation></string>
+ <string name="battery_saver_description_with_learn_more">Battery Saver turns off or restricts background activity, some visual effects \u0026 other high-power features to extend battery life. <annotation id="url">Learn More</annotation></string>
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description, without a "learn more" link. -->
- <string name="battery_saver_description">To extend your battery life, Battery Saver turns off some device features and restricts apps.</string>
+ <string name="battery_saver_description">Battery Saver turns off or restricts background activity, some visual effects \u0026 other high-power features to extend battery life.</string>
<!-- [CHAR_LIMIT=NONE] Data saver: Feature description -->
<string name="data_saver_description">To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them.</string>
diff --git a/core/tests/coretests/res/raw/com_android_tzdata.apex b/core/tests/coretests/res/raw/com_android_tzdata.apex
index 72294dead2de..06ea8fad6393 100644
--- a/core/tests/coretests/res/raw/com_android_tzdata.apex
+++ b/core/tests/coretests/res/raw/com_android_tzdata.apex
Binary files differ
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
index 52b26589279f..3d252fbddb80 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
@@ -30,6 +30,15 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link ClientTransaction}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:ClientTransactionTests
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index ad28d13dc46a..447f28e06d7e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -42,6 +42,15 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link ObjectPool}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:ObjectPoolTests
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index f730a244a593..1cca79954138 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -26,9 +26,8 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
-import static junit.framework.Assert.assertEquals;
-
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
@@ -61,7 +60,15 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-/** Test {@link TransactionExecutor} logic. */
+/**
+ * Test {@link TransactionExecutor} logic.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:TransactionExecutorTests
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index d73c174212bd..d117b4096ca0 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -21,8 +21,8 @@ import static android.app.servertransaction.TestUtils.mergedConfig;
import static android.app.servertransaction.TestUtils.referrerIntentList;
import static android.app.servertransaction.TestUtils.resultInfoList;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
@@ -64,7 +64,15 @@ import org.junit.runner.RunWith;
import java.util.List;
import java.util.Map;
-/** Test parcelling and unparcelling of transactions and transaction items. */
+/**
+ * Test parcelling and unparcelling of transactions and transaction items.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:TransactionParcelTests
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index aa0e0cdae265..0798c0c0805a 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -500,18 +500,30 @@ public class PackageParserTest {
File apexFile = copyRawResourceToFile("com.android.tzdata.apex",
R.raw.com_android_tzdata);
PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexFile, false);
- assertEquals("com.google.android.tzdata", pi.packageName);
assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
- assertEquals(1, pi.getLongVersionCode());
+ assertTrue(pi.applicationInfo.enabled);
+ assertEquals(28, pi.applicationInfo.targetSdkVersion);
assertEquals(1, pi.applicationInfo.longVersionCode);
+
+ assertEquals("com.google.android.tzdata", pi.packageName);
+ assertTrue(pi.splitNames.length > 0);
+ assertEquals(1, pi.getLongVersionCode());
assertNull(pi.signingInfo);
+ assertNull(pi.signatures);
+ assertTrue(pi.isApex);
pi = PackageParser.generatePackageInfoFromApex(apexFile, true);
- assertEquals("com.google.android.tzdata", pi.packageName);
assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
- assertEquals(1, pi.getLongVersionCode());
+ assertTrue(pi.applicationInfo.enabled);
+ assertEquals(28, pi.applicationInfo.targetSdkVersion);
assertEquals(1, pi.applicationInfo.longVersionCode);
+
+ assertEquals("com.google.android.tzdata", pi.packageName);
+ assertTrue(pi.splitNames.length > 0);
+ assertEquals(1, pi.getLongVersionCode());
assertNotNull(pi.signingInfo);
+ assertNotNull(pi.signatures);
assertTrue(pi.signingInfo.getApkContentsSigners().length > 0);
+ assertTrue(pi.isApex);
}
}
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index dd50af877bbb..182fe78dfa7a 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -44,6 +44,15 @@ import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.Collections;
+/**
+ * Tests for {@link DisplayCutout}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:DisplayCutoutTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 23ab05e952a3..ebbbdec7d376 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -18,18 +18,15 @@ package android.view;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
-
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowInsets.Type.sideBars;
import static android.view.WindowInsets.Type.systemBars;
-import static android.view.WindowInsets.Type.topBar;
-import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -55,6 +52,15 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
+/**
+ * Tests for {@link InsetsAnimationControlImpl}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:InsetsAnimationControlImplTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index d71bde837d6f..4d8d3f68f875 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -19,13 +19,13 @@ package android.view;
import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
-
import static android.view.WindowInsets.Type.topBar;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static junit.framework.Assert.assertEquals;
-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.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
@@ -53,6 +53,15 @@ import org.mockito.ArgumentCaptor;
import java.util.concurrent.CountDownLatch;
+/**
+ * Tests for {@link InsetsController}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:InsetsControllerTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 4266ba9fe86e..a32fa778e736 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -43,6 +43,15 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+/**
+ * Tests for {@link InsetsSourceConsumer}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:InsetsSourceConsumerTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 98ab3e785d0a..b55a9c600a61 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -18,7 +18,7 @@ package android.view;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
-import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -31,6 +31,15 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link InsetsSource}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:InsetsSourceTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index bd036b01c0cf..8e167da84e08 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -24,14 +24,13 @@ import static android.view.InsetsState.TYPE_SIDE_BAR_1;
import static android.view.InsetsState.TYPE_SIDE_BAR_2;
import static android.view.InsetsState.TYPE_SIDE_BAR_3;
import static android.view.InsetsState.TYPE_TOP_BAR;
-
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -47,6 +46,15 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link InsetsState}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:InsetsStateTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 1cb71f98a74d..1a22a70eed36 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -45,7 +45,6 @@ import org.mockito.stubbing.Answer;
import java.util.Arrays;
import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
@LargeTest
@RunWith(AndroidJUnit4.class)
@@ -61,16 +60,12 @@ public class AccessibilityCacheTest {
AccessibilityCache mAccessibilityCache;
AccessibilityCache.AccessibilityNodeRefresher mAccessibilityNodeRefresher;
- AtomicInteger mNumA11yNodeInfosInUse = new AtomicInteger(0);
- AtomicInteger mNumA11yWinInfosInUse = new AtomicInteger(0);
@Before
public void setUp() {
mAccessibilityNodeRefresher = mock(AccessibilityCache.AccessibilityNodeRefresher.class);
when(mAccessibilityNodeRefresher.refreshNode(anyObject(), anyBoolean())).thenReturn(true);
mAccessibilityCache = new AccessibilityCache(mAccessibilityNodeRefresher);
- AccessibilityNodeInfo.setNumInstancesInUseCounter(mNumA11yNodeInfosInUse);
- AccessibilityWindowInfo.setNumInstancesInUseCounter(mNumA11yWinInfosInUse);
}
@After
@@ -78,8 +73,6 @@ public class AccessibilityCacheTest {
// Make sure we're recycling all of our window and node infos
mAccessibilityCache.clear();
AccessibilityInteractionClient.getInstance().clearCache();
- assertEquals(0, mNumA11yWinInfosInUse.get());
- assertEquals(0, mNumA11yNodeInfosInUse.get());
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
index 1c84829c5491..e9cad0acfcc6 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
@@ -35,6 +35,7 @@ import org.junit.runner.RunWith;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.OptionalDouble;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
@@ -126,17 +127,21 @@ public class KernelCpuThreadReaderEndToEndTest {
final KernelCpuThreadReader kernelCpuThreadReader =
KernelCpuThreadReader.create(8, uid -> uid == Process.myUid(), 0);
assertNotNull(kernelCpuThreadReader);
- final ProcessCpuUsage currentProcessCpuUsage =
- kernelCpuThreadReader.getCurrentProcessCpuUsage();
+ kernelCpuThreadReader.setUidPredicate(uid -> uid == Process.myUid());
+ final Optional<ProcessCpuUsage> currentProcessCpuUsage =
+ kernelCpuThreadReader.getProcessCpuUsage().stream()
+ .filter(p -> p.processId == Process.myPid())
+ .findFirst();
+ assertTrue(currentProcessCpuUsage.isPresent());
// Threads can terminate, as we've finished crawling them from /proc
threadFinishedLatch.countDown();
// Check that we've got times for every thread we spawned
- final List<ThreadCpuUsage> threadCpuUsages = currentProcessCpuUsage.threadCpuUsages
- .stream()
- .filter((thread) -> thread.threadName.startsWith(tag))
- .collect(Collectors.toList());
+ final List<ThreadCpuUsage> threadCpuUsages =
+ currentProcessCpuUsage.get().threadCpuUsages.stream()
+ .filter((thread) -> thread.threadName.startsWith(tag))
+ .collect(Collectors.toList());
assertEquals(
"Incorrect number of threads returned by KernelCpuThreadReader",
numSamples, threadCpuUsages.size());
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
index e6e7a85ae16e..61209e21dda8 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
@@ -25,6 +25,7 @@ import static org.testng.Assert.assertThrows;
import android.content.Context;
import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -44,27 +45,10 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Predicate;
+@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KernelCpuThreadReaderTest {
-
- private static final int UID = 1000;
- private static final int PROCESS_ID = 1234;
- private static final int[] THREAD_IDS = {0, 1000, 1235, 4321};
- private static final String PROCESS_NAME = "test_process";
- private static final String[] THREAD_NAMES = {
- "test_thread_1", "test_thread_2", "test_thread_3", "test_thread_4"
- };
- private static final int[] THREAD_CPU_FREQUENCIES = {
- 1000, 2000, 3000, 4000,
- };
- private static final int[][] THREAD_CPU_TIMES = {
- {1, 0, 0, 1},
- {0, 0, 0, 0},
- {1000, 1000, 1000, 1000},
- {0, 1, 2, 3},
- };
-
private File mProcDirectory;
@Before
@@ -79,41 +63,6 @@ public class KernelCpuThreadReaderTest {
}
@Test
- public void testReader_currentProcess() throws IOException {
- KernelCpuThreadReader.Injector processUtils =
- new KernelCpuThreadReader.Injector() {
- @Override
- public int myPid() {
- return PROCESS_ID;
- }
-
- @Override
- public int myUid() {
- return UID;
- }
-
- @Override
- public int getUidForPid(int pid) {
- return 0;
- }
- };
- setupDirectory(mProcDirectory.toPath().resolve("self"), THREAD_IDS, PROCESS_NAME,
- THREAD_NAMES, THREAD_CPU_FREQUENCIES, THREAD_CPU_TIMES);
-
- final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader(
- 8,
- uid -> 1000 <= uid && uid < 2000,
- 0,
- mProcDirectory.toPath(),
- mProcDirectory.toPath().resolve("self/task/" + THREAD_IDS[0] + "/time_in_state"),
- processUtils);
- final KernelCpuThreadReader.ProcessCpuUsage processCpuUsage =
- kernelCpuThreadReader.getCurrentProcessCpuUsage();
- checkResults(processCpuUsage, kernelCpuThreadReader.getCpuFrequenciesKhz(), UID, PROCESS_ID,
- THREAD_IDS, PROCESS_NAME, THREAD_NAMES, THREAD_CPU_FREQUENCIES, THREAD_CPU_TIMES);
- }
-
- @Test
public void testReader_byUids() throws IOException {
int[] uids = new int[]{0, 2, 3, 4, 5, 6000};
Predicate<Integer> uidPredicate = uid -> uid == 0 || uid >= 4;
@@ -121,16 +70,6 @@ public class KernelCpuThreadReaderTest {
KernelCpuThreadReader.Injector processUtils =
new KernelCpuThreadReader.Injector() {
@Override
- public int myPid() {
- return 0;
- }
-
- @Override
- public int myUid() {
- return 0;
- }
-
- @Override
public int getUidForPid(int pid) {
return pid;
}
@@ -150,7 +89,7 @@ public class KernelCpuThreadReaderTest {
mProcDirectory.toPath().resolve(uids[0] + "/task/" + uids[0] + "/time_in_state"),
processUtils);
ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsageByUids =
- kernelCpuThreadReader.getProcessCpuUsageByUids();
+ kernelCpuThreadReader.getProcessCpuUsage();
processCpuUsageByUids.sort(Comparator.comparing(usage -> usage.processId));
assertEquals(expectedUids.length, processCpuUsageByUids.size());
@@ -173,16 +112,6 @@ public class KernelCpuThreadReaderTest {
KernelCpuThreadReader.Injector processUtils =
new KernelCpuThreadReader.Injector() {
@Override
- public int myPid() {
- return 0;
- }
-
- @Override
- public int myUid() {
- return 0;
- }
-
- @Override
public int getUidForPid(int pid) {
return pid;
}
@@ -206,7 +135,7 @@ public class KernelCpuThreadReaderTest {
mProcDirectory.toPath().resolve(uids[0] + "/task/" + uids[0] + "/time_in_state"),
processUtils);
ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsageByUids =
- kernelCpuThreadReader.getProcessCpuUsageByUids();
+ kernelCpuThreadReader.getProcessCpuUsage();
processCpuUsageByUids.sort(Comparator.comparing(usage -> usage.uid));
assertEquals(expectedUids.length, processCpuUsageByUids.size());
@@ -220,7 +149,7 @@ public class KernelCpuThreadReaderTest {
@Test
public void testReader_otherThreads() throws IOException {
- final Path processPath = mProcDirectory.toPath().resolve("self");
+ final Path processPath = mProcDirectory.toPath().resolve("1000");
setupDirectory(
processPath,
new int[]{1, 2, 3},
@@ -228,39 +157,34 @@ public class KernelCpuThreadReaderTest {
new String[]{"thread1", "thread2", "thread3"},
new int[]{1000, 2000},
new int[][]{{0, 100}, {10, 0}, {0, 300}});
- final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader(
- 8,
- i -> true,
- 2000,
- mProcDirectory.toPath(),
- processPath.resolve("task/1/time_in_state"),
+ KernelCpuThreadReader.Injector injector =
new KernelCpuThreadReader.Injector() {
@Override
- public int myPid() {
- return 1000;
- }
-
- @Override
- public int myUid() {
- return 0;
- }
-
- @Override
public int getUidForPid(int pid) {
return 0;
}
- });
+ };
+ final KernelCpuThreadReader kernelCpuThreadReader =
+ new KernelCpuThreadReader(
+ 8,
+ uid -> true,
+ 2000,
+ mProcDirectory.toPath(),
+ processPath.resolve("task/1/time_in_state"),
+ injector);
+ ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages =
+ kernelCpuThreadReader.getProcessCpuUsage();
+ assertEquals(1, processCpuUsages.size());
checkResults(
- kernelCpuThreadReader.getCurrentProcessCpuUsage(),
+ processCpuUsages.get(0),
kernelCpuThreadReader.getCpuFrequenciesKhz(),
0,
1000,
- new int[]{-1, 3},
+ new int[] {-1, 3},
"process",
- new String[]{"__OTHER_THREADS", "thread3"},
- new int[]{1000, 2000},
- new int[][]{{100, 1000}, {0, 3000}}
- );
+ new String[] {"__OTHER_THREADS", "thread3"},
+ new int[] {1000, 2000},
+ new int[][] {{10, 100}, {0, 300}});
}
private void setupDirectory(Path processPath, int[] threadIds, String processName,
@@ -289,8 +213,7 @@ public class KernelCpuThreadReaderTest {
final OutputStream timeInStateStream =
Files.newOutputStream(threadPath.resolve("time_in_state"));
for (int j = 0; j < cpuFrequencies.length; j++) {
- final String line = String.valueOf(cpuFrequencies[j]) + " "
- + String.valueOf(cpuTimes[i][j]) + "\n";
+ final String line = cpuFrequencies[j] + " " + cpuTimes[i][j] + "\n";
timeInStateStream.write(line.getBytes());
}
timeInStateStream.close();
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index bb4765835890..3968f84471c5 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -66,6 +66,14 @@ prebuilt_etc {
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.emergency",
+ product_specific: true,
+ sub_dir: "permissions",
+ src: "com.android.emergency.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.android.launcher3",
product_specific: true,
sub_dir: "permissions",
diff --git a/data/etc/com.android.emergency.xml b/data/etc/com.android.emergency.xml
new file mode 100644
index 000000000000..28f99dd1d018
--- /dev/null
+++ b/data/etc/com.android.emergency.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.emergency">
+ <!-- Required to place emergency calls from emergency info screen. -->
+ <permission name="android.permission.CALL_PRIVILEGED"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index afb50714a93d..347edc5dbbd7 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -50,12 +50,6 @@ applications that come with the platform
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
</privapp-permissions>
- <privapp-permissions package="com.android.emergency">
- <!-- Required to place emergency calls from emergency info screen. -->
- <permission name="android.permission.CALL_PRIVILEGED"/>
- <permission name="android.permission.MANAGE_USERS"/>
- </privapp-permissions>
-
<privapp-permissions package="com.android.externalstorage">
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
@@ -124,6 +118,7 @@ applications that come with the platform
<permission name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL"/>
<permission name="android.permission.APPROVE_INCIDENT_REPORTS"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+ <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
</privapp-permissions>
<privapp-permissions package="com.android.phone">
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 4bd344f1964f..170dec26f361 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1813,21 +1813,22 @@ public final class Bitmap implements Parcelable {
}
/**
- * Fills the bitmap's pixels with the specified {@link Color}.
+ * Fills the bitmap's pixels with the specified {@code ColorLong}.
*
+ * @param color The color to fill as packed by the {@link Color} class.
* @throws IllegalStateException if the bitmap is not mutable.
- * @throws IllegalArgumentException if the color space encoded in the long
- * is invalid or unknown.
+ * @throws IllegalArgumentException if the color space encoded in the
+ * {@code ColorLong} is invalid or unknown.
*
*/
- public void eraseColor(@ColorLong long c) {
+ public void eraseColor(@ColorLong long color) {
checkRecycled("Can't erase a recycled bitmap");
if (!isMutable()) {
throw new IllegalStateException("cannot erase immutable bitmaps");
}
- ColorSpace cs = Color.colorSpace(c);
- nativeErase(mNativePtr, cs.getNativeInstance(), c);
+ ColorSpace cs = Color.colorSpace(color);
+ nativeErase(mNativePtr, cs.getNativeInstance(), color);
}
/**
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 7b3f3da111d5..df64204d8647 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1683,8 +1683,9 @@ public class Canvas extends BaseCanvas {
* Fill the entire canvas' bitmap (restricted to the current clip) with the specified color,
* using srcover porterduff mode.
*
- * @param color the color to draw onto the canvas
- * @throws IllegalArgumentException if the color space encoded in the long
+ * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color}
+ * class for details about {@code ColorLong}s.
+ * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong}
* is invalid or unknown.
*/
public void drawColor(@ColorLong long color) {
@@ -1695,7 +1696,7 @@ public class Canvas extends BaseCanvas {
* Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and
* porter-duff xfermode.
*
- * @param color the color to draw with
+ * @param color the color to draw onto the canvas
* @param mode the porter-duff mode to apply to the color
*
* @deprecated use {@link #drawColor(int, BlendMode)} instead
@@ -1709,7 +1710,7 @@ public class Canvas extends BaseCanvas {
* Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and
* blendmode.
*
- * @param color the color to draw with
+ * @param color the color to draw onto the canvas
* @param mode the blendmode to apply to the color
*/
public void drawColor(@ColorInt int color, @NonNull BlendMode mode) {
@@ -1720,9 +1721,10 @@ public class Canvas extends BaseCanvas {
* Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and
* blendmode.
*
- * @param color the color to draw with
+ * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color}
+ * class for details about {@code ColorLong}s.
* @param mode the blendmode to apply to the color
- * @throws IllegalArgumentException if the color space encoded in the long
+ * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong}
* is invalid or unknown.
*/
public void drawColor(@ColorLong long color, @NonNull BlendMode mode) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index c48546103a6f..db5f06524c18 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1029,9 +1029,8 @@ public class Paint {
* premultiplied, meaning that alpha can be any value, regardless of the
* values of r,g,b. See the {@link Color} class for more details.
*
- * @see Color for APIs that help manipulate a color long.
- *
- * @return the paint's color (and alpha).
+ * @return the paint's color, alpha, and {@code ColorSpace} encoded as a
+ * {@code ColorLong}
*/
@ColorLong
public long getColorLong() {
@@ -1052,7 +1051,7 @@ public class Paint {
}
/**
- * Set the paint's color with a {@link ColorLong}. Note that the color is
+ * Set the paint's color with a {@code ColorLong}. Note that the color is
* a long with an encoded {@link ColorSpace} as well as alpha and r,g,b.
* These values are not premultiplied, meaning that alpha can be any value,
* regardless of the values of r,g,b. See the {@link Color} class for more
@@ -1060,8 +1059,8 @@ public class Paint {
*
* @param color The new color (including alpha and {@link ColorSpace})
* to set in the paint.
- * @throws IllegalArgumentException if the color space encoded in the long
- * is invalid or unknown.
+ * @throws IllegalArgumentException if the color space encoded in the
+ * {@code ColorLong} is invalid or unknown.
*/
public void setColor(@ColorLong long color) {
ColorSpace cs = Color.colorSpace(color);
@@ -1491,8 +1490,8 @@ public class Paint {
* The alpha of the shadow will be the paint's alpha if the shadow color is
* opaque, or the alpha from the shadow color if not.
*
- * @throws IllegalArgumentException if the color space encoded in the long
- * is invalid or unknown.
+ * @throws IllegalArgumentException if the color space encoded in the
+ * {@code ColorLong} is invalid or unknown.
*/
public void setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor) {
ColorSpace cs = Color.colorSpace(shadowColor);
@@ -1559,8 +1558,11 @@ public class Paint {
/**
* Returns the color of the shadow layer.
+ *
+ * @return the shadow layer's color encoded as a {@link ColorLong}.
* @see #setShadowLayer(float,float,float,int)
* @see #setShadowLayer(float,float,float,long)
+ * @see Color
*/
public @ColorLong long getShadowLayerColorLong() {
return mShadowLayerColor;
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 9b4f2c1b51d5..ae7fe6c46f2f 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -284,9 +284,10 @@ public final class RenderNode {
private static final class CompositePositionUpdateListener implements PositionUpdateListener {
private final PositionUpdateListener[] mListeners;
+ private static final PositionUpdateListener[] sEmpty = new PositionUpdateListener[0];
CompositePositionUpdateListener(PositionUpdateListener... listeners) {
- mListeners = listeners;
+ mListeners = listeners != null ? listeners : sEmpty;
}
public CompositePositionUpdateListener with(PositionUpdateListener listener) {
diff --git a/media/java/android/media/IMediaRoute2Callback.aidl b/media/java/android/media/IMediaRoute2Callback.aidl
new file mode 100644
index 000000000000..f03c8ab444c4
--- /dev/null
+++ b/media/java/android/media/IMediaRoute2Callback.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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 android.media;
+
+/**
+ * @hide
+ */
+oneway interface IMediaRoute2Callback {
+ void onRouteSelected(int uid, String routeId);
+}
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
new file mode 100644
index 000000000000..b97dcc521a04
--- /dev/null
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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 android.media;
+
+import android.media.IMediaRoute2Callback;
+
+/**
+ * {@hide}
+ */
+oneway interface IMediaRoute2Provider {
+ void setCallback(IMediaRoute2Callback callback);
+ void selectRoute(int uid, String id);
+}
diff --git a/media/java/android/media/IMediaRouter2ManagerClient.aidl b/media/java/android/media/IMediaRouter2ManagerClient.aidl
new file mode 100644
index 000000000000..234551b37a10
--- /dev/null
+++ b/media/java/android/media/IMediaRouter2ManagerClient.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 android.media;
+
+/**
+ * {@hide}
+ */
+oneway interface IMediaRouter2ManagerClient {
+ void onRouteSelected(int uid, String routeId);
+ void onControlCategoriesChanged(int uid, in List<String> categories);
+}
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 3308fc929b03..59f1d0dcbed8 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -17,6 +17,7 @@
package android.media;
import android.media.IMediaRouterClient;
+import android.media.IMediaRouter2ManagerClient;
import android.media.MediaRouterClientState;
/**
@@ -29,8 +30,15 @@ interface IMediaRouterService {
MediaRouterClientState getState(IMediaRouterClient client);
boolean isPlaybackActive(IMediaRouterClient client);
+ void setControlCategories(IMediaRouterClient client, in List<String> categories);
void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan);
void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction);
+
+ void registerManagerAsUser(IMediaRouter2ManagerClient callback,
+ String packageName, int userId);
+ void unregisterManager(IMediaRouter2ManagerClient callback);
+ void setRemoteRoute(IMediaRouter2ManagerClient callback,
+ int uid, String routeId, boolean explicit);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
new file mode 100644
index 000000000000..04ddc3089b91
--- /dev/null
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -0,0 +1,108 @@
+/*
+ * 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 android.media;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class MediaRoute2ProviderService extends Service {
+ private static final String TAG = "MediaRouteProviderSrv";
+
+ public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
+
+ private final Handler mHandler;
+ private ProviderStub mStub;
+ private IMediaRoute2Callback mCallback;
+
+ public MediaRoute2ProviderService() {
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ if (mStub == null) {
+ mStub = new ProviderStub();
+ }
+ return mStub;
+ }
+ return null;
+ }
+
+ /**
+ * Called when selectRoute is called on a route of the provider.
+ *
+ * @param uid The target application uid
+ * @param routeId The id of the target route
+ */
+ public abstract void onSelect(int uid, String routeId);
+
+ /**
+ * Updates provider info from selected route and appliation.
+ *
+ * TODO: When provider descriptor is defined, this should update the descriptor correctly.
+ *
+ * @param uid
+ * @param routeId
+ */
+ public void updateProvider(int uid, String routeId) {
+ if (mCallback != null) {
+ try {
+ //TODO: After publishState() is fully implemented, delete this.
+ mCallback.onRouteSelected(uid, routeId);
+ } catch (RemoteException ex) {
+ Log.d(TAG, "Failed to update provider");
+ }
+ }
+ publishState();
+ }
+
+ void setCallback(IMediaRoute2Callback callback) {
+ mCallback = callback;
+ publishState();
+ }
+
+ void publishState() {
+ //TODO: Send provider descriptor to the MediaRouterService
+ }
+
+ final class ProviderStub extends IMediaRoute2Provider.Stub {
+ ProviderStub() { }
+
+ @Override
+ public void setCallback(IMediaRoute2Callback callback) {
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setCallback,
+ MediaRoute2ProviderService.this, callback));
+ }
+
+ @Override
+ public void selectRoute(int uid, String id) {
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelect,
+ MediaRoute2ProviderService.this, uid, id));
+ }
+ }
+}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 3444e9277949..5a89d8c82f3a 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -347,6 +347,17 @@ public class MediaRouter {
return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
}
+ void setControlCategories(List<String> categories) {
+ if (mClient != null) {
+ try {
+ mMediaRouterService.setControlCategories(mClient,
+ categories);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to set control categories.", ex);
+ }
+ }
+ }
+
private void updatePresentationDisplays(int changedDisplayId) {
final int count = mRoutes.size();
for (int i = 0; i < count; i++) {
@@ -919,6 +930,25 @@ public class MediaRouter {
return -1;
}
+ //TODO: Remove @hide when it is ready.
+ //TODO: Provide pre-defined categories for app developers.
+ /**
+ * Sets control categories of the client application.
+ * Control categories can be used to filter out media routes
+ * that don't correspond with the client application.
+ * The only routes that match any of the categories will be shown on other applications.
+ *
+ * @hide
+ * @param categories Categories to set
+ */
+ public void setControlCategories(@NonNull List<String> categories) {
+ if (categories == null) {
+ throw new IllegalArgumentException("Categories must not be null");
+ }
+ sStatic.setControlCategories(categories);
+ }
+
+
/**
* Select the specified route to use for output of the given media types.
* <p class="note">
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
new file mode 100644
index 000000000000..ac5958ea9aa1
--- /dev/null
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -0,0 +1,241 @@
+/*
+ * 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 android.media;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public class MediaRouter2Manager {
+ private static final String TAG = "MediaRouter2Manager";
+ private static final Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static MediaRouter2Manager sInstance;
+
+ final String mPackageName;
+
+ private Context mContext;
+ private Client mClient;
+ private final IMediaRouterService mMediaRouterService;
+ final Handler mHandler;
+
+ @GuardedBy("sLock")
+ final ArrayList<CallbackRecord> mCallbacks = new ArrayList<>();
+
+ /**
+ * Gets an instance of media router manager that controls media route of other apps.
+ * @param context
+ * @return
+ */
+ public static MediaRouter2Manager getInstance(@NonNull Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("context must not be null");
+ }
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new MediaRouter2Manager(context);
+ }
+ return sInstance;
+ }
+ }
+
+ private MediaRouter2Manager(Context context) {
+ mContext = context.getApplicationContext();
+ mMediaRouterService = IMediaRouterService.Stub.asInterface(
+ ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
+ mPackageName = mContext.getPackageName();
+ mHandler = new Handler(context.getMainLooper());
+ }
+
+ /**
+ * Registers a callback to listen route info.
+ *
+ * @param executor The executor that runs the callback.
+ * @param callback The callback to add.
+ */
+ public void addCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Callback callback) {
+
+ if (executor == null) {
+ throw new IllegalArgumentException("executor must not be null");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
+ }
+
+ synchronized (sLock) {
+ final int index = findCallbackRecord(callback);
+ if (index >= 0) {
+ Log.w(TAG, "Ignore adding the same callback twice.");
+ return;
+ }
+ if (mCallbacks.size() == 0) {
+ Client client = new Client();
+ try {
+ mMediaRouterService.registerManagerAsUser(client, mPackageName,
+ UserHandle.myUserId());
+ mClient = client;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to register media router manager.", ex);
+ }
+ }
+ mCallbacks.add(new CallbackRecord(executor, callback));
+ }
+ }
+
+ /**
+ * Removes the specified callback.
+ *
+ * @param callback The callback to remove.
+ */
+ public void removeCallback(@NonNull Callback callback) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
+ }
+
+ synchronized (sLock) {
+ final int index = findCallbackRecord(callback);
+ if (index < 0) {
+ Log.w(TAG, "Ignore removing unknown callback. " + callback);
+ return;
+ }
+ mCallbacks.remove(index);
+ if (mCallbacks.size() == 0 && mClient != null) {
+ try {
+ mMediaRouterService.unregisterManager(mClient);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to unregister media router manager", ex);
+ }
+ mClient = null;
+ }
+ }
+ }
+
+ private int findCallbackRecord(Callback callback) {
+ final int count = mCallbacks.size();
+ for (int i = 0; i < count; i++) {
+ if (mCallbacks.get(i).mCallback == callback) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Selects media route for the specified application uid.
+ *
+ * @param uid The uid of the application that should change it's media route.
+ * @param routeId The id of the route to select
+ */
+ public void selectRoute(int uid, String routeId) {
+ if (mClient != null) {
+ try {
+ mMediaRouterService.setRemoteRoute(mClient, uid, routeId, /* explicit= */true);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to select media route", ex);
+ }
+ }
+ }
+
+ /**
+ * Unselects media route for the specified application uid.
+ *
+ * @param uid The uid of the application that should stop routing.
+ */
+ public void unselectRoute(int uid) {
+ if (mClient != null) {
+ try {
+ mMediaRouterService.setRemoteRoute(mClient, uid, null, /* explicit= */ true);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to select media route", ex);
+ }
+ }
+ }
+
+ void notifyRouteSelected(int uid, String routeId) {
+ for (CallbackRecord record : mCallbacks) {
+ record.mExecutor.execute(() -> record.mCallback.onRouteSelected(uid, routeId));
+ }
+ }
+
+ void notifyControlCategoriesChanged(int uid, List<String> categories) {
+ for (CallbackRecord record : mCallbacks) {
+ record.mExecutor.execute(
+ () -> record.mCallback.onControlCategoriesChanged(uid, categories));
+ }
+ }
+
+ /**
+ * Interface for receiving events about media routing changes.
+ */
+ public abstract static class Callback {
+ /**
+ * Called when a route is selected for some application uid.
+ * @param uid
+ * @param routeId
+ */
+ public abstract void onRouteSelected(int uid, String routeId);
+
+ /**
+ * Called when the control categories of an application is changed.
+ * @param uid the uid of the app that changed control categories
+ * @param categories the changed categories
+ */
+ public abstract void onControlCategoriesChanged(int uid, List<String> categories);
+ }
+
+ final class CallbackRecord {
+ public final Executor mExecutor;
+ public final Callback mCallback;
+
+ CallbackRecord(Executor executor, Callback callback) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+ }
+
+ class Client extends IMediaRouter2ManagerClient.Stub {
+ @Override
+ public void onRouteSelected(int uid, String routeId) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyRouteSelected,
+ MediaRouter2Manager.this, uid, routeId));
+ }
+
+ @Override
+ public void onControlCategoriesChanged(int uid, List<String> categories) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyControlCategoriesChanged,
+ MediaRouter2Manager.this, uid, categories));
+ }
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestResultPrinter.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestResultPrinter.java
index 2492109abb96..ed2eebf88665 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestResultPrinter.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestResultPrinter.java
@@ -40,14 +40,14 @@ public class CameraTestResultPrinter {
private Instrumentation mInst = null;
private boolean mWriteToFile = true;
-
public CameraTestResultPrinter(Instrumentation instrumentation, boolean writeToFile) {
mInst = instrumentation;
mWriteToFile = writeToFile;
// Create a log directory if not exists.
File baseDir = new File(RESULT_DIR);
- if (!baseDir.exists() && !baseDir.mkdirs()) {
+ baseDir.mkdirs();
+ if (!baseDir.isDirectory()) {
throw new IllegalStateException("Couldn't create directory for logs: " + baseDir);
}
Log.v(TAG, String.format("Saving test results under: %s", baseDir.getAbsolutePath()));
diff --git a/media/tests/MediaRouteProvider/Android.bp b/media/tests/MediaRouteProvider/Android.bp
new file mode 100644
index 000000000000..da4282495ac2
--- /dev/null
+++ b/media/tests/MediaRouteProvider/Android.bp
@@ -0,0 +1,18 @@
+android_test {
+ name: "mediarouteprovider",
+
+ srcs: ["**/*.java"],
+
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+
+ static_libs: [
+ "android-support-test",
+ "mockito-target-minus-junit4",
+ ],
+
+ platform_apis: true,
+ certificate: "platform",
+} \ No newline at end of file
diff --git a/media/tests/MediaRouteProvider/AndroidManifest.xml b/media/tests/MediaRouteProvider/AndroidManifest.xml
new file mode 100644
index 000000000000..489a6214ecbd
--- /dev/null
+++ b/media/tests/MediaRouteProvider/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.mediarouteprovider.example">
+
+ <application android:label="@string/app_name">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".SampleMediaRoute2ProviderService"
+ android:label="@string/app_name"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.media.MediaRoute2ProviderService" />
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
diff --git a/media/tests/MediaRouteProvider/res/values/strings.xml b/media/tests/MediaRouteProvider/res/values/strings.xml
new file mode 100644
index 000000000000..bb970641ffda
--- /dev/null
+++ b/media/tests/MediaRouteProvider/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- name of the app [CHAR LIMIT=25]-->
+ <string name="app_name">SampleMediaRouteProvider</string>
+</resources> \ No newline at end of file
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
new file mode 100644
index 000000000000..22fbd85d6979
--- /dev/null
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -0,0 +1,33 @@
+/*
+ * 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.mediarouteprovider.example;
+
+import android.content.Intent;
+import android.media.MediaRoute2ProviderService;
+import android.os.IBinder;
+
+public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService {
+ @Override
+ public IBinder onBind(Intent intent) {
+ return super.onBind(intent);
+ }
+
+ @Override
+ public void onSelect(int uid, String routeId) {
+ updateProvider(uid, routeId);
+ }
+}
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
new file mode 100644
index 000000000000..611b25a2f128
--- /dev/null
+++ b/media/tests/MediaRouter/Android.bp
@@ -0,0 +1,18 @@
+android_test {
+ name: "mediaroutertest",
+
+ srcs: ["**/*.java"],
+
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+
+ static_libs: [
+ "android-support-test",
+ "mockito-target-minus-junit4",
+ ],
+
+ platform_apis: true,
+ certificate: "platform",
+} \ No newline at end of file
diff --git a/media/tests/MediaRouter/AndroidManifest.xml b/media/tests/MediaRouter/AndroidManifest.xml
new file mode 100644
index 000000000000..a34a264e1247
--- /dev/null
+++ b/media/tests/MediaRouter/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.mediaroutertest">
+
+ <uses-permission android:name="android.permission.CONTROL_MEDIA_ROUTE" />
+
+ <application android:label="@string/app_name">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.mediaroutertest"
+ android:label="MediaRouter Tests"/>
+</manifest>
diff --git a/media/tests/MediaRouter/AndroidTest.xml b/media/tests/MediaRouter/AndroidTest.xml
new file mode 100644
index 000000000000..1301062db496
--- /dev/null
+++ b/media/tests/MediaRouter/AndroidTest.xml
@@ -0,0 +1,16 @@
+<configuration description="Runs sample instrumentation test.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="mediaroutertest.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="MediaRouterTest"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.mediaroutertest"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/media/tests/MediaRouter/res/values/strings.xml b/media/tests/MediaRouter/res/values/strings.xml
new file mode 100644
index 000000000000..07370207a3c9
--- /dev/null
+++ b/media/tests/MediaRouter/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- name of the app [CHAR LIMIT=25]-->
+ <string name="app_name">mediaRouterTest</string>
+</resources> \ No newline at end of file
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
new file mode 100644
index 000000000000..a4bde6592516
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.mediaroutertest;
+
+import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.media.MediaRouter;
+import android.media.MediaRouter2Manager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MediaRouterManagerTest {
+ private static final String TAG = "MediaRouterManagerTest";
+
+ private static final int TARGET_UID = 109992;
+ private static final String ROUTE_1 = "MediaRoute1";
+
+ private static final int AWAIT_MS = 1000;
+ private static final int TIMEOUT_MS = 1000;
+
+ private Context mContext;
+ private MediaRouter2Manager mManager;
+ private MediaRouter mRouter;
+ private Executor mExecutor;
+
+ private static final List<String> TEST_CONTROL_CATEGORIES = new ArrayList();
+ private static final String CONTROL_CATEGORY_1 = "android.media.mediarouter.MEDIA1";
+ private static final String CONTROL_CATEGORY_2 = "android.media.mediarouter.MEDIA2";
+ static {
+ TEST_CONTROL_CATEGORIES.add(CONTROL_CATEGORY_1);
+ TEST_CONTROL_CATEGORIES.add(CONTROL_CATEGORY_2);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mManager = MediaRouter2Manager.getInstance(mContext);
+ mRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ mExecutor = new ThreadPoolExecutor(
+ 1, 20, 3, TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>());
+ }
+
+ @Test
+ public void transferTest() throws Exception {
+ MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
+
+ mManager.addCallback(mExecutor, mockCallback);
+
+ verify(mockCallback, after(AWAIT_MS).never())
+ .onRouteSelected(eq(TARGET_UID), any(String.class));
+
+ mManager.selectRoute(TARGET_UID, ROUTE_1);
+ verify(mockCallback, timeout(TIMEOUT_MS)).onRouteSelected(TARGET_UID, ROUTE_1);
+
+ mManager.removeCallback(mockCallback);
+ }
+
+ @Test
+ public void controlCategoryTest() throws Exception {
+ final int uid = android.os.Process.myUid();
+
+ MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
+ mManager.addCallback(mExecutor, mockCallback);
+
+ verify(mockCallback, after(AWAIT_MS).never()).onControlCategoriesChanged(eq(uid),
+ any(List.class));
+
+ mRouter.setControlCategories(TEST_CONTROL_CATEGORIES);
+ verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+ .onControlCategoriesChanged(uid, TEST_CONTROL_CATEGORIES);
+
+ mManager.removeCallback(mockCallback);
+ }
+
+}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
index df2c57181904..e479e387b95a 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
@@ -49,6 +49,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
+import android.os.ParcelableException;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.image.DynamicSystemClient;
@@ -170,13 +171,13 @@ public class DynamicSystemInstallationService extends Service
@Override
public void onProgressUpdate(long installedSize) {
mInstalledSize = installedSize;
- postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED);
+ postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
}
@Override
- public void onResult(int result) {
+ public void onResult(int result, Throwable detail) {
if (result == RESULT_OK) {
- postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED);
+ postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null);
return;
}
@@ -185,15 +186,15 @@ public class DynamicSystemInstallationService extends Service
switch (result) {
case RESULT_ERROR_IO:
- postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_IO);
+ postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_IO, detail);
break;
case RESULT_ERROR_INVALID_URL:
- postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_INVALID_URL);
+ postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_INVALID_URL, detail);
break;
case RESULT_ERROR_EXCEPTION:
- postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_EXCEPTION);
+ postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_EXCEPTION, detail);
break;
}
}
@@ -201,7 +202,7 @@ public class DynamicSystemInstallationService extends Service
@Override
public void onCancelled() {
resetTaskAndStop();
- postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED);
+ postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null);
}
private void executeInstallCommand(Intent intent) {
@@ -266,7 +267,7 @@ public class DynamicSystemInstallationService extends Service
Toast.LENGTH_LONG).show();
resetTaskAndStop();
- postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED);
+ postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null);
mDynSystem.remove();
}
@@ -414,7 +415,7 @@ public class DynamicSystemInstallationService extends Service
return VerificationActivity.isVerified(url);
}
- private void postStatus(int status, int cause) {
+ private void postStatus(int status, int cause, Throwable detail) {
Log.d(TAG, "postStatus(): statusCode=" + status + ", causeCode=" + cause);
boolean notifyOnNotificationBar = true;
@@ -433,18 +434,24 @@ public class DynamicSystemInstallationService extends Service
for (int i = mClients.size() - 1; i >= 0; i--) {
try {
- notifyOneClient(mClients.get(i), status, cause);
+ notifyOneClient(mClients.get(i), status, cause, detail);
} catch (RemoteException e) {
mClients.remove(i);
}
}
}
- private void notifyOneClient(Messenger client, int status, int cause) throws RemoteException {
+ private void notifyOneClient(Messenger client, int status, int cause, Throwable detail)
+ throws RemoteException {
Bundle bundle = new Bundle();
bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mInstalledSize);
+ if (detail != null) {
+ bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL,
+ new ParcelableException(detail));
+ }
+
client.send(Message.obtain(null,
DynamicSystemClient.MSG_POST_STATUS, status, cause, bundle));
}
@@ -496,7 +503,7 @@ public class DynamicSystemInstallationService extends Service
int status = getStatus();
// tell just registered client my status, but do not specify cause
- notifyOneClient(client, status, CAUSE_NOT_SPECIFIED);
+ notifyOneClient(client, status, CAUSE_NOT_SPECIFIED, null);
mClients.add(client);
} catch (RemoteException e) {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java
index 052fc0a109b3..aee5de5efd5e 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java
@@ -31,7 +31,7 @@ import java.util.Locale;
import java.util.zip.GZIPInputStream;
-class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
+class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask";
@@ -43,7 +43,6 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
}
}
-
/** Not completed, including being cancelled */
static final int NO_RESULT = 0;
static final int RESULT_OK = 1;
@@ -53,7 +52,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
interface InstallStatusListener {
void onProgressUpdate(long installedSize);
- void onResult(int resultCode);
+ void onResult(int resultCode, Throwable detail);
void onCancelled();
}
@@ -84,7 +83,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
}
@Override
- protected Integer doInBackground(String... voids) {
+ protected Throwable doInBackground(String... voids) {
Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
try {
@@ -108,7 +107,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
if (isCancelled()) {
boolean aborted = mDynSystem.abort();
Log.d(TAG, "Called DynamicSystemManager.abort(), result = " + aborted);
- return RESULT_OK;
+ return null;
}
GsiProgress progress = mDynSystem.getInstallationProgress();
@@ -124,10 +123,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
if (mInstallationSession == null) {
- Log.e(TAG, "Failed to start installation with requested size: "
+ throw new IOException("Failed to start installation with requested size: "
+ (mSystemSize + mUserdataSize));
-
- return RESULT_ERROR_IO;
}
installedSize = mUserdataSize;
@@ -157,20 +154,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
}
}
- return RESULT_OK;
-
- } catch (IOException e) {
- e.printStackTrace();
- return RESULT_ERROR_IO;
-
- } catch (InvalidImageUrlException e) {
- e.printStackTrace();
- return RESULT_ERROR_INVALID_URL;
+ return null;
} catch (Exception e) {
e.printStackTrace();
- return RESULT_ERROR_EXCEPTION;
-
+ return e;
} finally {
close();
}
@@ -180,19 +168,24 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Integer> {
protected void onCancelled() {
Log.d(TAG, "onCancelled(), URL: " + mUrl);
- close();
-
mListener.onCancelled();
}
@Override
- protected void onPostExecute(Integer result) {
- Log.d(TAG, "onPostExecute(), URL: " + mUrl + ", result: " + result);
+ protected void onPostExecute(Throwable detail) {
+ if (detail == null) {
+ mResult = RESULT_OK;
+ } else if (detail instanceof IOException) {
+ mResult = RESULT_ERROR_IO;
+ } else if (detail instanceof InvalidImageUrlException) {
+ mResult = RESULT_ERROR_INVALID_URL;
+ } else {
+ mResult = RESULT_ERROR_EXCEPTION;
+ }
- close();
+ Log.d(TAG, "onPostExecute(), URL: " + mUrl + ", result: " + mResult);
- mResult = result;
- mListener.onResult(mResult);
+ mListener.onResult(mResult, detail);
}
@Override
diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml
index c1e74ef02623..9acfbafa3c0b 100644
--- a/packages/SystemUI/res/layout-land/volume_dialog.xml
+++ b/packages/SystemUI/res/layout-land/volume_dialog.xml
@@ -15,6 +15,7 @@
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:id="@+id/volume_dialog_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -116,16 +117,17 @@
android:clipToPadding="false"
android:translationZ="@dimen/volume_dialog_elevation"
android:background="@drawable/rounded_bg_full">
- <com.android.keyguard.AlphaOptimizedImageButton
+ <com.android.systemui.volume.CaptionsToggleImageButton
android:id="@+id/odi_captions_icon"
android:src="@drawable/ic_volume_odi_captions_disabled"
style="@style/VolumeButtons"
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:tint="@color/accent_tint_color_selector"
+ android:tint="@color/caption_tint_color_selector"
android:layout_gravity="center"
- android:soundEffectsEnabled="false" />
+ android:soundEffectsEnabled="false"
+ sysui:optedOut="false"/>
</FrameLayout>
<ViewStub
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index aca99e3cfae1..3aba6a08662e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2234,6 +2234,9 @@
<!-- Quick settings tile secondary label format combining roaming with the mobile data type. [CHAR LIMIT=NONE] -->
<string name="mobile_data_text_format"><xliff:g name="roaming_status" example="Roaming">%1$s</xliff:g> \u2014 <xliff:g name="mobile_data_type" example="LTE">%2$s</xliff:g></string>
+ <!-- Quick settings tile secondary label format combining carrier name with the mobile data tye. [CHAR LIMIT=NONE] -->
+ <string name="mobile_carrier_text_format"><xliff:g id="carrier_name" example="Test">%1$s</xliff:g>, <xliff:g id="mobile_data_type" example="LTE">%2$s</xliff:g></string>
+
<!-- Label for when wifi is off in QS detail panel [CHAR LIMIT=NONE] -->
<string name="wifi_is_off">Wi-Fi is off</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 294c725af481..8ad5c7b90882 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -39,6 +39,7 @@ import android.view.ViewGroup;
import androidx.annotation.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManager.DockEventListener;
@@ -72,6 +73,7 @@ public final class ClockManager {
private final Map<String, ClockPlugin> mClocks = new ArrayMap<>();
@Nullable private ClockPlugin mCurrentClock;
+ private final Context mContext;
private final ContentResolver mContentResolver;
private final SettingsWrapper mSettingsWrapper;
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
@@ -117,7 +119,7 @@ public final class ClockManager {
reload();
}
};
- @Nullable private final DockManager mDockManager;
+ @Nullable private DockManager mDockManager;
/**
* When docked, the DOCKED_CLOCK_FACE setting will be checked for the custom clock face
* to show.
@@ -132,18 +134,16 @@ public final class ClockManager {
@Inject
public ClockManager(Context context, InjectionInflationController injectionInflater,
- PluginManager pluginManager, @Nullable DockManager dockManager,
- SysuiColorExtractor colorExtractor) {
- this(context, injectionInflater, pluginManager, dockManager, colorExtractor,
+ PluginManager pluginManager, SysuiColorExtractor colorExtractor) {
+ this(context, injectionInflater, pluginManager, colorExtractor,
context.getContentResolver(), new SettingsWrapper(context.getContentResolver()));
}
ClockManager(Context context, InjectionInflationController injectionInflater,
- PluginManager pluginManager, @Nullable DockManager dockManager,
- SysuiColorExtractor colorExtractor, ContentResolver contentResolver,
- SettingsWrapper settingsWrapper) {
+ PluginManager pluginManager, SysuiColorExtractor colorExtractor,
+ ContentResolver contentResolver, SettingsWrapper settingsWrapper) {
+ mContext = context;
mPluginManager = pluginManager;
- mDockManager = dockManager;
mColorExtractor = colorExtractor;
mContentResolver = contentResolver;
mSettingsWrapper = settingsWrapper;
@@ -323,6 +323,9 @@ public final class ClockManager {
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.DOCKED_CLOCK_FACE),
false, mContentObserver);
+ if (mDockManager == null) {
+ mDockManager = SysUiServiceProvider.getComponent(mContext, DockManager.class);
+ }
if (mDockManager != null) {
mDockManager.addListener(mDockEventListener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 6bb4fb5ef94a..47ad0c17c414 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -31,7 +31,6 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.dock.DockManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -220,16 +219,6 @@ public class SystemUIFactory {
return SysUiServiceProvider.getComponent(context, StatusBar.class);
}
- /**
- * Provides DockManager.
- */
- @Singleton
- @Provides
- @Nullable
- public DockManager providesDockManager(Context context) {
- return SysUiServiceProvider.getComponent(context, DockManager.class);
- }
-
@Module
protected static class ContextHolder {
private Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 7a68be494cf9..979d226bf7e4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -84,7 +84,6 @@ public class BubbleView extends FrameLayout {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- updateViews();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index c587a39f49e3..db79e4d72642 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -25,11 +25,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -192,8 +188,10 @@ public class CellularTile extends QSTileImpl<SignalState> {
state.secondaryLabel = r.getString(R.string.status_bar_airplane);
} else if (mobileDataEnabled) {
state.state = Tile.STATE_ACTIVE;
- state.secondaryLabel = appendMobileDataType(getMobileDataSubscriptionName(cb),
- cb.dataContentDescription);
+ state.secondaryLabel = appendMobileDataType(
+ // Only show carrier name if there are more than 1 subscription
+ cb.multipleSubs ? cb.dataSubscriptionName : "",
+ getMobileDataContentName(cb));
} else {
state.state = Tile.STATE_INACTIVE;
state.secondaryLabel = r.getString(R.string.cell_data_off);
@@ -216,24 +214,22 @@ public class CellularTile extends QSTileImpl<SignalState> {
if (TextUtils.isEmpty(dataType)) {
return current;
}
- SpannableString type = new SpannableString(dataType);
- SpannableStringBuilder builder = new SpannableStringBuilder(current);
- builder.append(" ");
- builder.append(type, new TextAppearanceSpan(mContext, R.style.TextAppearance_RATBadge),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- return builder;
+ if (TextUtils.isEmpty(current)) {
+ return dataType;
+ }
+ return mContext.getString(R.string.mobile_carrier_text_format, current, dataType);
}
- private CharSequence getMobileDataSubscriptionName(CallbackInfo cb) {
- if (cb.roaming && !TextUtils.isEmpty(cb.dataSubscriptionName)) {
+ private CharSequence getMobileDataContentName(CallbackInfo cb) {
+ if (cb.roaming && !TextUtils.isEmpty(cb.dataContentDescription)) {
String roaming = mContext.getString(R.string.data_connection_roaming);
- String dataDescription = cb.dataSubscriptionName.toString();
+ String dataDescription = cb.dataContentDescription.toString();
return mContext.getString(R.string.mobile_data_text_format, roaming, dataDescription);
}
if (cb.roaming) {
return mContext.getString(R.string.data_connection_roaming);
}
- return cb.dataSubscriptionName;
+ return cb.dataContentDescription;
}
@Override
@@ -254,6 +250,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
boolean activityOut;
boolean noSim;
boolean roaming;
+ boolean multipleSubs;
}
private final class CellSignalCallback implements SignalCallback {
@@ -272,6 +269,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
mInfo.activityIn = activityIn;
mInfo.activityOut = activityOut;
mInfo.roaming = roaming;
+ mInfo.multipleSubs = mController.getNumberSubscriptions() > 1;
refreshState(mInfo);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index 4c7fdb0a6a7a..48974649191a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -108,7 +108,7 @@ public class NavigationBarEdgePanel extends View {
public static NavigationBarEdgePanel create(@NonNull Context context, int width, int height,
int gravity) {
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index f809b62c2b24..bfbe886eed98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -346,8 +346,11 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
post(() -> {
// When the ime changes visibility, resize the edge panels to not cover the ime
final int width = mPrototypeController.getEdgeSensitivityWidth();
- final int height = mContext.getDisplay().getHeight() - imeHeight
- - getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
+ int height = mContext.getDisplay().getHeight() - imeHeight;
+ if (!imeVisible) {
+ // Hide the navigation bar area at the bottom for gestures
+ height -= getResources().getDimensionPixelOffset(R.dimen.navigation_bar_height);
+ }
if (mLeftEdgePanel != null) {
mLeftEdgePanel.setDimensions(width, height);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 5bd394fb7187..c5996a1e1b00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -470,10 +470,16 @@ public class MobileSignalController extends SignalController<
mNetworkController.recalculateEmergency();
}
// Fill in the network name if we think we have it.
- if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
+ if (mCurrentState.networkName.equals(mNetworkNameDefault) && mServiceState != null
&& !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
}
+ // If this is the data subscription, update the currentState data name
+ if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null
+ && mCurrentState.dataSim
+ && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) {
+ mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort();
+ }
notifyListenersIfNecessary();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 51fef7d73993..71db618d6076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -37,6 +37,7 @@ public interface NetworkController extends CallbackController<SignalCallback>, D
DataUsageController getMobileDataController();
DataSaverController getDataSaverController();
String getMobileDataNetworkName();
+ int getNumberSubscriptions();
boolean hasVoiceCallingFeature();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index ef39912b6578..d01430a97783 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -376,6 +376,11 @@ public class NetworkControllerImpl extends BroadcastReceiver
return controller != null ? controller.getState().networkNameData : "";
}
+ @Override
+ public int getNumberSubscriptions() {
+ return mMobileSignalControllers.size();
+ }
+
public boolean isEmergencyOnly() {
if (mMobileSignalControllers.size() == 0) {
// When there are no active subscriptions, determine emengency state from last
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index 36265d485e2c..46b1833c2d6c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -67,8 +67,10 @@ public final class ClockManagerTest extends SysuiTestCase {
when(mMockInjectionInflationController.injectable(any())).thenReturn(inflater);
mFakeDockManager = new DockManagerFake();
+ getContext().putComponent(DockManager.class, mFakeDockManager);
+
mClockManager = new ClockManager(getContext(), mMockInjectionInflationController,
- mMockPluginManager, mFakeDockManager, mMockColorExtractor, mMockContentResolver,
+ mMockPluginManager, mMockColorExtractor, mMockContentResolver,
mMockSettingsWrapper);
mClockManager.addOnClockChangedListener(mMockListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 5cafc028d379..4fe18b486b9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -448,7 +448,12 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
}
}
- protected void assertNetworkNameEquals(String expected) {
+ protected void assertNetworkNameEquals(String expected) {
assertEquals("Network name", expected, mMobileSignalController.getState().networkName);
- }
+ }
+
+ protected void assertDataNetworkNameEquals(String expected) {
+ assertEquals("Data network name", expected, mNetworkController.getMobileDataNetworkName());
+ }
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 68323c912fdb..cd0a04411ee1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -285,6 +285,15 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
testDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT, true, true);
}
+ @Test
+ public void testUpdateDataNetworkName() {
+ setupDefaultSignal();
+ String newDataName = "TestDataName";
+ when(mServiceState.getDataOperatorAlphaShort()).thenReturn(newDataName);
+ updateServiceState();
+ assertDataNetworkNameEquals(newDataName);
+ }
+
private void testDataActivity(int direction, boolean in, boolean out) {
updateDataActivity(direction);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index bcbba8b163af..ac6544e129b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -20,6 +20,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.content.Intent;
import android.net.ConnectivityManager;
@@ -55,7 +56,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
@Test
public void testNoIconWithoutMobile() {
// Turn off mobile network support.
- Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
+ when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
// Create a new NetworkController as this is currently handled in constructor.
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
mConfig, Looper.getMainLooper(), mCallbackHandler,
@@ -117,7 +118,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
@Test
public void testNoSimlessIconWithoutMobile() {
// Turn off mobile network support.
- Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
+ when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
// Create a new NetworkController as this is currently handled in constructor.
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
mConfig, Looper.getMainLooper(), mCallbackHandler,
@@ -253,14 +254,14 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
// Generate a list of subscriptions we will tell the NetworkController to use.
SubscriptionInfo mockSubInfo = Mockito.mock(SubscriptionInfo.class);
- Mockito.when(mockSubInfo.getSubscriptionId()).thenReturn(testSubscriptions[i]);
+ when(mockSubInfo.getSubscriptionId()).thenReturn(testSubscriptions[i]);
subscriptions.add(mockSubInfo);
}
assertTrue(mNetworkController.hasCorrectMobileControllers(subscriptions));
// Add a subscription that the NetworkController doesn't know about.
SubscriptionInfo mockSubInfo = Mockito.mock(SubscriptionInfo.class);
- Mockito.when(mockSubInfo.getSubscriptionId()).thenReturn(notTestSubscription);
+ when(mockSubInfo.getSubscriptionId()).thenReturn(notTestSubscription);
subscriptions.add(mockSubInfo);
assertFalse(mNetworkController.hasCorrectMobileControllers(subscriptions));
}
@@ -290,8 +291,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
if (i != indexToSkipSubscription) {
// Generate a list of subscriptions we will tell the NetworkController to use.
SubscriptionInfo mockSubInfo = Mockito.mock(SubscriptionInfo.class);
- Mockito.when(mockSubInfo.getSubscriptionId()).thenReturn(testSubscriptions[i]);
- Mockito.when(mockSubInfo.getSimSlotIndex()).thenReturn(testSubscriptions[i]);
+ when(mockSubInfo.getSubscriptionId()).thenReturn(testSubscriptions[i]);
+ when(mockSubInfo.getSimSlotIndex()).thenReturn(testSubscriptions[i]);
subscriptions.add(mockSubInfo);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
index 5385f6d08bc5..d5ba381bfcac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
@@ -93,4 +93,9 @@ public class FakeNetworkController extends BaseLeakChecker<SignalCallback>
public String getMobileDataNetworkName() {
return "";
}
+
+ @Override
+ public int getNumberSubscriptions() {
+ return 0;
+ }
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 95abd05ff011..f629cf6c82b0 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7149,6 +7149,13 @@ message MetricsEvent {
// Settings > Display > Theme
DARK_UI_SETTINGS = 1698;
+
+ // Settings > global bubble settings
+ BUBBLE_SETTINGS = 1699;
+
+ // Settings > app > bubble settings
+ APP_BUBBLE_SETTINGS = 1700;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 47cd917bf84e..904817e1763e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -777,6 +777,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
token, mGlobalWindowTokens, mGlobalInteractionConnections);
if (removedWindowId >= 0) {
+ mSecurityPolicy.onAccessibilityClientRemovedLocked(removedWindowId);
if (DEBUG) {
Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
+ " with windowId: " + removedWindowId + " and token: " + window.asBinder());
@@ -790,6 +791,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
removeAccessibilityInteractionConnectionInternalLocked(
token, userState.mWindowTokens, userState.mInteractionConnections);
if (removedWindowIdForUser >= 0) {
+ mSecurityPolicy.onAccessibilityClientRemovedLocked(removedWindowIdForUser);
if (DEBUG) {
Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
+ " with windowId: " + removedWindowIdForUser + " and userId:"
@@ -1332,6 +1334,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState.mWindowTokens.remove(windowId);
userState.mInteractionConnections.remove(windowId);
}
+ mSecurityPolicy.onAccessibilityClientRemovedLocked(windowId);
if (DEBUG) {
Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
}
@@ -3266,6 +3269,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mWindows = null;
}
+ /**
+ * A callback when accessibility interaction client is removed.
+ */
+ public void onAccessibilityClientRemovedLocked(int windowId) {
+ // Active window cannot update immediately, if windows callback is unregistered.
+ // Update active window to invalid, when its a11y interaction client is removed.
+ if (mWindowsForAccessibilityCallback == null && windowId >= 0
+ && mActiveWindowId == windowId) {
+ mActiveWindowId = INVALID_WINDOW_ID;
+ }
+ }
+
public void updateWindowsLocked(List<WindowInfo> windows) {
if (mWindows == null) {
mWindows = new ArrayList<>();
diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
index 21088e442212..19226be2e1ca 100644
--- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
+++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
@@ -47,7 +47,8 @@ public class RemoteAppPredictionService extends
RemoteAppPredictionServiceCallbacks callback, boolean bindInstantServiceAllowed,
boolean verbose) {
super(context, serviceInterface, componentName, userId, callback,
- context.getMainThreadHandler(), bindInstantServiceAllowed,
+ context.getMainThreadHandler(),
+ bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0,
verbose, /* initialCapacity= */ 1);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 87a265cf38d4..7020e7ea6965 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -198,6 +198,11 @@ public final class AutofillManagerService
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
+ mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(),
+ com.android.internal.R.string.config_defaultAugmentedAutofillService);
+ mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
+ (u, s) -> getServiceForUserLocked(u).updateRemoteAugmentedAutofillService());
+
if (mSupportedSmartSuggestionModes != AutofillManager.FLAG_SMART_SUGGESTION_OFF) {
// Must eager load the services so they bind to the augmented autofill service
final UserManager um = getContext().getSystemService(UserManager.class);
@@ -207,11 +212,6 @@ public final class AutofillManagerService
getServiceForUserLocked(userId);
}
}
-
- mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(),
- com.android.internal.R.string.config_defaultAugmentedAutofillService);
- mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
- (u, s) -> getServiceForUserLocked(u).updateRemoteAugmentedAutofillService());
}
@Override // from AbstractMasterSystemService
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index ff284dcabfd0..d3cd48a81eab 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -247,7 +247,8 @@ final class AutofillManagerServiceImpl
if (isEnabledLocked()) return FLAG_ADD_CLIENT_ENABLED;
// Check if it's enabled for augmented autofill
- if (isSetupCompletedLocked() && isWhitelistedForAugmentedAutofillLocked(componentName)) {
+ if (isAugmentedAutofillServiceAvailableLocked()
+ && isWhitelistedForAugmentedAutofillLocked(componentName)) {
return FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
}
@@ -1150,12 +1151,30 @@ final class AutofillManagerServiceImpl
mRemoteAugmentedAutofillServiceInfo = null;
}
- if (isEnabledLocked()) {
+ final boolean available = isAugmentedAutofillServiceAvailableLocked();
+ if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): " + available);
+
+ if (available) {
mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
}
}
}
+ private boolean isAugmentedAutofillServiceAvailableLocked() {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "isAugmentedAutofillService(): "
+ + "setupCompleted=" + isSetupCompletedLocked()
+ + ", disabled=" + isDisabledByUserRestrictionsLocked()
+ + ", augmentedService="
+ + mMaster.mAugmentedAutofillResolver.getServiceName(mUserId));
+ }
+ if (!isSetupCompletedLocked() || isDisabledByUserRestrictionsLocked()
+ || mMaster.mAugmentedAutofillResolver.getServiceName(mUserId) == null) {
+ return false;
+ }
+ return true;
+ }
+
/**
* Sets which packages and activities can trigger augmented autofill.
*
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 3c17ac35f624..adf582925489 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -58,7 +58,8 @@ final class RemoteAugmentedAutofillService
boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs,
int requestTimeoutMs) {
super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
- context.getMainThreadHandler(), bindInstantServiceAllowed, verbose);
+ context.getMainThreadHandler(),
+ bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, verbose);
mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
mRequestTimeoutMs = requestTimeoutMs;
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index b8a7d44a4d10..0ce6c87f1f28 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -64,7 +64,8 @@ final class RemoteFillService
RemoteFillService(Context context, ComponentName componentName, int userId,
FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) {
super(context, AutofillService.SERVICE_INTERFACE, componentName, userId, callbacks,
- context.getMainThreadHandler(), bindInstantServiceAllowed, sVerbose);
+ context.getMainThreadHandler(), Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS
+ | (bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0), sVerbose);
mCallbacks = callbacks;
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index df9ccbc499ba..0afe252d96bd 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -47,7 +47,8 @@ final class RemoteContentCaptureService
ContentCapturePerUserService perUserService, boolean bindInstantServiceAllowed,
boolean verbose, int idleUnbindTimeoutMs) {
super(context, serviceInterface, serviceComponentName, userId, perUserService,
- context.getMainThreadHandler(), bindInstantServiceAllowed, verbose,
+ context.getMainThreadHandler(),
+ bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, verbose,
/* initialCapacity= */ 2);
mPerUserService = perUserService;
mServerCallback = callback.asBinder();
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
index 442972a1e477..4b36352bac51 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java
@@ -47,7 +47,8 @@ public class RemoteContentSuggestionsService extends
int userId, Callbacks callbacks,
boolean bindInstantServiceAllowed, boolean verbose) {
super(context, ContentSuggestionsService.SERVICE_INTERFACE, serviceName, userId, callbacks,
- context.getMainThreadHandler(), bindInstantServiceAllowed, verbose,
+ context.getMainThreadHandler(),
+ bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, verbose,
/* initialCapacity= */ 1);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 98311fcec536..5b9c1f8d6f24 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2881,6 +2881,32 @@ class StorageManagerService extends IStorageManager.Stub
mVold.commitChanges();
}
+ /**
+ * Check if we should be mounting with checkpointing or are checkpointing now
+ */
+ @Override
+ public boolean needsCheckpoint() throws RemoteException {
+ // Only the system process is permitted to commit checkpoints
+ if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ throw new SecurityException("no permission to commit checkpoint changes");
+ }
+
+ return mVold.needsCheckpoint();
+ }
+
+ /**
+ * Abort the current set of changes and either try again, or abort entirely
+ */
+ @Override
+ public void abortChanges(String message, boolean retry) throws RemoteException {
+ // Only the system process is permitted to abort checkpoints
+ if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ throw new SecurityException("no permission to commit checkpoint changes");
+ }
+
+ mVold.abortChanges(message, retry);
+ }
+
@Override
public String getPassword() throws RemoteException {
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
@@ -3871,6 +3897,7 @@ class StorageManagerService extends IStorageManager.Stub
case "com.jrtstudio.AnotherMusicPlayer": // b/129084562
case "ak.alizandro.smartaudiobookplayer": // b/129084042
case "com.campmobile.snow": // b/128803870
+ case "com.qnap.qfile": // b/126374406
return Zygote.MOUNT_EXTERNAL_LEGACY;
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 26896f54f932..8b10267f32ff 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -73,10 +73,12 @@ import com.android.server.am.BatteryStatsService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.OptionalInt;
/**
* Since phone process can be restarted, this class provides a centralized place
@@ -1159,17 +1161,28 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
@Override
public void notifyCarrierNetworkChange(boolean active) {
- enforceNotifyPermissionOrCarrierPrivilege("notifyCarrierNetworkChange()");
+ // only CarrierService with carrier privilege rule should have the permission.
+ int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ try {
+ subId = Arrays.stream(SubscriptionManager.from(mContext)
+ .getActiveSubscriptionIdList())
+ .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(i))
+ .findFirst().getAsInt();
+ } catch (NoSuchElementException ex) {
+ log("notifyCarrierNetworkChange without carrier privilege");
+ }
+ int phoneId = SubscriptionManager.getPhoneId(subId);
if (VDBG) {
- log("notifyCarrierNetworkChange: active=" + active);
+ log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId);
}
synchronized (mRecords) {
mCarrierNetworkChangeState = active;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE)) {
+ PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCarrierNetworkChange(active);
} catch (RemoteException ex) {
@@ -1885,7 +1898,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mDataConnectionState=" + mDataConnectionState[i]);
pw.println("mCellLocation=" + mCellLocation[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
- pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i).toString());
+ pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
pw.decreaseIndent();
}
pw.println("mCallNetworkType=" + mCallNetworkType);
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 712edcced5da..da665906a70d 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -58,7 +58,6 @@ class AccountsDb implements AutoCloseable {
private static final int CE_DATABASE_VERSION = 10;
private static final int DE_DATABASE_VERSION = 3; // Added visibility support in O
-
static final String TABLE_ACCOUNTS = "accounts";
private static final String ACCOUNTS_ID = "_id";
private static final String ACCOUNTS_NAME = "name";
@@ -267,6 +266,13 @@ class AccountsDb implements AutoCloseable {
}
@Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.e(TAG, "onDowngrade: recreate accounts CE table");
+ resetDatabase(db);
+ onCreate(db);
+ }
+
+ @Override
public void onOpen(SQLiteDatabase db) {
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "opened database " + CE_DATABASE_NAME);
}
@@ -616,6 +622,13 @@ class AccountsDb implements AutoCloseable {
}
}
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.e(TAG, "onDowngrade: recreate accounts DE table");
+ resetDatabase(db);
+ onCreate(db);
+ }
+
public SQLiteDatabase getReadableDatabaseUserIsUnlocked() {
if(!mCeAttached) {
Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId
@@ -1399,4 +1412,26 @@ class AccountsDb implements AutoCloseable {
return new AccountsDb(deDatabaseHelper, context, preNDatabaseFile);
}
+ /**
+ * Removes all tables and triggers created by AccountManager.
+ */
+ private static void resetDatabase(SQLiteDatabase db) {
+ try (Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type ='table'", null)) {
+ while (c.moveToNext()) {
+ String name = c.getString(0);
+ // Skip tables managed by SQLiteDatabase
+ if ("android_metadata".equals(name) || "sqlite_sequence".equals(name)) {
+ continue;
+ }
+ db.execSQL("DROP TABLE IF EXISTS " + name);
+ }
+ }
+
+ try (Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type ='trigger'", null)) {
+ while (c.moveToNext()) {
+ String name = c.getString(0);
+ db.execSQL("DROP TRIGGER IF EXISTS " + name);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index e357ce8ce929..1878d00ba9f9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1805,7 +1805,7 @@ public final class ActiveServices {
|| (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP
&& (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0),
b.client);
- mAm.updateOomAdjLocked(s.app, true);
+ mAm.updateOomAdjLocked();
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
diff --git a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
index ac07e9d6b0b7..c52921ef344b 100644
--- a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
@@ -113,6 +113,13 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
}
/**
+ * Gets whether the service is disabled by {@link UserManager} restrictions.
+ */
+ protected final boolean isDisabledByUserRestrictionsLocked() {
+ return mDisabled;
+ }
+
+ /**
* Updates the state of this service.
*
* <p>Typically called when the service {@link Settings} property or {@link UserManager}
@@ -136,7 +143,9 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
+ ", disabled=" + disabled + ", mDisabled=" + mDisabled);
}
- mSetupComplete = isSetupCompletedLocked();
+ final String setupComplete = Settings.Secure.getStringForUser(
+ getContext().getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, mUserId);
+ mSetupComplete = "1".equals(setupComplete);
mDisabled = disabled;
updateServiceInfoLocked();
@@ -235,6 +244,15 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
}
/**
+ * Gets the {@link ServiceInfo} of the remote service this service binds to, or {@code null}
+ * if the service is disabled.
+ */
+ @Nullable
+ public final ServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ /**
* Gets the {@link ComponentName} of the remote service this service binds to, or {@code null}
* if the service is disabled.
*/
@@ -311,9 +329,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
* Gets whether the device already finished setup.
*/
protected final boolean isSetupCompletedLocked() {
- final String setupComplete = Settings.Secure.getStringForUser(
- getContext().getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, mUserId);
- return "1".equals(setupComplete);
+ return mSetupComplete;
}
/**
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
new file mode 100644
index 000000000000..d284c6091f73
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -0,0 +1,341 @@
+/*
+ * 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.server.media;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.IMediaRoute2Callback;
+import android.media.IMediaRoute2Provider;
+import android.media.MediaRoute2ProviderService;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+
+/**
+ * Maintains a connection to a particular media route provider service.
+ */
+final class MediaRoute2ProviderProxy implements ServiceConnection {
+ private static final String TAG = "MediaRoute2ProviderProxy";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final Context mContext;
+ private final ComponentName mComponentName;
+ private final int mUserId;
+ private final Handler mHandler;
+
+ private Callback mCallback;
+
+ // Selected Route info
+ public int mSelectedUid;
+ public String mSelectedRouteId;
+
+ // Connection state
+ private boolean mRunning;
+ private boolean mBound;
+ private Connection mActiveConnection;
+ private boolean mConnectionReady;
+
+ MediaRoute2ProviderProxy(Context context, ComponentName componentName, int userId) {
+ mContext = context;
+ mComponentName = componentName;
+ mUserId = userId;
+ mHandler = new Handler();
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "Proxy");
+ pw.println(prefix + " mUserId=" + mUserId);
+ pw.println(prefix + " mRunning=" + mRunning);
+ pw.println(prefix + " mBound=" + mBound);
+ pw.println(prefix + " mActiveConnection=" + mActiveConnection);
+ pw.println(prefix + " mConnectionReady=" + mConnectionReady);
+ }
+
+ public void setCallback(Callback callback) {
+ mCallback = callback;
+ }
+
+ public void setSelectedRoute(int uid, String routeId) {
+ if (mConnectionReady) {
+ mActiveConnection.selectRoute(uid, routeId);
+ updateBinding();
+ }
+ }
+
+ public boolean hasComponentName(String packageName, String className) {
+ return mComponentName.getPackageName().equals(packageName)
+ && mComponentName.getClassName().equals(className);
+ }
+
+ public String getFlattenedComponentName() {
+ return mComponentName.flattenToShortString();
+ }
+
+ public void start() {
+ if (!mRunning) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Starting");
+ }
+
+ mRunning = true;
+ updateBinding();
+ }
+ }
+
+ public void stop() {
+ if (mRunning) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Stopping");
+ }
+
+ mRunning = false;
+ updateBinding();
+ }
+ }
+
+ public void rebindIfDisconnected() {
+ if (mActiveConnection == null && shouldBind()) {
+ unbind();
+ bind();
+ }
+ }
+
+ private void updateBinding() {
+ if (shouldBind()) {
+ bind();
+ } else {
+ unbind();
+ }
+ }
+
+ private boolean shouldBind() {
+ //TODO: binding could be delayed until it's necessary.
+ if (mRunning) {
+ return true;
+ }
+ return false;
+ }
+
+ private void bind() {
+ if (!mBound) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Binding");
+ }
+
+ Intent service = new Intent(MediaRoute2ProviderService.SERVICE_INTERFACE);
+ service.setComponent(mComponentName);
+ try {
+ mBound = mContext.bindServiceAsUser(service, this,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ new UserHandle(mUserId));
+ if (!mBound && DEBUG) {
+ Slog.d(TAG, this + ": Bind failed");
+ }
+ } catch (SecurityException ex) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Bind failed", ex);
+ }
+ }
+ }
+ }
+
+ private void unbind() {
+ if (mBound) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Unbinding");
+ }
+
+ mBound = false;
+ disconnect();
+ mContext.unbindService(this);
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Connected");
+ }
+
+ if (mBound) {
+ disconnect();
+
+ IMediaRoute2Provider provider = IMediaRoute2Provider.Stub.asInterface(service);
+ if (provider != null) {
+ Connection connection = new Connection(provider);
+ if (connection.register()) {
+ mActiveConnection = connection;
+ } else {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Registration failed");
+ }
+ }
+ } else {
+ Slog.e(TAG, this + ": Service returned invalid remote display provider binder");
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Service disconnected");
+ }
+ disconnect();
+ }
+
+ private void onConnectionReady(Connection connection) {
+ if (mActiveConnection == connection) {
+ mConnectionReady = true;
+ }
+ }
+
+ private void onConnectionDied(Connection connection) {
+ if (mActiveConnection == connection) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": Service connection died");
+ }
+ disconnect();
+ }
+ }
+
+ private void onRouteSelected(Connection connection, int uid, String routeId) {
+ mSelectedUid = uid;
+ mSelectedRouteId = routeId;
+
+ if (mActiveConnection == connection) {
+ if (DEBUG) {
+ Slog.d(TAG, this + ": State changed ");
+ }
+ mHandler.post(mStateChanged);
+ }
+ }
+
+ private void disconnect() {
+ if (mActiveConnection != null) {
+ mConnectionReady = false;
+ mActiveConnection.dispose();
+ mActiveConnection = null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Service connection " + mComponentName.flattenToShortString();
+ }
+
+ private final Runnable mStateChanged = new Runnable() {
+ @Override
+ public void run() {
+ if (mCallback != null) {
+ mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
+ }
+ }
+ };
+
+ public interface Callback {
+ void onProviderStateChanged(MediaRoute2ProviderProxy provider);
+ }
+
+ private final class Connection implements DeathRecipient {
+ private final IMediaRoute2Provider mProvider;
+ private final ProviderCallback mCallback;
+
+ Connection(IMediaRoute2Provider provider) {
+ mProvider = provider;
+ mCallback = new ProviderCallback(this);
+ }
+
+ public boolean register() {
+ try {
+ mProvider.asBinder().linkToDeath(this, 0);
+ mProvider.setCallback(mCallback);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onConnectionReady(Connection.this);
+ }
+ });
+ return true;
+ } catch (RemoteException ex) {
+ binderDied();
+ }
+ return false;
+ }
+
+ public void dispose() {
+ mProvider.asBinder().unlinkToDeath(this, 0);
+ mCallback.dispose();
+ }
+
+ public void selectRoute(int uid, String id) {
+ try {
+ mProvider.selectRoute(uid, id);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onConnectionDied(Connection.this);
+ }
+ });
+ }
+
+ void postRouteSelected(int uid, String routeId) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onRouteSelected(Connection.this, uid, routeId);
+ }
+ });
+ }
+ }
+
+ private static final class ProviderCallback extends IMediaRoute2Callback.Stub {
+ private final WeakReference<Connection> mConnectionRef;
+
+ ProviderCallback(Connection connection) {
+ mConnectionRef = new WeakReference<Connection>(connection);
+ }
+
+ public void dispose() {
+ mConnectionRef.clear();
+ }
+
+ @Override
+ public void onRouteSelected(int uid, String routeId) throws RemoteException {
+ Connection connection = mConnectionRef.get();
+ if (connection != null) {
+ connection.postRouteSelected(uid, routeId);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
new file mode 100644
index 000000000000..08d8c58f6f87
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
@@ -0,0 +1,176 @@
+/*
+ * 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.server.media;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.media.MediaRoute2ProviderService;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ */
+final class MediaRoute2ProviderWatcher {
+ private static final String TAG = "MediaRouteProvider"; // max. 23 chars
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final Context mContext;
+ private final Callback mCallback;
+ private final Handler mHandler;
+ private final int mUserId;
+ private final PackageManager mPackageManager;
+
+ private final ArrayList<MediaRoute2ProviderProxy> mProviders = new ArrayList<>();
+ private boolean mRunning;
+
+ MediaRoute2ProviderWatcher(Context context,
+ Callback callback, Handler handler, int userId) {
+ mContext = context;
+ mCallback = callback;
+ mHandler = handler;
+ mUserId = userId;
+ mPackageManager = context.getPackageManager();
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "Watcher");
+ pw.println(prefix + " mUserId=" + mUserId);
+ pw.println(prefix + " mRunning=" + mRunning);
+ pw.println(prefix + " mProviders.size()=" + mProviders.size());
+ }
+
+ public void start() {
+ if (!mRunning) {
+ mRunning = true;
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+ filter.addDataScheme("package");
+ mContext.registerReceiverAsUser(mScanPackagesReceiver,
+ new UserHandle(mUserId), filter, null, mHandler);
+
+ // Scan packages.
+ // Also has the side-effect of restarting providers if needed.
+ mHandler.post(mScanPackagesRunnable);
+ }
+ }
+
+ public void stop() {
+ if (mRunning) {
+ mRunning = false;
+
+ mContext.unregisterReceiver(mScanPackagesReceiver);
+ mHandler.removeCallbacks(mScanPackagesRunnable);
+
+ // Stop all providers.
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ mProviders.get(i).stop();
+ }
+ }
+ }
+
+ private void scanPackages() {
+ if (!mRunning) {
+ return;
+ }
+
+ // Add providers for all new services.
+ // Reorder the list so that providers left at the end will be the ones to remove.
+ int targetIndex = 0;
+ Intent intent = new Intent(MediaRoute2ProviderService.SERVICE_INTERFACE);
+ for (ResolveInfo resolveInfo : mPackageManager.queryIntentServicesAsUser(
+ intent, 0, mUserId)) {
+ ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+ if (serviceInfo != null) {
+ int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
+ if (sourceIndex < 0) {
+ MediaRoute2ProviderProxy provider =
+ new MediaRoute2ProviderProxy(mContext,
+ new ComponentName(serviceInfo.packageName, serviceInfo.name),
+ mUserId);
+ provider.start();
+ mProviders.add(targetIndex++, provider);
+ mCallback.addProvider(provider);
+ } else if (sourceIndex >= targetIndex) {
+ MediaRoute2ProviderProxy provider = mProviders.get(sourceIndex);
+ provider.start(); // restart the provider if needed
+ provider.rebindIfDisconnected();
+ Collections.swap(mProviders, sourceIndex, targetIndex++);
+ }
+ }
+ }
+
+ // Remove providers for missing services.
+ if (targetIndex < mProviders.size()) {
+ for (int i = mProviders.size() - 1; i >= targetIndex; i--) {
+ MediaRoute2ProviderProxy provider = mProviders.get(i);
+ mCallback.removeProvider(provider);
+ mProviders.remove(provider);
+ provider.stop();
+ }
+ }
+ }
+
+ private int findProvider(String packageName, String className) {
+ int count = mProviders.size();
+ for (int i = 0; i < count; i++) {
+ MediaRoute2ProviderProxy provider = mProviders.get(i);
+ if (provider.hasComponentName(packageName, className)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private final BroadcastReceiver mScanPackagesReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) {
+ Slog.d(TAG, "Received package manager broadcast: " + intent);
+ }
+ scanPackages();
+ }
+ };
+
+ private final Runnable mScanPackagesRunnable = new Runnable() {
+ @Override
+ public void run() {
+ scanPackages();
+ }
+ };
+
+ public interface Callback {
+ void addProvider(MediaRoute2ProviderProxy provider);
+ void removeProvider(MediaRoute2ProviderProxy provider);
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 3eb732157a44..f822e82ecdfc 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -16,14 +16,10 @@
package com.android.server.media;
-import com.android.internal.util.DumpUtils;
-import com.android.server.Watchdog;
-
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +30,7 @@ import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
import android.media.IAudioService;
+import android.media.IMediaRouter2ManagerClient;
import android.media.IMediaRouterClient;
import android.media.IMediaRouterService;
import android.media.MediaRouter;
@@ -53,10 +50,14 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.util.DumpUtils;
+import com.android.server.Watchdog;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -97,6 +98,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private final Object mLock = new Object();
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>();
+ private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>();
private int mCurrentUserId = -1;
private final IAudioService mAudioService;
private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
@@ -306,6 +308,22 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
+ public void setControlCategories(IMediaRouterClient client, List<String> categories) {
+ if (client == null) {
+ throw new IllegalArgumentException("client must not be null");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ setControlCategoriesLocked(client, categories);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // Binder call
+ @Override
public void setDiscoveryRequest(IMediaRouterClient client,
int routeTypes, boolean activeScan) {
if (client == null) {
@@ -404,6 +422,65 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
+ // Binder call
+ @Override
+ public void registerManagerAsUser(IMediaRouter2ManagerClient client,
+ String packageName, int userId) {
+ if (client == null) {
+ throw new IllegalArgumentException("client must not be null");
+ }
+ //TODO: should check permission
+ final boolean trusted = true;
+
+ final int uid = Binder.getCallingUid();
+ if (!validatePackageName(uid, packageName)) {
+ throw new SecurityException("packageName must match the calling uid");
+ }
+
+ final int pid = Binder.getCallingPid();
+ final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+ false /*allowAll*/, true /*requireFull*/, "registerManagerAsUser", packageName);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ registerManagerLocked(client, uid, pid, packageName, resolvedUserId, trusted);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // Binder call
+ @Override
+ public void unregisterManager(IMediaRouter2ManagerClient client) {
+ if (client == null) {
+ throw new IllegalArgumentException("client must not be null");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ unregisterManagerLocked(client, false);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // Binder call
+ @Override
+ public void setRemoteRoute(IMediaRouter2ManagerClient client,
+ int uid, String routeId, boolean explicit) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ setRemoteRouteLocked(client, uid, routeId, explicit);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
void restoreBluetoothA2dp() {
try {
boolean a2dpOn;
@@ -475,6 +552,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
+ void clientDied(ManagerRecord managerRecord) {
+ synchronized (mLock) {
+ unregisterManagerLocked(managerRecord.mClient, true);
+ }
+ }
+
private void registerClientLocked(IMediaRouterClient client,
int uid, int pid, String packageName, int userId, boolean trusted) {
final IBinder binder = client.asBinder();
@@ -522,6 +605,17 @@ public final class MediaRouterService extends IMediaRouterService.Stub
return null;
}
+ private void setControlCategoriesLocked(IMediaRouterClient client, List<String> categories) {
+ final IBinder binder = client.asBinder();
+ ClientRecord clientRecord = mAllClientRecords.get(binder);
+
+ if (clientRecord != null) {
+ clientRecord.mControlCategories = categories;
+ clientRecord.mUserRecord.mHandler.obtainMessage(
+ UserHandler.MSG_UPDATE_CLIENT_USAGE, clientRecord).sendToTarget();
+ }
+ }
+
private void setDiscoveryRequestLocked(IMediaRouterClient client,
int routeTypes, boolean activeScan) {
final IBinder binder = client.asBinder();
@@ -575,6 +669,63 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
+ private void registerManagerLocked(IMediaRouter2ManagerClient client,
+ int uid, int pid, String packageName, int userId, boolean trusted) {
+ final IBinder binder = client.asBinder();
+ ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+ if (managerRecord == null) {
+ boolean newUser = false;
+ UserRecord userRecord = mUserRecords.get(userId);
+ if (userRecord == null) {
+ userRecord = new UserRecord(userId);
+ newUser = true;
+ }
+ managerRecord = new ManagerRecord(userRecord, client, uid, pid, packageName, trusted);
+ try {
+ binder.linkToDeath(managerRecord, 0);
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Media router client died prematurely.", ex);
+ }
+
+ if (newUser) {
+ mUserRecords.put(userId, userRecord);
+ initializeUserLocked(userRecord);
+ }
+
+ userRecord.mManagerRecords.add(managerRecord);
+ mAllManagerRecords.put(binder, managerRecord);
+
+ // send client usage to manager
+ final int clientCount = userRecord.mClientRecords.size();
+ for (int i = 0; i < clientCount; i++) {
+ userRecord.mHandler.obtainMessage(UserHandler.MSG_UPDATE_CLIENT_USAGE,
+ userRecord.mClientRecords.get(i)).sendToTarget();
+ }
+ }
+ }
+
+ private void unregisterManagerLocked(IMediaRouter2ManagerClient client, boolean died) {
+ ManagerRecord clientRecord = mAllManagerRecords.remove(client.asBinder());
+ if (clientRecord != null) {
+ UserRecord userRecord = clientRecord.mUserRecord;
+ userRecord.mManagerRecords.remove(clientRecord);
+ clientRecord.dispose();
+ disposeUserIfNeededLocked(userRecord); // since client removed from user
+ }
+ }
+
+ private void setRemoteRouteLocked(IMediaRouter2ManagerClient client,
+ int uid, String routeId, boolean explicit) {
+ ManagerRecord managerRecord = mAllManagerRecords.get(client.asBinder());
+ if (managerRecord != null) {
+ if (explicit && managerRecord.mTrusted) {
+ Pair<Integer, String> obj = new Pair<>(uid, routeId);
+ managerRecord.mUserRecord.mHandler.obtainMessage(
+ UserHandler.MSG_SELECT_REMOTE_ROUTE, obj).sendToTarget();
+ }
+ }
+ }
+
private void requestSetVolumeLocked(IMediaRouterClient client,
String routeId, int volume) {
final IBinder binder = client.asBinder();
@@ -667,6 +818,46 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
+ final class ManagerRecord implements DeathRecipient {
+ public final UserRecord mUserRecord;
+ public final IMediaRouter2ManagerClient mClient;
+ public final int mUid;
+ public final int mPid;
+ public final String mPackageName;
+ public final boolean mTrusted;
+
+ ManagerRecord(UserRecord userRecord, IMediaRouter2ManagerClient client,
+ int uid, int pid, String packageName, boolean trusted) {
+ mUserRecord = userRecord;
+ mClient = client;
+ mUid = uid;
+ mPid = pid;
+ mPackageName = packageName;
+ mTrusted = trusted;
+ }
+
+ public void dispose() {
+ mClient.asBinder().unlinkToDeath(this, 0);
+ }
+
+ @Override
+ public void binderDied() {
+ clientDied(this);
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + this);
+
+ final String indent = prefix + " ";
+ pw.println(indent + "mTrusted=" + mTrusted);
+ }
+
+ @Override
+ public String toString() {
+ return "Client " + mPackageName + " (pid " + mPid + ")";
+ }
+ }
+
/**
* Information about a particular client of the media router.
* The contents of this object is guarded by mLock.
@@ -678,6 +869,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
public final int mPid;
public final String mPackageName;
public final boolean mTrusted;
+ public List<String> mControlCategories;
public int mRouteTypes;
public boolean mActiveScan;
@@ -728,7 +920,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
*/
final class UserRecord {
public final int mUserId;
- public final ArrayList<ClientRecord> mClientRecords = new ArrayList<ClientRecord>();
+ public final ArrayList<ClientRecord> mClientRecords = new ArrayList<>();
+ public final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>();
public final UserHandler mHandler;
public MediaRouterClientState mRouterState;
@@ -783,7 +976,9 @@ public final class MediaRouterService extends IMediaRouterService.Stub
*/
static final class UserHandler extends Handler
implements RemoteDisplayProviderWatcher.Callback,
- RemoteDisplayProviderProxy.Callback {
+ RemoteDisplayProviderProxy.Callback,
+ MediaRoute2ProviderWatcher.Callback,
+ MediaRoute2ProviderProxy.Callback {
public static final int MSG_START = 1;
public static final int MSG_STOP = 2;
public static final int MSG_UPDATE_DISCOVERY_REQUEST = 3;
@@ -794,6 +989,9 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private static final int MSG_UPDATE_CLIENT_STATE = 8;
private static final int MSG_CONNECTION_TIMED_OUT = 9;
+ private static final int MSG_SELECT_REMOTE_ROUTE = 10;
+ private static final int MSG_UPDATE_CLIENT_USAGE = 11;
+
private static final int TIMEOUT_REASON_NOT_AVAILABLE = 1;
private static final int TIMEOUT_REASON_CONNECTION_LOST = 2;
private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTING = 3;
@@ -809,11 +1007,17 @@ public final class MediaRouterService extends IMediaRouterService.Stub
private final MediaRouterService mService;
private final UserRecord mUserRecord;
private final RemoteDisplayProviderWatcher mWatcher;
+ private final MediaRoute2ProviderWatcher mMediaWatcher;
+
private final ArrayList<ProviderRecord> mProviderRecords =
new ArrayList<ProviderRecord>();
private final ArrayList<IMediaRouterClient> mTempClients =
new ArrayList<IMediaRouterClient>();
+ private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders =
+ new ArrayList<>();
+ private final ArrayList<IMediaRouter2ManagerClient> mTempManagers = new ArrayList<>();
+
private boolean mRunning;
private int mDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_NONE;
private RouteRecord mSelectedRouteRecord;
@@ -828,6 +1032,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mUserRecord = userRecord;
mWatcher = new RemoteDisplayProviderWatcher(service.mContext, this,
this, mUserRecord.mUserId);
+ mMediaWatcher = new MediaRoute2ProviderWatcher(service.mContext, this,
+ this, mUserRecord.mUserId);
}
@Override
@@ -869,6 +1075,15 @@ public final class MediaRouterService extends IMediaRouterService.Stub
connectionTimedOut();
break;
}
+ case MSG_SELECT_REMOTE_ROUTE: {
+ Pair<Integer, String> obj = (Pair<Integer, String>) msg.obj;
+ selectRemoteRoute(obj.first, obj.second);
+ break;
+ }
+ case MSG_UPDATE_CLIENT_USAGE: {
+ updateClientUsage((ClientRecord) msg.obj);
+ break;
+ }
}
}
@@ -900,6 +1115,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
if (!mRunning) {
mRunning = true;
mWatcher.start(); // also starts all providers
+ mMediaWatcher.start();
}
}
@@ -908,6 +1124,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mRunning = false;
unselectSelectedRoute();
mWatcher.stop(); // also stops all providers
+ mMediaWatcher.stop();
}
}
@@ -1039,6 +1256,26 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
+ @Override
+ public void addProvider(MediaRoute2ProviderProxy provider) {
+ provider.setCallback(this);
+ mMediaProviders.add(provider);
+ }
+
+ @Override
+ public void removeProvider(MediaRoute2ProviderProxy provider) {
+ mMediaProviders.remove(provider);
+ }
+
+ @Override
+ public void onProviderStateChanged(MediaRoute2ProviderProxy provider) {
+ updateProvider(provider);
+ }
+
+ private void updateProvider(MediaRoute2ProviderProxy provider) {
+ scheduleUpdateClientState();
+ }
+
/**
* This function is called whenever the state of the selected route may have changed.
* It checks the state and updates timeouts or unselects the route as appropriate.
@@ -1149,6 +1386,17 @@ public final class MediaRouterService extends IMediaRouterService.Stub
unselectSelectedRoute();
}
+ private void selectRemoteRoute(int uid, String routeId) {
+ if (routeId != null) {
+ final int providerCount = mMediaProviders.size();
+
+ //TODO: should find proper provider (currently assumes a single provider)
+ for (int i = 0; i < providerCount; ++i) {
+ mMediaProviders.get(i).setSelectedRoute(uid, routeId);
+ }
+ }
+ }
+
private void scheduleUpdateClientState() {
if (!mClientStateUpdateScheduled) {
mClientStateUpdateScheduled = true;
@@ -1166,6 +1414,15 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mProviderRecords.get(i).appendClientState(routerState);
}
+ //TODO: send provider info
+ int selectedUid = 0;
+ String selectedRouteId = null;
+ final int mediaCount = mMediaProviders.size();
+ for (int i = 0; i < mediaCount; i++) {
+ selectedUid = mMediaProviders.get(i).mSelectedUid;
+ selectedRouteId = mMediaProviders.get(i).mSelectedRouteId;
+ }
+
try {
synchronized (mService.mLock) {
// Update the UserRecord.
@@ -1176,6 +1433,11 @@ public final class MediaRouterService extends IMediaRouterService.Stub
for (int i = 0; i < count; i++) {
mTempClients.add(mUserRecord.mClientRecords.get(i).mClient);
}
+
+ final int count2 = mUserRecord.mManagerRecords.size();
+ for (int i = 0; i < count2; i++) {
+ mTempManagers.add(mUserRecord.mManagerRecords.get(i).mClient);
+ }
}
// Notify all clients (outside of the lock).
@@ -1187,9 +1449,39 @@ public final class MediaRouterService extends IMediaRouterService.Stub
Slog.w(TAG, "Failed to call onStateChanged. Client probably died.");
}
}
+ //TODO: Call proper callbacks when provider descriptor is implemented.
+ final int count2 = mTempManagers.size();
+ for (int i = 0; i < count2; i++) {
+ try {
+ mTempManagers.get(i).onRouteSelected(selectedUid, selectedRouteId);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to call onStateChanged. Manager probably died.", ex);
+ }
+ }
} finally {
// Clear the list in preparation for the next time.
mTempClients.clear();
+ mTempManagers.clear();
+ }
+ }
+
+ private void updateClientUsage(ClientRecord clientRecord) {
+ List<IMediaRouter2ManagerClient> managers = new ArrayList<>();
+ synchronized (mService.mLock) {
+ final int count = mUserRecord.mManagerRecords.size();
+ for (int i = 0; i < count; i++) {
+ managers.add(mUserRecord.mManagerRecords.get(i).mClient);
+ }
+ }
+ final int count = managers.size();
+ for (int i = 0; i < count; i++) {
+ try {
+ managers.get(i).onControlCategoriesChanged(clientRecord.mUid,
+ clientRecord.mControlCategories);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to call onControlCategoriesChanged. "
+ + "Manager probably died.", ex);
+ }
}
}
@@ -1576,4 +1868,5 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
}
+
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e43fc1f057b0..dddb7efca50b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4106,11 +4106,19 @@ public class NotificationManagerService extends SystemService {
if (r == null) {
return;
}
- if (mAssistants.isAdjustmentAllowed(adjustment.getKey())) {
- if (adjustment.getSignals() != null) {
- Bundle.setDefusable(adjustment.getSignals(), true);
- r.addAdjustment(adjustment);
+ if (adjustment.getSignals() != null) {
+ final Bundle adjustments = adjustment.getSignals();
+ Bundle.setDefusable(adjustments, true);
+ List<String> toRemove = new ArrayList<>();
+ for (String potentialKey : adjustments.keySet()) {
+ if (!mAssistants.isAdjustmentAllowed(potentialKey)) {
+ toRemove.add(potentialKey);
+ }
+ }
+ for (String removeKey : toRemove) {
+ adjustments.remove(removeKey);
}
+ r.addAdjustment(adjustment);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 66b530f19ed8..f1d4524cccac 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -476,6 +476,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mResolvedBaseFile.getAbsolutePath() : null;
info.progress = mProgress;
info.sealed = mSealed;
+ info.isCommitted = mCommitted;
info.active = mActiveCount.get() > 0;
info.mode = params.mode;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 73b000e7cbf1..1a33b1622a40 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1141,11 +1141,22 @@ public class PackageManagerService extends IPackageManager.Stub
switch (userStatus) {
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
if (!verified) {
- // updatedStatus is already UNDEFINED
- needUpdate = true;
-
- if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.d(TAG, "Formerly validated but now failing; demoting");
+ // Don't demote if sysconfig says 'always'
+ SystemConfig systemConfig = SystemConfig.getInstance();
+ ArraySet<String> packages = systemConfig.getLinkedApps();
+ if (!packages.contains(packageName)) {
+ // updatedStatus is already UNDEFINED
+ needUpdate = true;
+
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.d(TAG, "Formerly validated but now failing; demoting");
+ }
+ } else {
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.d(TAG, "Updating bundled package " + packageName
+ + " failed autoVerify, but sysconfig supersedes");
+ }
+ // leave needUpdate == false here intentionally
}
}
break;
@@ -17789,6 +17800,12 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public boolean isPackageDeviceAdminOnAnyUser(String packageName) {
final int callingUid = Binder.getCallingUid();
+ if (checkUidPermission(android.Manifest.permission.MANAGE_USERS, callingUid)
+ != PERMISSION_GRANTED) {
+ EventLog.writeEvent(0x534e4554, "128599183", -1, "");
+ throw new SecurityException(android.Manifest.permission.MANAGE_USERS
+ + " permission is required to call this API");
+ }
if (getInstantAppPackageName(callingUid) != null
&& !isCallerSameApp(packageName, callingUid)) {
return false;
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 0a17e1305f03..212df435adea 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -189,11 +189,8 @@ public final class DefaultPermissionGrantPolicy {
@Deprecated
private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>();
static {
- // STOPSHIP(b/112545973): remove once feature enabled by default
- if (!StorageManager.hasIsolatedStorage()) {
- STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
- STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
- }
+ STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
private static final Set<String> MEDIA_AURAL_PERMISSIONS = new ArraySet<>();
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 40f2a2b9dcc2..3029f51d4e09 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1666,18 +1666,6 @@ public class PermissionManagerService {
for (int i = 0; i < numPerms; i++) {
String permission = pkg.requestedPermissions.get(i);
- int op = permissionToOpCode(permission);
- if (op == OP_NONE) {
- continue;
- }
-
- // Runtime permissions are per uid, not per package, hence per package app-op
- // modes should never have been set. It is possible to set them via the shell
- // though. Revert such settings during boot to get the device back into a good
- // state.
- LocalServices.getService(AppOpsManagerInternal.class).setAllPkgModesToDefault(
- op, getUid(userId, getAppId(pkg.applicationInfo.uid)));
-
// For pre-M apps the runtime permission do not store the state
if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
continue;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 55af3571f63a..1c5c7a38e334 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3807,6 +3807,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
case KeyEvent.KEYCODE_POWER: {
+ Slog.d(TAG, "interceptKeyBeforeQueueing: KEYCODE_POWER "
+ + KeyEvent.actionToString(event.getAction())
+ + " mPowerKeyHandled=" + mPowerKeyHandled + " b/128933363");
// Any activity on the power button stops the accessibility shortcut
cancelPendingAccessibilityShortcutAction();
result &= ~ACTION_PASS_TO_USER;
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 18004336e7a2..28a853ff6767 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -1724,7 +1724,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
throw new IllegalStateException("mKernelCpuThreadReader is null");
}
ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages =
- this.mKernelCpuThreadReader.getProcessCpuUsageByUids();
+ this.mKernelCpuThreadReader.getProcessCpuUsage();
if (processCpuUsages == null) {
throw new IllegalStateException("processCpuUsages is null");
}
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index bbbf11d2a7a2..9f7cb3d35ecb 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -49,7 +49,7 @@ class AppWindowThumbnail implements Animatable {
private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM;
private final AppWindowToken mAppToken;
- private final SurfaceControl mSurfaceControl;
+ private SurfaceControl mSurfaceControl;
private final SurfaceAnimator mSurfaceAnimator;
private final int mWidth;
private final int mHeight;
@@ -68,10 +68,21 @@ class AppWindowThumbnail implements Animatable {
*/
AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
boolean relative) {
+ this(t, appToken, thumbnailHeader, relative, new Surface(), null);
+ }
+
+ AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
+ boolean relative, Surface drawSurface, SurfaceAnimator animator) {
mAppToken = appToken;
mRelative = relative;
- mSurfaceAnimator =
+ if (animator != null) {
+ mSurfaceAnimator = animator;
+ } else {
+ // We can't use a delegating constructor since we need to
+ // reference this::onAnimationFinished
+ mSurfaceAnimator =
new SurfaceAnimator(this, this::onAnimationFinished, appToken.mWmService);
+ }
mWidth = thumbnailHeader.getWidth();
mHeight = thumbnailHeader.getHeight();
@@ -95,7 +106,6 @@ class AppWindowThumbnail implements Animatable {
}
// Transfer the thumbnail to the surface
- Surface drawSurface = new Surface();
drawSurface.copyFrom(mSurfaceControl);
drawSurface.attachAndQueueBuffer(thumbnailHeader);
drawSurface.release();
@@ -145,6 +155,7 @@ class AppWindowThumbnail implements Animatable {
void destroy() {
mSurfaceAnimator.cancelAnimation();
getPendingTransaction().remove(mSurfaceControl);
+ mSurfaceControl = null;
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 58055e58fce3..5a9ca0f88287 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -353,8 +353,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
// Verify DPM gets notified about new device lock
mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
- PasswordMetrics metric = PasswordMetrics.computeForPassword(pattern);
- metric.quality = PASSWORD_QUALITY_SOMETHING;
+ final PasswordMetrics metric = PasswordMetrics.computeForCredential(
+ LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern);
verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 426122a830f1..987d46a697c2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -40,6 +40,8 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION_CODES.O_MR1;
import static android.os.Build.VERSION_CODES.P;
+import static android.service.notification.Adjustment.KEY_IMPORTANCE;
+import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
@@ -492,6 +494,19 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
return answers;
}
+ private void clearDeviceConfig() {
+ DeviceConfig.resetToDefaults(
+ Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
+ }
+
+ private void setDefaultAssistantInDeviceConfig(String componentName) {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
+ componentName,
+ false);
+ }
+
@Test
public void testCreateNotificationChannels_SingleChannel() throws Exception {
final NotificationChannel channel =
@@ -831,7 +846,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.addEnqueuedNotification(r);
Bundle bundle = new Bundle();
- bundle.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE);
+ bundle.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Adjustment adjustment = new Adjustment(
r.sbn.getPackageName(), r.getKey(), bundle, "", r.getUser().getIdentifier());
mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
@@ -2826,7 +2841,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.setHandler(handler);
Bundle signals = new Bundle();
- signals.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE);
+ signals.putInt(KEY_IMPORTANCE, IMPORTANCE_NONE);
Adjustment adjustment = new Adjustment(
r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
@@ -2867,7 +2882,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Bundle signals = new Bundle();
- signals.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_LOW);
+ signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Adjustment adjustment = new Adjustment(
r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
@@ -2885,13 +2900,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
Bundle signals = new Bundle();
- signals.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_LOW);
+ signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
Adjustment adjustment = new Adjustment(
r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
assertEquals(IMPORTANCE_DEFAULT, r.getImportance());
- assertFalse(r.hasAdjustment(Adjustment.KEY_IMPORTANCE));
+ assertFalse(r.hasAdjustment(KEY_IMPORTANCE));
}
@Test
@@ -4275,18 +4290,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.onGranted(eq(xmlConfig), eq(0), eq(true));
}
- private void clearDeviceConfig() {
- DeviceConfig.resetToDefaults(
- Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
- }
- private void setDefaultAssistantInDeviceConfig(String componentName) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
- componentName,
- false);
- }
public void testGetAllowedAssistantCapabilities() throws Exception {
List<String> capabilities = mBinderService.getAllowedAssistantCapabilities(null);
@@ -4301,4 +4305,23 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertFalse(currentCapabilities.contains(capability));
}
}
+
+ public void testAdjustRestrictedKey() throws Exception {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+
+ when(mAssistants.isAdjustmentAllowed(KEY_IMPORTANCE)).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowed(KEY_USER_SENTIMENT)).thenReturn(false);
+
+ Bundle signals = new Bundle();
+ signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
+ signals.putInt(KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
+ Adjustment adjustment = new Adjustment(r.sbn.getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+
+ mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+ r.applyAdjustments();
+
+ assertEquals(IMPORTANCE_LOW, r.getAssistantImportance());
+ assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
index febb79540fea..380f7c67402e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
@@ -22,12 +22,11 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
-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/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 9bd993070939..b1ffbbd4ffba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -24,9 +24,9 @@ import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
new file mode 100644
index 000000000000..fa0c384ca89d
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Test class for {@link TaskSnapshotSurface}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTest:AppWindowThumbnailTest
+ *
+ */
+@SmallTest
+@Presubmit
+public class AppWindowThumbnailTest extends WindowTestsBase {
+ private AppWindowThumbnail buildThumbnail() {
+ final GraphicBuffer buffer = GraphicBuffer.create(1, 1, PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+ final AppWindowToken mockAwt = mock(AppWindowToken.class);
+ when(mockAwt.getPendingTransaction()).thenReturn(new StubTransaction());
+ when(mockAwt.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
+ return new AppWindowThumbnail(new StubTransaction(), mockAwt,
+ buffer, false, mock(Surface.class), mock(SurfaceAnimator.class));
+ }
+
+ @Test
+ public void testDestroy_nullsSurface() {
+ final AppWindowThumbnail t = buildThumbnail();
+ assertNotNull(t.getSurfaceControl());
+ t.destroy();
+ assertNull(t.getSurfaceControl());
+ }
+}
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 a166444ce871..4e906bc9b6c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
@@ -18,11 +18,10 @@ package com.android.server.wm;
import static com.google.common.truth.Truth.assertWithMessage;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertSame;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import android.os.SystemClock;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 1c6afd545b1f..3bedabc45c00 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -18,8 +18,8 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import android.platform.test.annotations.Presubmit;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 792e8a6f7582..113f3c8e237c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -23,7 +23,7 @@ import static android.view.WindowManager.TRANSIT_UNSET;
import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_APP_THEME;
import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_REAL;
-import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 8854edef9994..a91daf0c7647 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -16,9 +16,8 @@
package com.android.server.wm;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertTrue;
-import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5df7bf717aed..d5245e30f2a4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1321,7 +1321,7 @@ public class TelephonyManager {
/**
* An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} to indicate the
- * subscription which has changed.
+ * subscription which has changed; or in general whenever a subscription ID needs specified.
*/
public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID";
@@ -1439,13 +1439,24 @@ public class TelephonyManager {
/**
* Integer intent extra to be used with {@link #ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED}
- * to indicate whether a SIM selection is needed to choose default subscription.
+ * to indicate what type of SIM selection is needed.
*
* @hide
*/
public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE =
"android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
+ /** @hide */
+ @IntDef({
+ EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE,
+ EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA,
+ EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE,
+ EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS,
+ EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DefaultSubscriptionSelectType{}
+
/**
* Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE}
* to indicate there's no need to re-select any default subscription.
@@ -1477,20 +1488,11 @@ public class TelephonyManager {
/**
* Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE}
* to indicate user to decide whether current SIM should be preferred for all
- * data / voice / sms.
- * @hide
- */
- public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES = 4;
-
- /**
- * Integer intent extra to be used with
- * {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES}
- * to indicate which SIM is being selected.
- *
+ * data / voice / sms. {@link #EXTRA_SUBSCRIPTION_ID} will specified to indicate
+ * which subscription should be the default subscription.
* @hide
*/
- public static final String EXTRA_DEFAULT_SUBSCRIPTION_ID =
- "android.telephony.extra.DEFAULT_SUBSCRIPTION_ID";
+ public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4;
//
//
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 4886a3f8f141..d93e58254b95 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -123,6 +123,19 @@ public final class TelephonyPermissions {
context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
}
+ /**
+ * Check whether the calling packages has carrier privileges for the passing subscription.
+ * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
+ */
+ public static boolean checkCarrierPrivilegeForSubId(int subId) {
+ if (SubscriptionManager.isValidSubscriptionId(subId)
+ && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid())
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
+ return false;
+ }
+
@VisibleForTesting
public static boolean checkReadPhoneState(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
@@ -204,9 +217,7 @@ public final class TelephonyPermissions {
}
// Calling packages with carrier privileges will also have access to device identifiers, but
// this may be removed in a future release.
- if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(
- TELEPHONY_SUPPLIER, subId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ if (checkCarrierPrivilegeForSubId(subId)) {
return true;
}
// else the calling package is not authorized to access the device identifiers; call
@@ -243,9 +254,7 @@ public final class TelephonyPermissions {
}
// If the calling package has carrier privileges then allow access to the subscriber
// identifiers.
- if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(
- TELEPHONY_SUPPLIER, subId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ if (checkCarrierPrivilegeForSubId(subId)) {
return true;
}
return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
@@ -365,9 +374,7 @@ public final class TelephonyPermissions {
uid) == PackageManager.PERMISSION_GRANTED) {
return false;
}
- if (SubscriptionManager.isValidSubscriptionId(subId)
- && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ if (checkCarrierPrivilegeForSubId(subId)) {
return false;
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1151214418df..e881ad4a5620 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -212,7 +212,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -4022,8 +4021,13 @@ public class ConnectivityServiceTest {
callback3.expectStopped();
}
+ @FunctionalInterface
+ private interface ThrowingConsumer<T> {
+ void accept(T t) throws Exception;
+ }
+
// Helper method to prepare the executor and run test
- private void runTestWithSerialExecutors(Consumer<Executor> functor) {
+ private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
final Executor executorInline = (Runnable r) -> r.run();
functor.accept(executorSingleThread);
@@ -4032,15 +4036,9 @@ public class ConnectivityServiceTest {
}
@Test
- public void testNattSocketKeepalives() {
- runTestWithSerialExecutors(executor -> {
- try {
- doTestNattSocketKeepalivesWithExecutor(executor);
- doTestNattSocketKeepalivesFdWithExecutor(executor);
- } catch (Exception e) {
- fail(e.getMessage());
- }
- });
+ public void testNattSocketKeepalives() throws Exception {
+ runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
+ runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
}
private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
@@ -4210,14 +4208,8 @@ public class ConnectivityServiceTest {
}
@Test
- public void testTcpSocketKeepalives() {
- runTestWithSerialExecutors(executor -> {
- try {
- doTestTcpSocketKeepalivesWithExecutor(executor);
- } catch (Exception e) {
- fail(e.getMessage());
- }
- });
+ public void testTcpSocketKeepalives() throws Exception {
+ runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
}
private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/CoreTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index 1a81c2c9fd41..e0d74e0908ee 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/CoreTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -26,23 +26,25 @@ import com.android.test.filters.SelectTest;
* <p>Use this filter when running FrameworksCoreTests as
* <pre>
* adb shell am instrument -w \
- * -e filter com.android.server.wm.test.filters.CoreTestsFilter \
+ * -e filter com.android.server.wm.test.filters.FrameworksTestsFilter \
* -e selectTest_verbose true \
* com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
* </pre>
*/
-public final class CoreTestsFilter extends SelectTest {
+public final class FrameworksTestsFilter extends SelectTest {
- private static final String[] SELECTED_CORE_TESTS = {
+ private static final String[] SELECTED_TESTS = {
+ // Test specifications for FrameworksCoreTests.
"android.app.servertransaction.", // all tests under the package.
"android.view.DisplayCutoutTest",
+ "android.view.InsetsAnimationControlImplTest",
"android.view.InsetsControllerTest",
"android.view.InsetsSourceTest",
"android.view.InsetsSourceConsumerTest",
"android.view.InsetsStateTest",
};
- public CoreTestsFilter(Bundle testArgs) {
- super(addSelectTest(testArgs, SELECTED_CORE_TESTS));
+ public FrameworksTestsFilter(Bundle testArgs) {
+ super(addSelectTest(testArgs, SELECTED_TESTS));
}
}
diff --git a/tools/bit/main.cpp b/tools/bit/main.cpp
index 0f555b11d30f..1a91f52bc6cf 100644
--- a/tools/bit/main.cpp
+++ b/tools/bit/main.cpp
@@ -856,7 +856,7 @@ run_phases(vector<Target*> targets, const Options& options)
// TODO: if (!apk.file.fileInfo.exists || apk.file.HasChanged())
err = run_adb("shell", "mkdir", "-p", dir.c_str(), NULL);
check_error(err);
- err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str());
+ err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str(), NULL);
check_error(err);
// pushed.installed = true;
}